本文实例介绍了android实现2048小游戏的相关代码,分享给大家供大家参考,具体内容如下
根据界面,主要实现4*4的格子方块比较麻烦,其他的都挺简单的.总体为实现4*4的格子,自定义gridlayout,并在其中添加触摸监听事件,进行一系列的操作,从而实现游戏的逻辑,最后再添加动画效果即可完成.
下面是设计思路:
一.gameview的设计
首先自定义一个类,继承gridlayout,添加两个构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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轴的偏移量的比较
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
//初始化变量的方法 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,这个时候代表是空值,也就是空卡片.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
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()函数,这个在程序打开的时候运行一次,通过他来动态设计卡片大小,并且添加卡片和开始游戏.
1
2
3
4
5
6
7
8
|
@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,也就是全部添加空卡片
1
2
3
4
5
6
7
8
9
10
11
12
|
//添加卡片 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
1
2
3
4
5
6
7
8
9
10
11
|
//开始游戏 public void startgame(){ for ( int y = 0 ;y< 4 ;y++){ for ( int x = 0 ;x< 4 ;x++){ cardmap[y][x].setnum( 0 ); } } addrandomcard(); addrandomcard(); } |
随机添加卡片设计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//添加随机卡片 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 ? 2 : 4 ); mainactivity.getmainactivity().getanimlayer().createscaleto1(cardmap[p.x][p.y]); } |
这样大体框架就设计好了
接下来是滑动事件,这里只举例左滑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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(); } } |
每次添加卡片还需要判断是否结束游戏
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
//结束游戏 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中实例化当前这个类,然后可以操作其方法,然后通过滑动来设置动画
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
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); } } |
最后主布局文件如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
<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> |
以上就是本文的全部内容,希望对大家的学习有所帮助。