這篇文章主要介紹了Android實(shí)現(xiàn)俄羅斯方塊的方法,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
創(chuàng)新互聯(lián)是一家專注于網(wǎng)站建設(shè)、做網(wǎng)站與策劃設(shè)計(jì),嘉魚(yú)網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:嘉魚(yú)等地區(qū)。嘉魚(yú)做網(wǎng)站價(jià)格咨詢:13518219792
具體內(nèi)容如下
思路:
首先要畫出游戲背景墻;
其次,要有方塊,以及方塊單元;
方塊的不同形狀,顏色隨機(jī)產(chǎn)生;
游戲的控制面板。
可能會(huì)出現(xiàn)的問(wèn)題或者難點(diǎn):
邊界問(wèn)題:
①處于邊界的時(shí)候,方塊不可以再左右移動(dòng);
②下降的時(shí)候,到達(dá)邊界即底部,則不可繼續(xù)下落,此時(shí)應(yīng)該產(chǎn)生一個(gè)新的方塊;
與其它方塊接觸問(wèn)題:
①下落的時(shí)候,如果碰到其它的方塊則停止下落;
②左右移動(dòng)的時(shí)候,移動(dòng)的過(guò)程中,如果接觸到其他方快,則不可再繼續(xù)左右移動(dòng);
方塊的消除:
①調(diào)用方塊消除方法的時(shí)間:當(dāng)方塊下落到底部的時(shí)候,判斷是否有需要消除的行;
②消除某一行之后,應(yīng)該把這一行上面的全部方塊下移一行;
方塊的旋轉(zhuǎn):
在當(dāng)前項(xiàng)目中,我采用的是順時(shí)針旋轉(zhuǎn)。
①當(dāng)旋轉(zhuǎn)的時(shí)候,如果出現(xiàn)方塊部分超出了邊界,應(yīng)該對(duì)方塊進(jìn)行平移,使其回到邊界以內(nèi)。(曾在網(wǎng)上看到有人做過(guò),判斷旋轉(zhuǎn)之后是否會(huì)超出邊界,如果會(huì)超出,則不進(jìn)行旋轉(zhuǎn),我覺(jué)得不好,方塊只要沒(méi)有下落到底部,我覺(jué)得都可以進(jìn)行旋轉(zhuǎn),除了沒(méi)有空間讓其旋轉(zhuǎn)外);
②如果空間不足以旋轉(zhuǎn),也不可以旋轉(zhuǎn)??臻g不足以旋轉(zhuǎn)的意思是:比如橫向方向只有兩個(gè)的空間,而方塊旋轉(zhuǎn)后會(huì)占用三個(gè)空間,此時(shí)也不可進(jìn)行旋轉(zhuǎn);
③當(dāng)無(wú)法繼續(xù)下落或者下落到了底部也不可再進(jìn)行旋轉(zhuǎn)
控制面板:
①游戲開(kāi)始、暫停、繼續(xù)、結(jié)束,這些狀態(tài)應(yīng)該怎么去控制,以及游戲與控制臺(tái)的事件關(guān)聯(lián)。
未發(fā)現(xiàn)的問(wèn)題:
因?yàn)楸救四芰?,只做到這么多,如果有人發(fā)現(xiàn)問(wèn)題,可以留言交流,歡迎挑問(wèn)題。
游戲的運(yùn)行界面如下所示,基本的功能以及操作很簡(jiǎn)單。
下面直接看項(xiàng)目代碼
項(xiàng)目文件結(jié)構(gòu)
下面分別介紹每個(gè)類的功能
TetrisViewAW.java游戲的主界面,背景墻以及方塊都在此TetrisViewAW.Java里面,就是一個(gè)自定義的View ,(默認(rèn)大家對(duì)于自定義View是熟悉的),在改類里面,有一個(gè)游戲主線程,用于控制游戲的開(kāi)始,暫停,繼續(xù),停止,以及方塊下落的速率。代碼我加了很多注釋,看不懂的可以留言。還有一點(diǎn)需要注意,當(dāng)停止游戲時(shí),要釋放線程,養(yǎng)成好習(xí)慣
/** * 俄羅斯方塊Game主界面 * * @sign Created by wang.ao on 2017年1月12日 */ @SuppressLint("DrawAllocation") public class TetrisViewAW extends View { /** 網(wǎng)格開(kāi)始坐標(biāo)值,橫縱坐標(biāo)的開(kāi)始值都是此值 */ public static final int beginPoint = 10; /** 俄羅斯方塊的最大坐標(biāo) */ private static int max_x, max_y; /** 行數(shù)和列數(shù) */ 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; /** 當(dāng)前正在下落的方塊 */ private ListblockUnits = new ArrayList (); /** 下一個(gè)要顯示的方塊 */ private List blockUnitBufs = new ArrayList (); /** 下一個(gè)要顯示的方塊 */ private List routeBlockUnitBufs = new ArrayList (); /** 全部的方塊allBlockUnits */ private List allBlockUnits = new ArrayList (); /** 調(diào)用此對(duì)象的Activity對(duì)象 */ private TetrisActivityAW father = null; private int[] map = new int[100]; // 保存每行網(wǎng)格中包含俄羅斯方塊單元的個(gè)數(shù) /** 游戲的主線程 */ private Thread mainThread = null; // 游戲的幾種狀態(tài) /** 標(biāo)識(shí)游戲是開(kāi)始還是停止 */ private boolean gameStatus = false; /** 標(biāo)識(shí)游戲是暫停還是運(yùn)行 */ private boolean runningStatus = false; /** 俄羅斯方塊顏色數(shù)組 */ private static final int color[] = { Color.parseColor("#FF6600"), Color.BLUE, Color.RED, Color.GREEN, Color.GRAY }; /** 方塊的中心方塊單元的坐標(biāo), */ private int xx, yy; /** 方塊,用戶隨機(jī)獲取各種形狀的方塊 */ private TetrisBlock tetrisBlock; /** 分?jǐn)?shù) */ private int score = 0; /** 當(dāng)前方塊的類型 */ 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); // 每行網(wǎng)格中包含俄羅斯方塊單元的個(gè)數(shù)全部初始化為0 // 繪制方塊 } /** * 設(shè)置當(dāng)前游戲頁(yè)面的父類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; // 繪制網(wǎng)格 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++; } // 隨機(jī)產(chǎn)生一個(gè)俄羅斯方塊 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; // 設(shè)置當(dāng)前方塊的顏色 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); } // 隨機(jī)產(chǎn)生一個(gè)俄羅斯方塊 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); } } /** * 開(kāi)始游戲 */ 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; } /** * 繼續(xù)游戲 */ public void continueGame() { runningStatus = true; } /** * 停止游戲 */ public void stopGame() { // 停止游戲,釋放游戲主線程 runningStatus = false; gameStatus = false; mainThread.interrupt(); blockUnits.clear(); allBlockUnits.clear(); score = 0; invalidate(); } /** * 向左滑動(dòng) */ public void toLeft() { if (BlockUnit.toLeft(blockUnits, max_x, allBlockUnits)) { xx = xx - BlockUnit.UNIT_SIZE; } invalidate(); } /** * 向右滑動(dòng) */ public void toRight() { if (BlockUnit.toRight(blockUnits, max_x, allBlockUnits)) { xx = xx + BlockUnit.UNIT_SIZE; } invalidate(); } /** * 按順時(shí)針旋轉(zhuǎn) */ public void route() { if (blockType == 3) {// 如果當(dāng)前正在下落的方塊為正方形,則不進(jìn)行旋轉(zhuǎn) 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, "不可旋轉(zhuǎn)", 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(); } /** * 如果方塊處于邊緣,則翻轉(zhuǎn)過(guò)后,會(huì)出現(xiàn)方塊部分處于邊緣之外的情況, 因此,通過(guò)遞歸判斷是否有超出邊緣的部分, * 如果有,則進(jìn)行左右平移,把處于邊緣外的方塊移動(dòng)到邊緣內(nèi) */ public void routeTran(List 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; } } /** * 獲取一個(gè)新的方塊 */ private void getNewBlock() { // 新的方塊的坐標(biāo),x坐標(biāo)位于x軸的中間,y 位于起始位置 this.xx = beginPoint + (num_x / 2) * BlockUnit.UNIT_SIZE; this.yy = beginPoint; if (blockUnitBufs.size() == 0) { // 當(dāng)游戲第一次開(kāi)始的時(shí)候,先初始化一個(gè)方塊 blockUnitBufs = tetrisBlock.getUnits(xx, yy); } blockUnits = blockUnitBufs; blockType = tetrisBlock.blockType; blockUnitBufs = tetrisBlock.getUnits(xx, yy); if (father != null) {// 顯示出下一個(gè)要出現(xiàn)的方塊 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)) { // 判斷是否可以繼續(xù)下落,如果可以下落,則下落 BlockUnit.toDown(blockUnits, max_y, allBlockUnits); yy = yy + BlockUnit.UNIT_SIZE; } else { /** * 當(dāng)不可以繼續(xù)下落的時(shí)候,把當(dāng)前的方塊添加到allBlockUnits中, * 并且判斷是否有需要消除的方塊,然后再產(chǎn)生一個(gè)新的方塊 */ for (BlockUnit blockUnit : blockUnits) { blockUnit.y = blockUnit.y + BlockUnit.UNIT_SIZE; allBlockUnits.add(blockUnit); } for (BlockUnit u : blockUnits) { // 更新map,即更新每行網(wǎng)格中靜止俄羅斯方塊單元的個(gè)數(shù) int index = (int) ((u.y - beginPoint) / 50); // 計(jì)算所在行數(shù) map[index]++; } // 每行最大個(gè)數(shù) 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++) { /*** * 消除需要消除的方塊(觸發(fā)條件,某一行中被塞滿了方塊,沒(méi)有空白) * 注意順序,先消除某一行,再移動(dòng)這一行上邊的方塊 */ 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() { /** * 刷新分?jǐn)?shù) */ 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方塊的單元塊,大家都玩過(guò)俄羅斯方塊,每一個(gè)方塊由四個(gè)單元塊組成。單元快應(yīng)該有以下屬性:①大?。?jiǎn)卧獕K的大小決定了主界面的容量(容納單元塊的數(shù)量);②顏色:每個(gè)單元塊都有一個(gè)顏色,美化游戲界面(可無(wú));③坐標(biāo):包括X軸坐標(biāo)、Y軸坐標(biāo),在繪制方塊的時(shí)候,以單元塊的坐標(biāo)為起點(diǎn)繪制,即:?jiǎn)卧獕K的坐標(biāo)值應(yīng)該為單元塊在界面上的左上角的坐標(biāo)。
此類的主要功能有:方塊的下落,左右移動(dòng),判斷是否可以旋轉(zhuǎn)等功能都在此類中,算是核心類。
/** * 俄羅斯方塊的單元快 * * @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; // 單元塊 的坐標(biāo) public int x, y; public BlockUnit() { } public BlockUnit(int x, int y, int color) { /* * @param 單元塊橫縱坐標(biāo) 構(gòu)造函數(shù) */ this.x = x; this.y = y; this.color = color; } /** * 判斷方塊是否可以向左移動(dòng),1是否在邊緣,2是否會(huì)與其他方塊重合 * @param blockUnits 當(dāng)前正在下落的方塊 * @param max_x 游戲主界面X軸的最大值 ,下同 * @param allBlockUnits 所有的方塊 * @return 能移動(dòng)true;不能移動(dòng)false */ public static boolean canMoveToLeft(ListblockUnits, int max_x, List 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; } /** * 判斷方塊是否可以向右移動(dòng),1是否在邊緣,2是否會(huì)與其他方塊重合 * @param blockUnits 當(dāng)前正在下落的方塊 * @param max_x 游戲主界面X軸的最大值 ,下同 * @param allBlockUnits 所有的方塊 * @return 能移動(dòng)true;不能移動(dòng)false */ public static boolean canMoveToRight(List blockUnits, int max_x, List 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; } /** * 判斷方塊是否可以向下移動(dòng),1是否在邊緣,2是否會(huì)與其他方塊重合 * @param blockUnits 當(dāng)前正在下落的方塊 * @param max_x 游戲主界面X軸的最大值 ,下同 * @param allBlockUnits 所有的方塊 * @return 能移動(dòng)true;不能移動(dòng)false */ public static boolean canMoveToDown(List blockUnits, int max_y, List 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 blockUnits, List allBlockUnits){ for (BlockUnit blockUnit: blockUnits) { if(isSameUnit(blockUnit.x, blockUnit.y, allBlockUnits)){ return false; } } return true; } /** * 把當(dāng)前方塊向左移動(dòng)一格 * @param blockUnits * @param max_x * @param allBlockUnits * @return 是否成功移動(dòng)一格,是:true,否:false */ public static boolean toLeft(List blockUnits, int max_x, List allBlockUnits) { if (canMoveToLeft(blockUnits, max_x, allBlockUnits)) { for (BlockUnit blockUnit : blockUnits) { blockUnit.x = blockUnit.x - UNIT_SIZE; } return true; } return false; } /** * 把當(dāng)前方塊向右移動(dòng)一格 * @param blockUnits * @param max_x * @param allBlockUnits * @return 是否成功移動(dòng)一格,是:true,否:false */ public static boolean toRight(List blockUnits, int max_x, List allBlockUnits) { if (canMoveToRight(blockUnits, max_x, allBlockUnits)) { for (BlockUnit blockUnit : blockUnits) { blockUnit.x = blockUnit.x + UNIT_SIZE; } return true; } return false; } /** * 把當(dāng)前方塊下落一格 * @param blockUnits * @param allBlockUnits * @return 是否成功移動(dòng)一格,是:true,否:false */ public static void toDown(List blockUnits, int max_Y, List 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 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 需刪除行標(biāo) */ public static void remove(List allBlockUnits, int j) { for (int i = allBlockUnits.size() - 1; i >= 0; i--) { /* * ①逆向遍歷 ②根據(jù)y坐標(biāo)計(jì)算單元所在行,若為j行則從units中刪除 */ if ((int) ((allBlockUnits.get(i).y - BEGIN) / 50) == j) allBlockUnits.remove(i); } } }
TetrisBlock.java用于產(chǎn)生不同形狀的方塊,共有其中類型。
/** * 方塊 * * @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; // 方塊坐標(biāo) public TetrisBlock() { } public TetrisBlock(int x, int y) { this.x = x; this.y = y; } public ListgetUnits(int x, int y) { this.x = x; this.y = y; return returnUnit(); } /** * 隨機(jī)產(chǎn)生一種方塊 * @return */ public List returnUnit() { List units = new ArrayList (); // 方塊組成部分 blockType = (int) (Math.random() * TYPE_SUM) + 1; // 隨機(jī)生成一個(gè)種類 blockDirection = 1; // 默認(rèn)初始方向 color = (int) (Math.random() * 4) + 1; // 隨機(jī)生成一個(gè)顏色 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其實(shí)就是游戲主界面的一個(gè)縮減版,用于顯示下一個(gè)要出現(xiàn)的方塊的,玩家可以明確的知道下一個(gè)方塊的形狀和顏色。
/** * 下一個(gè)要展示的方塊 * * @sign Created by wang.ao on 2017年1月13日 */ @SuppressLint("DrawAllocation") public class NextBlockView extends View { /** 網(wǎng)格開(kāi)始坐標(biāo)值,橫縱坐標(biāo)的開(kāi)始值都是此值 */ public static final int beginPoint = 10; /** 俄羅斯方塊的最大坐標(biāo) */ private static int max_x, max_y; private ListblockUnits = new ArrayList (); /** 背景墻畫筆 */ private static Paint paintWall = null; private static final int BOUND_WIDTH_OF_WALL = 2; private static Paint paintBlock = null; private int div_x = 0; // 俄羅斯方塊顏色數(shù)組 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 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; // 繪制網(wǎng)格 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主界面,包括游戲主界面和控制臺(tái),很簡(jiǎn)單,直接貼代碼。
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(ListblockUnits, int div_x) { nextBlockView.setBlockUnits(blockUnits, div_x); } /** * 開(kāi)始游戲 * * @param view */ public void startGame(View view) { tetrisViewAW.startGame(); gameStatusTip.setText("游戲運(yùn)行中"); } /** * 暫停游戲 */ public void pauseGame(View view) { tetrisViewAW.pauseGame(); gameStatusTip.setText("游戲已暫停"); } /** * 繼續(xù)游戲 */ public void continueGame(View view) { tetrisViewAW.continueGame(); gameStatusTip.setText("游戲運(yùn)行中"); } /** * 停止游戲 */ public void stopGame(View view) { tetrisViewAW.stopGame(); score.setText(""+0); gameStatusTip.setText("游戲已停止"); } /** * 向左滑動(dòng) */ public void toLeft(View view) { tetrisViewAW.toLeft(); } /** * 向右滑動(dòng) */ public void toRight(View view) { tetrisViewAW.toRight(); } /** * 向右滑動(dòng) */ public void toRoute(View view) { tetrisViewAW.route(); } }
TetrisActivityAW activity的xml文件
整個(gè)項(xiàng)目就是這些,代碼已經(jīng)全部貼出來(lái)了。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Android實(shí)現(xiàn)俄羅斯方塊的方法”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!