本文实例介绍了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>
|
以上就是本文的全部内容,希望对大家的学习有所帮助。