您好,登錄后才能下訂單哦!
這篇文章主要介紹了Android實現俄羅斯方塊的方法,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
具體內容如下
思路:
首先要畫出游戲背景墻;
其次,要有方塊,以及方塊單元;
方塊的不同形狀,顏色隨機產生;
游戲的控制面板。
可能會出現的問題或者難點:
邊界問題:
①處于邊界的時候,方塊不可以再左右移動;
②下降的時候,到達邊界即底部,則不可繼續下落,此時應該產生一個新的方塊;
與其它方塊接觸問題:
①下落的時候,如果碰到其它的方塊則停止下落;
②左右移動的時候,移動的過程中,如果接觸到其他方快,則不可再繼續左右移動;
方塊的消除:
①調用方塊消除方法的時間:當方塊下落到底部的時候,判斷是否有需要消除的行;
②消除某一行之后,應該把這一行上面的全部方塊下移一行;
方塊的旋轉:
在當前項目中,我采用的是順時針旋轉。
①當旋轉的時候,如果出現方塊部分超出了邊界,應該對方塊進行平移,使其回到邊界以內。(曾在網上看到有人做過,判斷旋轉之后是否會超出邊界,如果會超出,則不進行旋轉,我覺得不好,方塊只要沒有下落到底部,我覺得都可以進行旋轉,除了沒有空間讓其旋轉外);
②如果空間不足以旋轉,也不可以旋轉。空間不足以旋轉的意思是:比如橫向方向只有兩個的空間,而方塊旋轉后會占用三個空間,此時也不可進行旋轉;
③當無法繼續下落或者下落到了底部也不可再進行旋轉
控制面板:
①游戲開始、暫停、繼續、結束,這些狀態應該怎么去控制,以及游戲與控制臺的事件關聯。
未發現的問題:
因為本人能力,只做到這么多,如果有人發現問題,可以留言交流,歡迎挑問題。
游戲的運行界面如下所示,基本的功能以及操作很簡單。
下面直接看項目代碼
項目文件結構
下面分別介紹每個類的功能
TetrisViewAW.java游戲的主界面,背景墻以及方塊都在此TetrisViewAW.Java里面,就是一個自定義的View ,(默認大家對于自定義View是熟悉的),在改類里面,有一個游戲主線程,用于控制游戲的開始,暫停,繼續,停止,以及方塊下落的速率。代碼我加了很多注釋,看不懂的可以留言。還有一點需要注意,當停止游戲時,要釋放線程,養成好習慣
/** * 俄羅斯方塊Game主界面 * * @sign Created by wang.ao on 2017年1月12日 */ @SuppressLint("DrawAllocation") public class TetrisViewAW extends View { /** 網格開始坐標值,橫縱坐標的開始值都是此值 */ public static final int beginPoint = 10; /** 俄羅斯方塊的最大坐標 */ private static int max_x, max_y; /** 行數和列數 */ private static int num_x = 0, num_y = 0; /** 背景墻畫筆 */ private static Paint paintWall = null; /** 俄羅斯方塊的單元塊畫筆 */ private static Paint paintBlock = null; private static final int BOUND_WIDTH_OF_WALL = 2; /** 當前正在下落的方塊 */ private List<BlockUnit> blockUnits = new ArrayList<BlockUnit>(); /** 下一個要顯示的方塊 */ private List<BlockUnit> blockUnitBufs = new ArrayList<BlockUnit>(); /** 下一個要顯示的方塊 */ private List<BlockUnit> routeBlockUnitBufs = new ArrayList<BlockUnit>(); /** 全部的方塊allBlockUnits */ private List<BlockUnit> allBlockUnits = new ArrayList<BlockUnit>(); /** 調用此對象的Activity對象 */ private TetrisActivityAW father = null; private int[] map = new int[100]; // 保存每行網格中包含俄羅斯方塊單元的個數 /** 游戲的主線程 */ private Thread mainThread = null; // 游戲的幾種狀態 /** 標識游戲是開始還是停止 */ private boolean gameStatus = false; /** 標識游戲是暫停還是運行 */ private boolean runningStatus = false; /** 俄羅斯方塊顏色數組 */ private static final int color[] = { Color.parseColor("#FF6600"), Color.BLUE, Color.RED, Color.GREEN, Color.GRAY }; /** 方塊的中心方塊單元的坐標, */ private int xx, yy; /** 方塊,用戶隨機獲取各種形狀的方塊 */ private TetrisBlock tetrisBlock; /** 分數 */ private int score = 0; /** 當前方塊的類型 */ private int blockType = 0; public TetrisViewAW(Context context) { this(context, null); } public TetrisViewAW(Context context, AttributeSet attrs) { super(context, attrs); if (paintWall == null) {// 初始化化背景墻畫筆 paintWall = new Paint(); paintWall.setColor(Color.LTGRAY); paintWall.setStyle(Paint.Style.STROKE); paintWall.setStrokeWidth(BOUND_WIDTH_OF_WALL + 1); } if (paintBlock == null) {// 初始化化背景墻畫筆 paintBlock = new Paint(); paintBlock.setColor(Color.parseColor("#FF6600")); } tetrisBlock = new TetrisBlock(); routeBlockUnitBufs = tetrisBlock.getUnits(beginPoint, beginPoint); Arrays.fill(map, 0); // 每行網格中包含俄羅斯方塊單元的個數全部初始化為0 // 繪制方塊 } /** * 設置當前游戲頁面的父類activity * * @param tetrisActivityAW */ public void setFather(TetrisActivityAW tetrisActivityAW) { father = tetrisActivityAW; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); max_x = getWidth(); max_y = getHeight(); RectF rel; // 繪制網格 num_x = 0; num_y = 0; for (int i = beginPoint; i < max_x - BlockUnit.UNIT_SIZE; i += BlockUnit.UNIT_SIZE) { for (int j = beginPoint; j < max_y - BlockUnit.UNIT_SIZE; j += BlockUnit.UNIT_SIZE) { rel = new RectF(i, j, i + BlockUnit.UNIT_SIZE, j + BlockUnit.UNIT_SIZE); canvas.drawRoundRect(rel, 8, 8, paintWall); num_y++; } num_x++; } // 隨機產生一個俄羅斯方塊 int len = blockUnits.size(); // 繪制方塊 // Toast.makeText(context, "" + len, Toast.LENGTH_SHORT).show(); for (int i = 0; i < len; i++) { int x = blockUnits.get(i).x; int y = blockUnits.get(i).y; // 設置當前方塊的顏色 paintBlock.setColor(color[blockUnits.get(i).color]); rel = new RectF(x + BOUND_WIDTH_OF_WALL, y + BOUND_WIDTH_OF_WALL, x + BlockUnit.UNIT_SIZE - BOUND_WIDTH_OF_WALL, y + BlockUnit.UNIT_SIZE - BOUND_WIDTH_OF_WALL); canvas.drawRoundRect(rel, 8, 8, paintBlock); } // 隨機產生一個俄羅斯方塊 len = allBlockUnits.size(); // 繪制方塊 // Toast.makeText(context, "" + len, Toast.LENGTH_SHORT).show(); for (int i = 0; i < len; i++) { int x = allBlockUnits.get(i).x; int y = allBlockUnits.get(i).y; paintBlock.setColor(color[allBlockUnits.get(i).color]); rel = new RectF(x + BOUND_WIDTH_OF_WALL, y + BOUND_WIDTH_OF_WALL, x + BlockUnit.UNIT_SIZE - BOUND_WIDTH_OF_WALL, y + BlockUnit.UNIT_SIZE - BOUND_WIDTH_OF_WALL); canvas.drawRoundRect(rel, 8, 8, paintBlock); } } /** * 開始游戲 */ public void startGame() { gameStatus = true; runningStatus = true; if (mainThread == null || !mainThread.isAlive()) { getNewBlock(); mainThread = new Thread(new MainThread()); mainThread.start(); } } /** * 暫停游戲 */ public void pauseGame() { runningStatus = false; } /** * 繼續游戲 */ public void continueGame() { runningStatus = true; } /** * 停止游戲 */ public void stopGame() { // 停止游戲,釋放游戲主線程 runningStatus = false; gameStatus = false; mainThread.interrupt(); blockUnits.clear(); allBlockUnits.clear(); score = 0; invalidate(); } /** * 向左滑動 */ public void toLeft() { if (BlockUnit.toLeft(blockUnits, max_x, allBlockUnits)) { xx = xx - BlockUnit.UNIT_SIZE; } invalidate(); } /** * 向右滑動 */ public void toRight() { if (BlockUnit.toRight(blockUnits, max_x, allBlockUnits)) { xx = xx + BlockUnit.UNIT_SIZE; } invalidate(); } /** * 按順時針旋轉 */ public void route() { if (blockType == 3) {// 如果當前正在下落的方塊為正方形,則不進行旋轉 return; } if (routeBlockUnitBufs.size() != blockUnits.size()) { routeBlockUnitBufs = tetrisBlock.getUnits(xx, yy); } for (int i = 0; i < blockUnits.size(); i++) { routeBlockUnitBufs.get(i).x = blockUnits.get(i).x; routeBlockUnitBufs.get(i).y = blockUnits.get(i).y; } for (BlockUnit blockUnit : routeBlockUnitBufs) { int tx = blockUnit.x; int ty = blockUnit.y; blockUnit.x = -(ty - yy) + xx; blockUnit.y = tx - xx + yy; } routeTran(routeBlockUnitBufs); if (!BlockUnit.canRoute(routeBlockUnitBufs, allBlockUnits)) { // Toast.makeText(father, "不可旋轉", Toast.LENGTH_SHORT).show(); return; } for (BlockUnit blockUnit : blockUnits) { int tx = blockUnit.x; int ty = blockUnit.y; blockUnit.x = -(ty - yy) + xx; blockUnit.y = tx - xx + yy; } routeTran(blockUnits); invalidate(); } /** * 如果方塊處于邊緣,則翻轉過后,會出現方塊部分處于邊緣之外的情況, 因此,通過遞歸判斷是否有超出邊緣的部分, * 如果有,則進行左右平移,把處于邊緣外的方塊移動到邊緣內 */ public void routeTran(List<BlockUnit> blockUnitsBuf) { boolean needLeftTran = false; boolean needRightTran = false; for (BlockUnit u : blockUnitsBuf) { if (u.x < beginPoint) { needLeftTran = true; } if (u.x > max_x - BlockUnit.UNIT_SIZE) { needRightTran = true; } } if (needLeftTran || needRightTran) { for (BlockUnit u : blockUnitsBuf) { if (needLeftTran) { u.x = u.x + BlockUnit.UNIT_SIZE; } else if (needRightTran) { u.x = u.x - BlockUnit.UNIT_SIZE; } } routeTran(blockUnitsBuf); } else { return; } } /** * 獲取一個新的方塊 */ private void getNewBlock() { // 新的方塊的坐標,x坐標位于x軸的中間,y 位于起始位置 this.xx = beginPoint + (num_x / 2) * BlockUnit.UNIT_SIZE; this.yy = beginPoint; if (blockUnitBufs.size() == 0) { // 當游戲第一次開始的時候,先初始化一個方塊 blockUnitBufs = tetrisBlock.getUnits(xx, yy); } blockUnits = blockUnitBufs; blockType = tetrisBlock.blockType; blockUnitBufs = tetrisBlock.getUnits(xx, yy); if (father != null) {// 顯示出下一個要出現的方塊 father.setNextBlockView(blockUnitBufs, (num_x / 2) * BlockUnit.UNIT_SIZE); } } /** * 游戲的主線程 * * @sign Created by wang.ao on 2017年1月16日 */ private class MainThread implements Runnable { @Override public void run() { while (gameStatus) { while (runningStatus) { if (BlockUnit.canMoveToDown(blockUnits, max_y, allBlockUnits)) { // 判斷是否可以繼續下落,如果可以下落,則下落 BlockUnit.toDown(blockUnits, max_y, allBlockUnits); yy = yy + BlockUnit.UNIT_SIZE; } else { /** * 當不可以繼續下落的時候,把當前的方塊添加到allBlockUnits中, * 并且判斷是否有需要消除的方塊,然后再產生一個新的方塊 */ for (BlockUnit blockUnit : blockUnits) { blockUnit.y = blockUnit.y + BlockUnit.UNIT_SIZE; allBlockUnits.add(blockUnit); } for (BlockUnit u : blockUnits) { // 更新map,即更新每行網格中靜止俄羅斯方塊單元的個數 int index = (int) ((u.y - beginPoint) / 50); // 計算所在行數 map[index]++; } // 每行最大個數 int end = (int) ((max_y - 50 - beginPoint) / BlockUnit.UNIT_SIZE); int full = (int) ((max_x - 50 - beginPoint) / BlockUnit.UNIT_SIZE) + 1; try { Thread.sleep(GameConfig.SPEED); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i <= end; i++) { /*** * 消除需要消除的方塊(觸發條件,某一行中被塞滿了方塊,沒有空白) * 注意順序,先消除某一行,再移動這一行上邊的方塊 */ if (map[i] >= full) { BlockUnit.remove(allBlockUnits, i); score += 100; map[i] = 0; for (int j = i; j > 0; j--) map[j] = map[j - 1]; map[0] = 0; for (BlockUnit blockUnit : allBlockUnits) { if (blockUnit.y < (i * BlockUnit.UNIT_SIZE + beginPoint)) { blockUnit.y = blockUnit.y + BlockUnit.UNIT_SIZE; } } } } father.runOnUiThread(new Runnable() { @Override public void run() { /** * 刷新分數 */ father.score.setText("" + score); invalidate(); } }); try { Thread.sleep(GameConfig.SPEED * 3); } catch (InterruptedException e) { e.printStackTrace(); } father.runOnUiThread(new Runnable() { @Override public void run() { getNewBlock(); score += 10; father.score.setText("" + score); } }); } father.runOnUiThread(new Runnable() { @Override public void run() { invalidate(); } }); try { Thread.sleep(GameConfig.SPEED); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
BlockUnit.java方塊的單元塊,大家都玩過俄羅斯方塊,每一個方塊由四個單元塊組成。單元快應該有以下屬性:①大小:單元塊的大小決定了主界面的容量(容納單元塊的數量);②顏色:每個單元塊都有一個顏色,美化游戲界面(可無);③坐標:包括X軸坐標、Y軸坐標,在繪制方塊的時候,以單元塊的坐標為起點繪制,即:單元塊的坐標值應該為單元塊在界面上的左上角的坐標。
此類的主要功能有:方塊的下落,左右移動,判斷是否可以旋轉等功能都在此類中,算是核心類。
/** * 俄羅斯方塊的單元快 * * @sign Created by wang.ao on 2017年1月13日 */ public class BlockUnit { public static final int UNIT_SIZE = 50; public static final int BEGIN = 10; public int color; // 單元塊 的坐標 public int x, y; public BlockUnit() { } public BlockUnit(int x, int y, int color) { /* * @param 單元塊橫縱坐標 構造函數 */ this.x = x; this.y = y; this.color = color; } /** * 判斷方塊是否可以向左移動,1是否在邊緣,2是否會與其他方塊重合 * @param blockUnits 當前正在下落的方塊 * @param max_x 游戲主界面X軸的最大值 ,下同 * @param allBlockUnits 所有的方塊 * @return 能移動true;不能移動false */ public static boolean canMoveToLeft(List<BlockUnit> blockUnits, int max_x, List<BlockUnit> allBlockUnits) { for (BlockUnit blockUnit : blockUnits) { int x = blockUnit.x; if (x - UNIT_SIZE < BEGIN) { return false; } int y = blockUnit.y; if (isSameUnit(x - UNIT_SIZE, y, allBlockUnits)) { return false; } } return true; } /** * 判斷方塊是否可以向右移動,1是否在邊緣,2是否會與其他方塊重合 * @param blockUnits 當前正在下落的方塊 * @param max_x 游戲主界面X軸的最大值 ,下同 * @param allBlockUnits 所有的方塊 * @return 能移動true;不能移動false */ public static boolean canMoveToRight(List<BlockUnit> blockUnits, int max_x, List<BlockUnit> allBlockUnits) { for (BlockUnit blockUnit : blockUnits) { int x = blockUnit.x; if (x + UNIT_SIZE > max_x - UNIT_SIZE) { return false; } int y = blockUnit.y; if (isSameUnit(x + UNIT_SIZE, y, allBlockUnits)) { return false; } } return true; } /** * 判斷方塊是否可以向下移動,1是否在邊緣,2是否會與其他方塊重合 * @param blockUnits 當前正在下落的方塊 * @param max_x 游戲主界面X軸的最大值 ,下同 * @param allBlockUnits 所有的方塊 * @return 能移動true;不能移動false */ public static boolean canMoveToDown(List<BlockUnit> blockUnits, int max_y, List<BlockUnit> allBlockUnits) { for (BlockUnit blockUnit : blockUnits) { int x = blockUnit.x; int y = blockUnit.y + UNIT_SIZE * 2; if (y > max_y - UNIT_SIZE) { return false; } if (isSameUnit(x, y, allBlockUnits)) { return false; } } return true; } public static boolean canRoute(List<BlockUnit> blockUnits, List<BlockUnit> allBlockUnits){ for (BlockUnit blockUnit: blockUnits) { if(isSameUnit(blockUnit.x, blockUnit.y, allBlockUnits)){ return false; } } return true; } /** * 把當前方塊向左移動一格 * @param blockUnits * @param max_x * @param allBlockUnits * @return 是否成功移動一格,是:true,否:false */ public static boolean toLeft(List<BlockUnit> blockUnits, int max_x, List<BlockUnit> allBlockUnits) { if (canMoveToLeft(blockUnits, max_x, allBlockUnits)) { for (BlockUnit blockUnit : blockUnits) { blockUnit.x = blockUnit.x - UNIT_SIZE; } return true; } return false; } /** * 把當前方塊向右移動一格 * @param blockUnits * @param max_x * @param allBlockUnits * @return 是否成功移動一格,是:true,否:false */ public static boolean toRight(List<BlockUnit> blockUnits, int max_x, List<BlockUnit> allBlockUnits) { if (canMoveToRight(blockUnits, max_x, allBlockUnits)) { for (BlockUnit blockUnit : blockUnits) { blockUnit.x = blockUnit.x + UNIT_SIZE; } return true; } return false; } /** * 把當前方塊下落一格 * @param blockUnits * @param allBlockUnits * @return 是否成功移動一格,是:true,否:false */ public static void toDown(List<BlockUnit> blockUnits, int max_Y, List<BlockUnit> allBlockUnits) { for (BlockUnit blockUnit : blockUnits) { blockUnit.y = blockUnit.y + BlockUnit.UNIT_SIZE; } } /** * 判斷 方塊單元是否和所有方塊有重合 * @param x * @param y * @param allBlockUnits * @return */ public static boolean isSameUnit(int x, int y, List<BlockUnit> allBlockUnits) { for (BlockUnit blockUnit : allBlockUnits) { if (Math.abs(x - blockUnit.x) < UNIT_SIZE && Math.abs(y - blockUnit.y) < UNIT_SIZE) { return true; } } return false; } /** * 刪除在第j行上的方塊單元 * @param allBlockUnits * @param j 需刪除行標 */ public static void remove(List<BlockUnit> allBlockUnits, int j) { for (int i = allBlockUnits.size() - 1; i >= 0; i--) { /* * ①逆向遍歷 ②根據y坐標計算單元所在行,若為j行則從units中刪除 */ if ((int) ((allBlockUnits.get(i).y - BEGIN) / 50) == j) allBlockUnits.remove(i); } } }
TetrisBlock.java用于產生不同形狀的方塊,共有其中類型。
/** * 方塊 * * @sign Created by wang.ao on 2017年1月13日 */ public class TetrisBlock { private static final int TYPE_SUM = 7; public int blockType, blockDirection; // 方塊種類,方塊朝向 private int color; // 方塊顏色 private int x, y; // 方塊坐標 public TetrisBlock() { } public TetrisBlock(int x, int y) { this.x = x; this.y = y; } public List<BlockUnit> getUnits(int x, int y) { this.x = x; this.y = y; return returnUnit(); } /** * 隨機產生一種方塊 * @return */ public List<BlockUnit> returnUnit() { List<BlockUnit> units = new ArrayList<BlockUnit>(); // 方塊組成部分 blockType = (int) (Math.random() * TYPE_SUM) + 1; // 隨機生成一個種類 blockDirection = 1; // 默認初始方向 color = (int) (Math.random() * 4) + 1; // 隨機生成一個顏色 units.clear(); switch (blockType) { case 1:// 橫線 for (int i = 0; i < 4; i++) { units.add(new BlockUnit(x + (-2 + i) * BlockUnit.UNIT_SIZE, y, color)); } break; case 2: units.add(new BlockUnit(x + (-1 + 1) * BlockUnit.UNIT_SIZE, y - BlockUnit.UNIT_SIZE, color)); for (int i = 0; i < 3; i++) { units.add(new BlockUnit(x + (-1 + i) * BlockUnit.UNIT_SIZE, y, color)); } break; case 3: for (int i = 0; i < 2; i++) { units.add(new BlockUnit(x + (i - 1) * BlockUnit.UNIT_SIZE, y - BlockUnit.UNIT_SIZE, color)); units.add(new BlockUnit(x + (i - 1) * BlockUnit.UNIT_SIZE, y, color)); } break; case 4: units.add(new BlockUnit(x + (-1 + 0) * BlockUnit.UNIT_SIZE, y - BlockUnit.UNIT_SIZE, color)); for (int i = 0; i < 3; i++) { units.add(new BlockUnit(x + (-1 + i) * BlockUnit.UNIT_SIZE, y, color)); } break; case 5: units.add(new BlockUnit(x + (-1 + 2) * BlockUnit.UNIT_SIZE, y - BlockUnit.UNIT_SIZE, color)); for (int i = 0; i < 3; i++) { units.add(new BlockUnit(x + (-1 + i) * BlockUnit.UNIT_SIZE, y, color)); } break; case 6: for (int i = 0; i < 2; i++) { units.add(new BlockUnit(x + (-1 + i) * BlockUnit.UNIT_SIZE, y - BlockUnit.UNIT_SIZE, color)); units.add(new BlockUnit(x + i * BlockUnit.UNIT_SIZE, y, color)); } break; case 7: for (int i = 0; i < 2; i++) { units.add(new BlockUnit(x + i * BlockUnit.UNIT_SIZE, y - BlockUnit.UNIT_SIZE, color)); units.add(new BlockUnit(x + (-1 + i) * BlockUnit.UNIT_SIZE, y, color)); } break; } return units; }
NextBlockView.java其實就是游戲主界面的一個縮減版,用于顯示下一個要出現的方塊的,玩家可以明確的知道下一個方塊的形狀和顏色。
/** * 下一個要展示的方塊 * * @sign Created by wang.ao on 2017年1月13日 */ @SuppressLint("DrawAllocation") public class NextBlockView extends View { /** 網格開始坐標值,橫縱坐標的開始值都是此值 */ public static final int beginPoint = 10; /** 俄羅斯方塊的最大坐標 */ private static int max_x, max_y; private List<BlockUnit> blockUnits = new ArrayList<BlockUnit>(); /** 背景墻畫筆 */ private static Paint paintWall = null; private static final int BOUND_WIDTH_OF_WALL = 2; private static Paint paintBlock = null; private int div_x = 0; // 俄羅斯方塊顏色數組 private static final int color[] ={ Color.parseColor("#FF6600"), Color.BLUE, Color.RED, Color.GREEN, Color.GRAY }; public NextBlockView(Context context) { this(context, null); } public NextBlockView(Context context, AttributeSet attrs) { super(context, attrs); if (paintWall == null) {// 初始化化背景墻畫筆 paintWall = new Paint(); paintWall.setColor(Color.LTGRAY); paintWall.setStyle(Paint.Style.STROKE); paintWall.setStrokeWidth(BOUND_WIDTH_OF_WALL + 1); } if (paintBlock == null) {// 初始化化背景墻畫筆 paintBlock = new Paint(); paintBlock.setColor(Color.parseColor("#FF6600")); } } public void setBlockUnits(List<BlockUnit> blockUnits, int div_x) { this.blockUnits = blockUnits; this.div_x = div_x; invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); max_x = getWidth(); max_y = getHeight(); RectF rel; // 繪制網格 int len = blockUnits.size(); // 繪制方塊 // Toast.makeText(context, "" + len, Toast.LENGTH_SHORT).show(); for (int i = 0; i < len; i++) { paintBlock.setColor(color[blockUnits.get(i).color]); int x = blockUnits.get(i).x - div_x + BlockUnit.UNIT_SIZE * 2; int y = blockUnits.get(i).y + BlockUnit.UNIT_SIZE * 2; rel = new RectF(x + BOUND_WIDTH_OF_WALL, y + BOUND_WIDTH_OF_WALL, x + BlockUnit.UNIT_SIZE - BOUND_WIDTH_OF_WALL, y + BlockUnit.UNIT_SIZE - BOUND_WIDTH_OF_WALL); canvas.drawRoundRect(rel, 8, 8, paintBlock); rel = new RectF(x, y, x + BlockUnit.UNIT_SIZE, y + BlockUnit.UNIT_SIZE); canvas.drawRoundRect(rel, 8, 8, paintWall); } } }
GameConfig.java用于配置方塊的下落速度
public class GameConfig { /**方塊下落的速度*/ public static final int SPEED = 300; }
TetrisActivityAW.java主界面,包括游戲主界面和控制臺,很簡單,直接貼代碼。
public class TetrisActivityAW extends Activity { private NextBlockView nextBlockView; private TetrisViewAW tetrisViewAW; private TextView gameStatusTip; public TextView score; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tetris_activity_aw); nextBlockView = (NextBlockView) findViewById(R.id.nextBlockView1); tetrisViewAW = (TetrisViewAW) findViewById(R.id.tetrisViewAW1); tetrisViewAW.setFather(this); gameStatusTip = (TextView) findViewById(R.id.game_staus_tip); score = (TextView) findViewById(R.id.score); } public void setNextBlockView(List<BlockUnit> blockUnits, int div_x) { nextBlockView.setBlockUnits(blockUnits, div_x); } /** * 開始游戲 * * @param view */ public void startGame(View view) { tetrisViewAW.startGame(); gameStatusTip.setText("游戲運行中"); } /** * 暫停游戲 */ public void pauseGame(View view) { tetrisViewAW.pauseGame(); gameStatusTip.setText("游戲已暫停"); } /** * 繼續游戲 */ public void continueGame(View view) { tetrisViewAW.continueGame(); gameStatusTip.setText("游戲運行中"); } /** * 停止游戲 */ public void stopGame(View view) { tetrisViewAW.stopGame(); score.setText(""+0); gameStatusTip.setText("游戲已停止"); } /** * 向左滑動 */ public void toLeft(View view) { tetrisViewAW.toLeft(); } /** * 向右滑動 */ public void toRight(View view) { tetrisViewAW.toRight(); } /** * 向右滑動 */ public void toRoute(View view) { tetrisViewAW.route(); } }
TetrisActivityAW activity的xml文件
<RelativeLayout 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" tools:context="${relativePackage}.${activityClass}" > <com.awang.media.minetetris.TetrisViewAW android:id="@+id/tetrisViewAW1" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="200dp" android:layout_marginRight="120dp" /> <com.awang.media.minetetris.NextBlockView android:id="@+id/nextBlockView1" android:layout_width="120dp" android:layout_height="120dp" android:layout_alignParentRight="true" /> <LinearLayout android:layout_width="110dp" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_below="@+id/nextBlockView1" android:layout_marginTop="20dp" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="分數" /> <TextView android:id="@+id/score" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="1" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="等級" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="1" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="速度" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="0" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="最高分" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="0" /> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:onClick="startGame" android:text="開始" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="pauseGame" android:text="暫停" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="continueGame" android:text="繼續" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="stopGame" android:text="結束" /> </LinearLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="200dp" android:layout_alignParentBottom="true" > <Button android:layout_width="100dp" android:layout_height="100dp" android:onClick="toLeft" android:text="左" /> <TextView android:id="@+id/game_staus_tip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="5dp" android:text="點擊開始運行游戲" android:textSize="20sp" /> <Button android:layout_width="100dp" android:layout_height="100dp" android:layout_centerInParent="true" android:onClick="toRoute" android:text="旋轉" /> <Button android:layout_width="100dp" android:layout_height="100dp" android:layout_alignParentRight="true" android:onClick="toRight" android:text="右" /> </RelativeLayout> </RelativeLayout>
整個項目就是這些,代碼已經全部貼出來了。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Android實現俄羅斯方塊的方法”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。