Android實現2048小游戲,android小游戲源代碼

9
回復
824
查看
打印 上一主題 下一主題
[復制鏈接]

497

主題

1166

帖子

1040

安幣

手工藝人

樓主
發表于 2018-1-29 15:24:11 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

            

        本文實例介紹了android實現2048小游戲的相關代碼,分享給大家供大家參考,具體內容如下

        

        根據界面,主要實現4*4的格子方塊比較麻煩,其他的都挺簡單的.總體為實現4*4的格子,自定義gridlayout,并在其中添加觸摸監聽事件,進行一系列的操作,從而實現游戲的邏輯,最后再添加動畫效果即可完成.
下面是設計思路:

        一.gameview的設計

        首先自定義一個類,繼承gridlayout,添加兩個構造方法

[Java] 查看源文件 復制代碼
public class gameview extends gridlayout {

  //兩個必要的構造方法
  public gameview(context context) {
    super(context);
    initview();
  }

  public gameview(context context, attributeset attrs) {
    super(context, attrs);
    initview();
  }
  }

        接下來在initview()中實現設置gridlayout為四列,并且添加觸摸事件監聽.(監聽方法還可以重寫ontouchevent(),返回值為true即可),判斷觸摸方向,主要是通過x軸和y軸的偏移量的比較

[Java] 查看源文件 復制代碼
 //初始化變量的方法
  public void initview(){
    //設置只有四列
    setcolumncount(4);
    //設置監聽事件
    setontouchlistener(new ontouchlistener() {
      @override
      public boolean ontouch(view v, motionevent event) {
        switch (event.getaction()) {
          case motionevent.action_down:
            setx = event.getx();
            sety = event.gety();
            break;
          case motionevent.action_up:
            offsetx = event.getx() - setx;
            offsety = event.gety() - sety;
            //判斷滑動方向
            if (math.abs(offsetx) >= math.abs(offsety)) {
              if (offsetx > 0) {
                swipright();
              } else if (offsetx < 0) {
                swipleft();
              }
            } else {
              if (offsety > 0) {
                swipdown();
              } else if (offsety < 0) {
                swipup();
              }
            }

            break;
        }

        return true;
      }
    });
  }

        監聽事件實現后先放在那里,接下來把4*4的里面每個小格子設計成小卡片,每個卡片就是一個textview,卡片設計很簡單,需要什么就添加什么,默認數字為0,這個時候代表是空值,也就是空卡片.

        

[Java] 查看源文件 復制代碼
public class card extends framelayout {

  public card(context context) {
    super(context);
    tvcard = new textview(getcontext());
    tvcard.settextsize(40f);
    tvcard.setgravity(gravity.center);
    layoutparams lp = new layoutparams(-1,-1);
    lp.setmargins(15,15,0,0);
    addview(tvcard, lp);
  }
  //卡片上的數字
  private int num;
  private boolean is2048 = true;
  private void judgeis2048(int num){
    if (is2048){
      if (2048==num){
        toast.maketext(getcontext(),"恭喜趙瑩達到2048",toast.length_long).show();
        is2048 = false;
      }
    }
  }
  public int getnum() {
    return num;
  }

  public void setnum(int num) {
    this.num = num;
    if (num<=0){
      tvcard.settext("");
    }else {
    //這里傳進去的是字符串因此需要加上空字符
      tvcard.settext(num+"");
    }
    switch (num) {
      case 0:
        tvcard.setbackgroundcolor(0x33ffffff);
        break;
      case 2:
        tvcard.setbackgroundcolor(0xffeee4da);
        break;
      case 4:
        tvcard.setbackgroundcolor(0xffede0c8);
        break;
      case 8:
        tvcard.setbackgroundcolor(0xfff2b179);
        break;
      case 16:
        tvcard.setbackgroundcolor(0xfff59563);
        break;
      case 32:
        tvcard.setbackgroundcolor(0xfff67c5f);
        break;
      case 64:
        tvcard.setbackgroundcolor(0xfff65e3b);
        break;
      case 128:
        tvcard.setbackgroundcolor(0xffedcf72);
        break;
      case 256:
        tvcard.setbackgroundcolor(0xffedcc61);
        break;
      case 512:
        tvcard.setbackgroundcolor(0xffedc850);
        break;
      case 1024:
        tvcard.setbackgroundcolor(0xffedc53f);
        break;
      case 2048:
        tvcard.setbackgroundcolor(0xffedc22e);
        break;
      default:
        tvcard.setbackgroundcolor(0xff3c3a32);
        break;
    }
    judgeis2048(num);
  }


  //判斷是否相等,用于合并
  public boolean equals(card o) {
    return getnum()==o.getnum();
  }

  //用于顯示數字
  private textview tvcard;

