【Android 2d 游戏开发(2)】——2048
来源:互联网 发布:unity3d arduino 编辑:程序博客网 时间:2024/05/18 22:14
实现效果 :
代码结构:
完整代码:
MainActivity:
package com.next.next2048;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); //全屏 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(new GameView(this)); }}
Tile:
package com.next.next2048;
/**
* Created by Next on 2016/3/17 0017.
*/
public class Tile {
private int number;
private int x,y;
public Tile(int x,int y,int number){
this.x = x;
this.y = y;
this.number = number;
}
public int getY() { return y;}public void setY(int y) { this.y = y;}public int getX() { return x;}public void setX(int x) { this.x = x;}public int getNumber() { return number;}public void setNumber(int number) { this.number = number;}
}
GameView:
package com.next.next2048;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.view.MotionEvent;import android.view.View;import java.util.ArrayList;import java.util.Random;/** * Created by Next on 2016/3/17 0017. */public class GameView extends View { enum GameState { Menu, Playing, Over } GameState gameState = GameState.Menu; public static final int MAX_X = 4; public static final int MAX_Y = 4; int tWidth;//tile宽度 int scrW;//屏幕宽 int scrH;//屏幕高 int offsetX;//偏移x int offsetY;//偏移y,用于调整游戏区域在屏幕中的位置 Paint paint; Tile[][] tiles;//Tile集合 Random random; ArrayList<Tile> zeroList; float downX, downY, upX, upY; public GameView(Context context) { super(context); scrW = ((MainActivity) context).getWindowManager().getDefaultDisplay().getWidth(); scrH = ((MainActivity) context).getWindowManager().getDefaultDisplay().getHeight(); offsetX = 30; offsetY = (scrH - scrW) / 2;//使棋盘位于屏幕中央 tWidth = (scrW - offsetX * 2) / MAX_X; paint = new Paint(); tiles = new Tile[MAX_X][MAX_Y]; setKeepScreenOn(true);//保持屏幕常亮 random = new Random(); zeroList = new ArrayList<Tile>(); } private void newGame() { for (int x = 0; x < MAX_X; x++) { for (int y = 0; y < MAX_Y; y++) { tiles[x][y] = new Tile(x, y, 0); } } newTile(); newTile(); } private void newTile() { zeroList.removeAll(zeroList); for (int x = 0; x < MAX_X; x++) { for (int y = 0; y < MAX_Y; y++) { if (tiles[x][y].getNumber() == 0) { zeroList.add(tiles[x][y]); } } } int size = zeroList.size(); if (size > 0) { //出现4的概率是20%,出现2的概率是80% if (random.nextInt(5) == 0) { zeroList.get(random.nextInt(size)).setNumber(4); } else { zeroList.get(random.nextInt(size)).setNumber(2); } } else { return; } } @Override protected void onDraw(Canvas canvas) { switch (gameState) { case Menu: menuDraw(canvas); break; case Playing: playingDraw(canvas); break; case Over: overDraw(canvas); break; default: break; } } private void menuDraw(Canvas canvas) { canvas.drawColor(Color.WHITE); paint.setColor(Color.BLACK); paint.setTextAlign(Paint.Align.CENTER); paint.setTextSize(tWidth / 2); canvas.drawText("2048", scrW / 2, scrH / 4, paint); canvas.drawText("Touch me", scrW / 2, scrH / 2, paint); } private void playingDraw(Canvas canvas) { canvas.drawColor(Color.WHITE); //画主游戏区域 paint.setColor(Color.BLACK); paint.setStrokeWidth(10); for (int x = 0; x < MAX_X + 1; x++) { canvas.drawLine(offsetX + x * tWidth, offsetY, offsetX + x * tWidth, offsetY + tWidth * MAX_Y, paint); } for (int y = 0; y < MAX_Y + 1; y++) { canvas.drawLine(offsetX, offsetY + y * tWidth, offsetX + MAX_X * tWidth, offsetY + y * tWidth, paint); } for (int x = 0; x < MAX_X; x++) { for (int y = 0; y < MAX_Y; y++) { if (tiles[x][y].getNumber() != 0) { switch (tiles[x][y].getNumber()){ case 2: paint.setColor(0xffff6666); break; case 4: paint.setColor(0xffff9900); break; case 8: paint.setColor(0xff99CC33); break; case 16: paint.setColor(0xff33CC99); break; case 32: paint.setColor(0xff666699); break; case 64: paint.setColor(0xff339933); break; case 128: paint.setColor(0xff0099CC); break; case 256: paint.setColor(0xff660033); break; case 512: paint.setColor(0xff006633); break; case 1024: paint.setColor(0xff660099); break; case 2048: paint.setColor(0xffff0033); break; case 4096: paint.setColor(0xff333333); break; case 8192: paint.setColor(0xff000000); break; default: paint.setColor(0xff000000); break; } canvas.drawText(tiles[x][y].getNumber() + "", offsetX + x * tWidth + tWidth / 2, offsetY + y * tWidth + tWidth * 3 / 4, paint); } } } } private void overDraw(Canvas canvas) { int max = 0; for (int x = 0; x < MAX_X; x++) { for (int y = 0; y < MAX_Y; y++) { if (tiles[x][y].getNumber() > max) { max = tiles[x][y].getNumber(); } } } canvas.drawColor(Color.WHITE); paint.setColor(Color.BLACK); paint.setTextAlign(Paint.Align.CENTER); paint.setTextSize(tWidth / 2); canvas.drawText("Top:" + max, scrW / 2, scrH / 4, paint); canvas.drawText("Try again", scrW / 2, scrH / 2, paint); } @Override public boolean onTouchEvent(MotionEvent event) { switch (gameState) { case Menu: menuLogic(event); break; case Playing: playingLoic(event); break; case Over: overLogic(event); break; } return true; } private void menuLogic(MotionEvent event) { if (event.getX() > 0) { gameState = GameState.Playing; newGame(); invalidate(); } } private void playingLoic(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { downX = event.getX(); downY = event.getY(); } else if (event.getAction() == MotionEvent.ACTION_UP) { upX = event.getX(); upY = event.getY(); float moveX = upX - downX; float moveY = upY - downY; if (Math.abs(moveX) > Math.abs(moveY)) { if (moveX > 50) { //右滑 //合并 boolean isMove = false;//判断是否有tile移动 for (int y = 0; y < MAX_Y; y++) { for (int x = MAX_X - 1; x >= 0; x--) { if (tiles[x][y].getNumber() == 0) { continue; } for (int x0 = x - 1; x0 >= 0; x0--) { if (tiles[x0][y].getNumber() == 0) { continue; } else if (tiles[x][y].getNumber() == tiles[x0][y].getNumber()) { tiles[x][y].setNumber(tiles[x][y].getNumber() * 2); tiles[x0][y].setNumber(0); isMove = true; break; } else { break; } } } } //移动 for (int y = 0; y < MAX_Y; y++) { for (int x = MAX_X - 1; x >= 0; x--) { if (tiles[x][y].getNumber() != 0) { continue; } for (int x0 = x - 1; x0 >= 0; x0--) { if (tiles[x0][y].getNumber() == 0) { continue; } else { tiles[x][y].setNumber(tiles[x0][y].getNumber()); tiles[x0][y].setNumber(0); isMove = true; break; } } } } //有tile移动才添加新的tile if (isMove) { newTile(); invalidate(); judgeOver(); } } else if (moveX < -50) { //左滑 //合并 boolean isMove = false; for (int y = 0; y < MAX_Y; y++) { for (int x = 0; x < MAX_X; x++) { if (tiles[x][y].getNumber() == 0) { continue; } for (int x0 = x + 1; x0 < MAX_X; x0++) { if (tiles[x0][y].getNumber() == 0) { continue; } else if (tiles[x][y].getNumber() == tiles[x0][y].getNumber()) { tiles[x][y].setNumber(tiles[x][y].getNumber() * 2); tiles[x0][y].setNumber(0); isMove = true; break; } else { break; } } } } //移动 for (int y = 0; y < MAX_Y; y++) { for (int x = 0; x < MAX_X; x++) { if (tiles[x][y].getNumber() != 0) { continue; } for (int x0 = x + 1; x0 < MAX_X; x0++) { if (tiles[x0][y].getNumber() == 0) { continue; } else { tiles[x][y].setNumber(tiles[x0][y].getNumber()); tiles[x0][y].setNumber(0); isMove = true; break; } } } } if (isMove) { newTile(); invalidate(); judgeOver(); } } } else { if (moveY > 50) { //下滑 //合并 boolean isMove = false; for (int x = 0; x < MAX_X; x++) { for (int y = MAX_Y - 1; y >= 0; y--) { if (tiles[x][y].getNumber() == 0) { continue; } for (int y0 = y - 1; y0 >= 0; y0--) { if (tiles[x][y0].getNumber() == 0) { continue; } else if (tiles[x][y].getNumber() == tiles[x][y0].getNumber()) { tiles[x][y].setNumber(tiles[x][y].getNumber() * 2); tiles[x][y0].setNumber(0); isMove = true; break; } else { break; } } } } //移动 for (int x = 0; x < MAX_X; x++) { for (int y = MAX_Y - 1; y >= 0; y--) { if (tiles[x][y].getNumber() != 0) { continue; } for (int y0 = y - 1; y0 >= 0; y0--) { if (tiles[x][y0].getNumber() == 0) { continue; } else { tiles[x][y].setNumber(tiles[x][y0].getNumber()); tiles[x][y0].setNumber(0); isMove = true; break; } } } } if (isMove) { newTile(); invalidate(); judgeOver(); } } else if (moveY < -50) { //上滑 //合并 boolean isMove = false; for (int x = 0; x < MAX_X; x++) { for (int y = 0; y < MAX_Y; y++) { if (tiles[x][y].getNumber() == 0) { continue; } for (int y0 = y + 1; y0 < MAX_Y; y0++) { if (tiles[x][y0].getNumber() == 0) { continue; } else if (tiles[x][y].getNumber() == tiles[x][y0].getNumber()) { tiles[x][y].setNumber(tiles[x][y].getNumber() * 2); tiles[x][y0].setNumber(0); isMove = true; break; } else { break; } } } } //移动 for (int x = 0; x < MAX_X; x++) { for (int y = 0; y < MAX_Y; y++) { if (tiles[x][y].getNumber() != 0) { continue; } for (int y0 = y + 1; y0 < MAX_Y; y0++) { if (tiles[x][y0].getNumber() == 0) { continue; } else { tiles[x][y].setNumber(tiles[x][y0].getNumber()); tiles[x][y0].setNumber(0); isMove = true; break; } } } } if (isMove) { newTile(); invalidate(); judgeOver(); } } } } } private void overLogic(MotionEvent event) { if (event.getX() > 0) { newGame(); gameState = GameState.Playing; } } private void judgeOver() { //右滑 //合并 for (int y = 0; y < MAX_Y; y++) { for (int x = MAX_X - 1; x >= 0; x--) { if (tiles[x][y].getNumber() == 0) { continue; } for (int x0 = x - 1; x0 >= 0; x0--) { if (tiles[x0][y].getNumber() == 0) { continue; } else if (tiles[x][y].getNumber() == tiles[x0][y].getNumber()) { return; } else { break; } } } } //移动 for (int y = 0; y < MAX_Y; y++) { for (int x = MAX_X - 1; x >= 0; x--) { if (tiles[x][y].getNumber() != 0) { continue; } for (int x0 = x - 1; x0 >= 0; x0--) { if (tiles[x0][y].getNumber() == 0) { continue; } else { return; } } } } //左滑 //合并 for (int y = 0; y < MAX_Y; y++) { for (int x = 0; x < MAX_X; x++) { if (tiles[x][y].getNumber() == 0) { continue; } for (int x0 = x + 1; x0 < MAX_X; x0++) { if (tiles[x0][y].getNumber() == 0) { continue; } else if (tiles[x][y].getNumber() == tiles[x0][y].getNumber()) { return; } else { break; } } } } //移动 for (int y = 0; y < MAX_Y; y++) { for (int x = 0; x < MAX_X; x++) { if (tiles[x][y].getNumber() != 0) { continue; } for (int x0 = x + 1; x0 < MAX_X; x0++) { if (tiles[x0][y].getNumber() == 0) { continue; } else { return; } } } } //下滑 //合并 for (int x = 0; x < MAX_X; x++) { for (int y = MAX_Y - 1; y >= 0; y--) { if (tiles[x][y].getNumber() == 0) { continue; } for (int y0 = y - 1; y0 >= 0; y0--) { if (tiles[x][y0].getNumber() == 0) { continue; } else if (tiles[x][y].getNumber() == tiles[x][y0].getNumber()) { return; } else { break; } } } } //移动 for (int x = 0; x < MAX_X; x++) { for (int y = MAX_Y - 1; y >= 0; y--) { if (tiles[x][y].getNumber() != 0) { continue; } for (int y0 = y - 1; y0 >= 0; y0--) { if (tiles[x][y0].getNumber() == 0) { continue; } else { return; } } } } //上滑 //合并 for (int x = 0; x < MAX_X; x++) { for (int y = 0; y < MAX_Y; y++) { if (tiles[x][y].getNumber() == 0) { continue; } for (int y0 = y + 1; y0 < MAX_Y; y0++) { if (tiles[x][y0].getNumber() == 0) { continue; } else if (tiles[x][y].getNumber() == tiles[x][y0].getNumber()) { return; } else { break; } } } } //移动 for (int x = 0; x < MAX_X; x++) { for (int y = 0; y < MAX_Y; y++) { if (tiles[x][y].getNumber() != 0) { continue; } for (int y0 = y + 1; y0 < MAX_Y; y0++) { if (tiles[x][y0].getNumber() == 0) { continue; } else { return; } } } } gameState = GameState.Over; invalidate(); }}
说两句:
这次跟上次的五子棋用的一样的游戏框架,应该很容易理解游戏的主题逻辑,当然最重要的是游戏算法,我实现的算法可能有些麻烦,但还算达到了效果,欢迎提意见。
关于主体算法:
我分了两个步骤:1.合并。2.移动
哎呀,不写了,有兴趣的人自己看代码吧,好像也没多少人看我写这个东西。。。囧
下次写个能动的游戏,就贪吃蛇吧,感觉自己帅的人请加我的公众微信号:xinshouit 更新会在里面通知
0 0
- 【Android 2d 游戏开发(2)】——2048
- android 2D游戏开发
- 【Android 2d游戏开发(1)】——五子棋
- Android游戏开发---2D游戏中背景的绘制
- Android游戏开发---2D游戏中背景的绘制
- 【Android 2d游戏开发日记(0)】——写在前面
- 【Android 2d游戏开发(3)】——贪吃蛇(基于surfaceview框架,精讲)
- 【Android 2D 游戏开发(4)】——俄罗斯方块(手势操作)
- 【Android 2D 游戏开发(5)】——九宫格拼图(苍老师版)
- 游戏开发及游戏(2D/3D)小Demo(进行中)- Android
- DirectX 2D游戏开发
- 2D游戏引擎开发
- unity3d 2D游戏开发
- cocos-2d 游戏开发
- Windows 2d游戏开发
- XNA游戏开发之2D游戏
- android 2D 游戏的开发的方法
- android 2D游戏开发,引擎设计(一) 基本构思
- MATLAB dlopen: cannot load any more object with static TLS
- SVN服务器搭建和使用(二)
- C++ 虚函数表解析
- android Handler引起内存泄漏
- 【python】:python如何编写函数
- 【Android 2d 游戏开发(2)】——2048
- oc 内存管理 -堆栈操作
- 01背包和完全背包问题
- Linux中的文件描述符与打开文件之间的关系
- Matlab中的常用快捷键
- 【SDUT2414】An interesting game——最小费用
- shiro入门级demo
- Android_实现页面跳转(intent的应用)及进阶
- (译)在Android中使用并发提高应用性能