  public textview gettvcard() {
    return tvcard;
  }
}

        卡片設計就需要添加到gameview里面,這個時候重寫onsizechanged()函數,這個在程序打開的時候運行一次,通過他來動態設計卡片大小,并且添加卡片和開始游戲.

[Java] 查看源文件 復制代碼
@override
  protected void onsizechanged(int w, int h, int oldw, int oldh) {
    super.onsizechanged(w, w, oldw, oldh);
    config.card_width = (math.min(w,h)-10)/4;
    addcard(config.card_width);
    startgame();

  }

        添加卡片,一開始全設置為0,也就是全部添加空卡片

[Java] 查看源文件 復制代碼
 //添加卡片
  private void addcard(int card_width){
    card c;
    for (int x = 0;x<4;x++){
      for (int y = 0;y<4;y++){
        c = new card(getcontext());
        c.setnum(0);
        addview(c, card_width, card_width);
        cardmap[y][x] = c;
      }
    }
  }

        游戲開始需要隨機添加兩張卡片,數值2或者4,出現比率9:1

[Java] 查看源文件 復制代碼
//開始游戲
  public void startgame(){

    for (int y = 0;y<4;y++){
      for (int x = 0;x<4;x++){
        cardmap[y][x].setnum(0);
      }
    }
    addrandomcard();
    addrandomcard();
  }

        隨機添加卡片設計

[Java] 查看源文件 復制代碼
//添加隨機卡片
  private void addrandomcard(){
    cardpoint.clear();
    for (int y = 0;y<4;y++){
      for (int x = 0;x<4;x++){
        if (cardmap[x][y].getnum()<=0){
          cardpoint.add(new point(x,y));
        }
      }
    }
    //把一張空卡片換成帶數字的
    point p = cardpoint.remove((int)(math.random()*cardpoint.size()));
    cardmap[p.x][p.y].setnum(math.random()>0.1[p.x][p.y]);

}

        這樣大體框架就設計好了
接下來是滑動事件,這里只舉例左滑

[Java] 查看源文件 復制代碼
private void swipleft(){
    boolean status = false;
    for (int y = 0; y < 4; y++) {
      for (int x = 0; x < 4; x++) {

        for (int x1 = x+1; x1 < 4; x1++) {
          if (cardmap[x1][y].getnum()>0) {

            if (cardmap[x][y].getnum()<=0) {

              mainactivity.getmainactivity().getanimlayer().createmoveanim(cardmap[x1][y],cardmap[x][y], x1, x, y, y);
              cardmap[x][y].setnum(cardmap[x1][y].getnum());
              cardmap[x1][y].setnum(0);
              x--;
              status = true;
            }else if (cardmap[x][y].equals(cardmap[x1][y])) {
              mainactivity.getmainactivity().getanimlayer().createmoveanim(cardmap[x1][y], cardmap[x][y],x1, x, y, y);
              cardmap[x][y].setnum(cardmap[x][y].getnum() * 2);
              cardmap[x1][y].setnum(0);
              mainactivity.getmainactivity().addscore(cardmap[x][y].getnum());
              status = true;
            }
            break;
          }
        }
      }
    }
    if (status){
      addrandomcard();
      checkgame();
    }
  }

        每次添加卡片還需要判斷是否結束游戲

[Java] 查看源文件 復制代碼
//結束游戲
  private void checkgame(){
    boolean complete = true;

    all:
    for (int y = 0; y < 4; y++) {
      for (int x = 0; x < 4; x++) {
        if (cardmap[x][y].getnum()==0||
            (x>0&&cardmap[x][y].equals(cardmap[x-1][y]))||
            (x<3&&cardmap[x][y].equals(cardmap[x+1][y]))||
            (y>0&&cardmap[x][y].equals(cardmap[x][y-1]))||
            (y<3&&cardmap[x][y].equals(cardmap[x][y+1]))) {

          complete = false;
          break all;
        }
      }
    }

    if (complete) {
      toast.maketext(getcontext(), "游戲結束" + mainactivity.getmainactivity().getscore(), toast.length_long).show();
    }
  }

        設計總體上框架就是上面說的那些.

        二.動畫效果

        動畫效果主要是創建,移動,合并這三個效果,因此重寫個繼承framelayout的class,覆蓋到游戲界面上,這樣的目的可以通過mainactivity中實例化當前這個類,然后可以操作其方法,然后通過滑動來設置動畫

[Java] 查看源文件 復制代碼
public class animlayer extends framelayout {

  public animlayer(context context, attributeset attrs, int defstyle) {
    super(context, attrs, defstyle);
  }

  public animlayer(context context, attributeset attrs) {
    super(context, attrs);
  }

  public animlayer(context context) {
    super(context);
  }



  public void createmoveanim(final card from,final card to,int fromx,int tox,int fromy,int toy){

    final card c = getcard(from.getnum());

    layoutparams lp = new layoutparams(config.card_width, config.card_width);
    lp.leftmargin = fromx*config.card_width;
    lp.topmargin = fromy*config.card_width;
    c.setlayoutparams(lp);

    if (to.getnum()<=0) {
      to.gettvcard().setvisibility(view.invisible);
    }
    translateanimation ta = new translateanimation(0, config.card_width*(tox-fromx), 0, config.card_width*(toy-fromy));
    ta.setduration(100);
    ta.setanimationlistener(new animation.animationlistener() {

      @override
      public void onanimationstart(animation animation) {}

      @override
      public void onanimationrepeat(animation animation) {}

      @override
      public void onanimationend(animation animation) {
        to.gettvcard().setvisibility(view.visible);
        recyclecard(c);
      }
    });
    c.startanimation(ta);
  }

  private card getcard(int num){
    card c;
    if (cards.size()>0) {
      c = cards.remove(0);
    }else{
      c = new card(getcontext());
      addview(c);
    }
    c.setvisibility(view.visible);
    c.setnum(num);
    return c;
  }
  private void recyclecard(card c){
    c.setvisibility(view.invisible);
    c.setanimation(null);
    cards.add(c);
  }
  private list<card> cards = new arraylist<card>();

  public void createscaleto1(card target){
    scaleanimation sa = new scaleanimation(0.1f, 1, 0.1f, 1, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f);
    sa.setduration(100);
    target.setanimation(null);
    target.gettvcard().startanimation(sa);
  }

}

        最后主布局文件如下

[Java] 查看源文件 復制代碼
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#fffaf8ef"
  android:orientation="vertical"
  android:paddingbottom="@dimen/activity_vertical_margin"
  android:paddingleft="@dimen/activity_horizontal_margin"
  android:paddingright="@dimen/activity_horizontal_margin"
  android:paddingtop="@dimen/activity_vertical_margin"
  tools:context=".mainactivity">
  <linearlayout
    android:layout_margintop="15dp"
    android:orientation="horizontal"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <textview
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textcolor="#ff776e65"
      android:text="@string/title"
      android:textsize="50sp"/>
  </linearlayout>

  <linearlayout
    android:layout_width="match_parent"
    android:orientation="horizontal"
    android:layout_margintop="10dp"
    android:layout_height="wrap_content">

    <textview
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textcolor="#ff776e65"
      android:layout_marginleft="30dp"
      android:textsize="35sp"
      android:text="@string/score"/>
    <textview
      android:id="@+id/tvscore"
      android:layout_marginleft="20dp"
      android:textsize="25sp"
      android:textcolor="#ff776e65"
      android:layout_width="70dp"
      android:layout_height="37dp"
      />
    <button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/startgame"
      android:layout_marginleft="40dp"
      android:background="#ffbbada0"
      android:textsize="15sp"
      android:text="@string/start"/>

  </linearlayout>
  <framelayout
    android:id="@+id/gamecontainer"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1">
  <develop.niuli.com.game.gameview
    android:layout_margintop="40dp"
    android:id="@+id/gridlayout"
    android:layout_width="match_parent"
    android:background="#ffbbada0"
    android:layout_height="350dp">

  </develop.niuli.com.game.gameview>

  <develop.niuli.com.game.animlayer
    android:id="@+id/animlayer"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  </develop.niuli.com.game.animlayer>

  </framelayout>

</linearlayout>



        
分享到:  QQ好友和群 QQ空間 微信
收藏
收藏0
支持
支持0
反對
反對0
沙發
發表于 2018-1-29 20:32:51 | 只看該作者
感謝大神~

0

主題

9200

帖子

2067

安幣

Android大神

Rank: 6Rank: 6

板凳
發表于 2018-1-30 04:39:11 | 只看該作者
感謝分享,樓主V5~

17

主題

9246

帖子

2337

安幣

Android大神

Rank: 6Rank: 6

地板
發表于 2018-1-30 13:47:57 | 只看該作者
感覺樓主很用心,辛苦啦~

0

主題

9809

帖子

1669

安幣

Android大神

IT

Rank: 6Rank: 6

5#
發表于 2018-1-30 22:49:16 | 只看該作者
樓主是好人,回個帖會有安幣嗎?

6

主題

9492

帖子

2877

安幣

Android大神

Rank: 6Rank: 6

6#
發表于 2018-1-31 15:10:00 | 只看該作者
支持,感謝,祝巴士越來越好~

0

主題

9375

帖子

2413

安幣

Android大神

Rank: 6Rank: 6

7#
發表于 2018-2-1 05:51:59 | 只看該作者
支持,感謝,祝巴士越來越好~

0

主題

316

帖子

3513

安幣

碼皇(巴士元老)

Rank: 8Rank: 8

8#
發表于 2018-4-19 17:12:44 | 只看該作者
樓主威武啊,安卓巴士有你更給力!
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

两码中特期期