俄罗斯方块原本是前苏联(俄罗斯)科学家阿列克谢·帕基特诺夫(Алексей Леонидович Пажитнов)在1984年6月利用空闲时间所编写的游戏程序 ,据说游戏的作者最喜欢网球(Tennis)运动,于是,他把来源于希腊语的tetra(意为“四”)与其结合,造了“tetris”一词,之后开始提供授权给各个游戏公司。在那个时代,游戏机甚至于计算机的运算能力普遍较低(当时盛行传说中的640KB内存……),游戏堪称匮乏之极,因此简单易写的俄罗斯方块迅速普及, 造成各平台上软件大量发行的“恐怖”现象。
传说中Game Boy版的俄罗斯方块层在日本大卖424万套,是Game Boy史上卖得最好的游戏。海湾战争时,也是前线美军最常拿来消磨时间的游戏之一(如果鄙人没记错的话,GB是美军当时的标准装备之一|||,传说美军是一边玩着口袋妖怪,一边战胜了伊拉克~~~)。
俄罗斯方块的游戏规则:
* 俄罗斯方块是由下面这几种常见方块构成,全部为四点组成:
o 长条:一次最多消除四层
o 7(左右):最多消除三层,或消除二层
o 田:消除一至二层
o S(左右):最多二层,容易造成孔洞
o T:最多二层
o 部分游戏有单格方块,可以穿透固定的方块到达最下层空位。其他的改版中出现更多特别的造型。
游戏方式:
* 方块会从区域上方开始缓慢继续落下。
* 玩家可以做的操作有:以90度为单位旋转方块,以格子为单位左右移动方块,让方块加速落下。
* 方块移到区域最下方或是着地到其他方块上无法移动时,就会固定在该处,而新的方块出现在区域上方开始落下。
* 当区域中某一列横向格子全部由方块填满,则该列会消失并成为玩家的得分。同时删除的列数越多,得分指数上升。
* 当固定的方块堆到区域最上方而无法消除层数时,则游戏结束。
一般来说,游戏还会提示下一个要落下的方块,熟练的玩家会计算到下一个方块,评估现在要如何进行。由于游戏能不断进行下去,对商业用游戏不太理想,所以一般还会随着游戏的进行而加速提高难度,通常打到最后时,多眨一次眼就可能牺牲掉……
PS:另外补充一点,俄罗斯方块事实上是有知识产权的。最初的俄罗斯方块知识产权由前苏联外国贸易协会(ELORG)持有,在苏联over之后,由The Tetris Company继承,但由于“非法”使用者数量过大,事实上陷入了无法收取任何使用费的窘态中。自1990年代初期开始,全世界大量流行的小型游戏机,多半都有类似于俄罗斯方块的游戏,不过——9成9都不是授权产品。
闲话少说,既然是如此简单的东东,今天我们也用Java写两个俄罗斯方块好了。
示例源码下载地址: http://code.google.com/p/loon-simple/downloads/list
与往常一样,一个例子写两台平台的,首先是PC版的实现,源码如下:
package org.loon.game.test; import java.awt.Graphics2D; import java.awt.Image; /** * * Copyright 2008 - 2009 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loonframework * @author chenpeng * @email:[email protected] * @version 0.1 */ public class TetrisField { private Block stoneCurrent; private Block stoneNext; private int[][] stonePosition; private int[][] gameFieldStones; private int curLines = 0, curLevel = 1, curPoints = 0, row, col; private boolean gameOver = false; public TetrisField(int row, int col) { int i = 0; int j = 0; this.row = row; this.col = col; stonePosition = new int[4][2]; gameFieldStones = new int[row][col]; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { gameFieldStones[i][j] = 0; } } } public int getCol() { return col; } public int getRow() { return row; } public void createCurrentStone(int NextStoneID) { stoneCurrent = stoneNext; createNextStone(NextStoneID); stonePosition = stoneCurrent.getStartPosition(); if (gameFieldStones[5][4] != 0) { gameOver = true; } setCurrentStonePosition(stonePosition); } public void createNextStone(int stoneID) { stoneNext = new Block(stoneID); } public void setCurrentStonePosition(int[][] StoneNewPosition) { int i; for (i = 0; i < 4; i++) { gameFieldStones[StoneNewPosition[i][0]][StoneNewPosition[i][1]] = stoneCurrent .getBlockID(); } } public void setCurrentStonePosition(int[][] StoneNewPosition, int[][] StoneOldPosition) { int i; for (i = 0; i < 4; i++) { gameFieldStones[StoneOldPosition[i][0]][StoneOldPosition[i][1]] = 0; } for (i = 0; i < 4; i++) { gameFieldStones[StoneNewPosition[i][0]][StoneNewPosition[i][1]] = stoneCurrent .getBlockID(); } stonePosition = StoneNewPosition; } public boolean incrementPositionY(boolean isThread) { int i; int[][] StoneNewPosition = new int[4][2]; int canStart = 0; for (i = 0; i < 4; i++) { if (stonePosition[i][1] > 3) { canStart = 1; } } if (canStart == 1 || isThread) { for (i = 0; i < 4; i++) { StoneNewPosition[i][1] = stonePosition[i][1] + 1; StoneNewPosition[i][0] = stonePosition[i][0]; } if (!hasCollision(StoneNewPosition)) { setCurrentStonePosition(StoneNewPosition, stonePosition); return true; } else { setCurrentStonePosition(stonePosition); return false; } } return false; } public void rightPositionX() { int i; int[][] StoneNewPosition = new int[4][2]; int canStart = 0; for (i = 0; i < 4; i++) { if (stonePosition[i][1] > 3) { canStart = 1; } } if (canStart == 1) { for (i = 0; i < 4; i++) { StoneNewPosition[i][1] = stonePosition[i][1]; StoneNewPosition[i][0] = stonePosition[i][0] + 1; } if (!hasCollision(StoneNewPosition)) { setCurrentStonePosition(StoneNewPosition, stonePosition); } else { setCurrentStonePosition(stonePosition); } } } public void leftPositionX() { int i; int[][] StoneNewPosition = new int[4][2]; int canStart = 0; for (i = 0; i < 4; i++) { if (stonePosition[i][1] > 3) { canStart = 1; } } if (canStart == 1) { for (i = 0; i < 4; i++) { StoneNewPosition[i][1] = stonePosition[i][1]; StoneNewPosition[i][0] = stonePosition[i][0] - 1; } if (!hasCollision(StoneNewPosition)) { setCurrentStonePosition(StoneNewPosition, stonePosition); } else { setCurrentStonePosition(stonePosition); } } } public void rotateStone() { int[][] StoneNewPosition = new int[4][2]; StoneNewPosition = stoneCurrent.rotateStone(stonePosition); if (!hasCollision(StoneNewPosition)) { setCurrentStonePosition(StoneNewPosition, stonePosition); } else { stoneCurrent.noRoate(); setCurrentStonePosition(stonePosition); } } public boolean hasCollision(int[][] StoneNewPosition) { int i; for (i = 0; i < 4; i++) { gameFieldStones[stonePosition[i][0]][stonePosition[i][1]] = 0; } for (i = 0; i < 4; i++) { if (StoneNewPosition[i][0] < 0) { return true; } else if (StoneNewPosition[i][0] == row) { return true; } else if (StoneNewPosition[i][1] == col) { return true; } else if (gameFieldStones[StoneNewPosition[i][0]][StoneNewPosition[i][1]] != 0) { return true; } } return false; } public boolean hasLines() { int i = 0; int j = 0; int[] lines = new int[4]; int Quantity = 0; boolean isLine = false; for (i = 3; i < col; i++) { for (j = 0; j < row; j++) { isLine = true; if (gameFieldStones[j][i] == 0) { isLine = false; break; } } if (isLine == true) { lines[Quantity] = i; Quantity++; } } if (Quantity > 0) { int[][] TempGameField = new int[row][col]; int sum = 0; curLines += Quantity; curLevel = Math.round(curLines / row) + 1; //最大等级为20 if (curLevel > 20) { curLevel = 20; } curPoints += Math.pow((row * curLevel), Quantity); for (i = col - 1; i > 3; i--) { for (j = 0; j < row; j++) { isLine = true; if (gameFieldStones[j][i] == 0) { isLine = false; break; } } if (isLine == false) { for (j = 0; j < row; j++) { TempGameField[j][i + sum] = gameFieldStones[j][i]; } } else { sum++; } } for (i = 0; i < 4; i++) { for (j = 0; j < row; j++) { TempGameField[j][i] = gameFieldStones[j][i]; } } gameFieldStones = TempGameField; return true; } else { return false; } } public int[][] getStonePosition() { return gameFieldStones; } public void draw(Graphics2D g, Image[] stones) { int nextStone = getNextStone(); switch (nextStone) { case 1: g.drawImage(stones[1], 240, 60, null); g.drawImage(stones[1], 260, 60, null); g.drawImage(stones[1], 240, 80, null); g.drawImage(stones[1], 260, 80, null); break; case 2: g.drawImage(stones[2], 220, 70, null); g.drawImage(stones[2], 240, 70, null); g.drawImage(stones[2], 260, 70, null); g.drawImage(stones[2], 280, 70, null); break; case 3: g.drawImage(stones[3], 250, 60, null); g.drawImage(stones[3], 230, 80, null); g.drawImage(stones[3], 250, 80, null); g.drawImage(stones[3], 270, 80, null); break; case 4: g.drawImage(stones[4], 270, 60, null); g.drawImage(stones[4], 230, 80, null); g.drawImage(stones[4], 250, 80, null); g.drawImage(stones[4], 270, 80, null); break; case 5: g.drawImage(stones[5], 230, 60, null); g.drawImage(stones[5], 230, 80, null); g.drawImage(stones[5], 250, 80, null); g.drawImage(stones[5], 270, 80, null); break; case 6: g.drawImage(stones[6], 230, 60, null); g.drawImage(stones[6], 250, 60, null); g.drawImage(stones[6], 250, 80, null); g.drawImage(stones[6], 270, 80, null); break; case 7: g.drawImage(stones[7], 250, 60, null); g.drawImage(stones[7], 270, 60, null); g.drawImage(stones[7], 230, 80, null); g.drawImage(stones[7], 250, 80, null); break; } } public int getNextStone() { if (stoneNext == null) { stoneNext = new Block((int) Math.round(Math.random() * 6) + 1); } return stoneNext.getBlockID(); } public int getLines() { return curLines; } public int getLevel() { return curLevel; } public int getPoints() { return curPoints; } public boolean isGameOver() { return gameOver; } class Block { private int blockID; private int[][] startPosition = new int[4][2]; private int rotatePosition = 0; public Block(int blockID) { setBlockID(blockID); createStone(); } private void createStone() { switch (blockID) { case 1: startPosition[0][0] = 4; startPosition[0][1] = 2; startPosition[1][0] = 5; startPosition[1][1] = 2; startPosition[2][0] = 4; startPosition[2][1] = 3; startPosition[3][0] = 5; startPosition[3][1] = 3; break; case 2: startPosition[0][0] = 5; startPosition[0][1] = 0; startPosition[1][0] = 5; startPosition[1][1] = 1; startPosition[2][0] = 5; startPosition[2][1] = 2; startPosition[3][0] = 5; startPosition[3][1] = 3; break; case 3: startPosition[0][0] = 5; startPosition[0][1] = 2; startPosition[1][0] = 4; startPosition[1][1] = 3; startPosition[2][0] = 5; startPosition[2][1] = 3; startPosition[3][0] = 6; startPosition[3][1] = 3; break; case 4: startPosition[0][0] = 4; startPosition[0][1] = 1; startPosition[1][0] = 4; startPosition[1][1] = 2; startPosition[2][0] = 4; startPosition[2][1] = 3; startPosition[3][0] = 5; startPosition[3][1] = 3; break; case 5: startPosition[0][0] = 5; startPosition[0][1] = 1; startPosition[1][0] = 5; startPosition[1][1] = 2; startPosition[2][0] = 5; startPosition[2][1] = 3; startPosition[3][0] = 4; startPosition[3][1] = 3; break; case 6: startPosition[0][0] = 5; startPosition[0][1] = 1; startPosition[1][0] = 4; startPosition[1][1] = 2; startPosition[2][0] = 5; startPosition[2][1] = 2; startPosition[3][0] = 4; startPosition[3][1] = 3; break; case 7: startPosition[0][0] = 4; startPosition[0][1] = 1; startPosition[1][0] = 4; startPosition[1][1] = 2; startPosition[2][0] = 5; startPosition[2][1] = 2; startPosition[3][0] = 5; startPosition[3][1] = 3; break; } } public int[][] rotateStone(int[][] currentPosition) { int[][] newPosition = new int[4][2]; int x, y; switch (blockID) { case 2: if (rotatePosition == 0) { x = currentPosition[3][0]; y = currentPosition[3][1]; newPosition[0][0] = x - 3; newPosition[0][1] = y; newPosition[1][0] = x - 2; newPosition[1][1] = y; newPosition[2][0] = x - 1; newPosition[2][1] = y; newPosition[3][0] = x; newPosition[3][1] = y; rotatePosition = 1; } else { x = currentPosition[3][0]; y = currentPosition[3][1]; newPosition[0][0] = x; newPosition[0][1] = y - 3; newPosition[1][0] = x; newPosition[1][1] = y - 2; newPosition[2][0] = x; newPosition[2][1] = y - 1; newPosition[3][0] = x; newPosition[3][1] = y; rotatePosition = 0; } return newPosition; case 3: if (rotatePosition == 0) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x; newPosition[0][1] = y - 1; newPosition[1][0] = x; newPosition[1][1] = y + 1; newPosition[2][0] = x; newPosition[2][1] = y; newPosition[3][0] = x + 1; newPosition[3][1] = y; rotatePosition = 1; } else if (rotatePosition == 1) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x; newPosition[0][1] = y + 1; newPosition[1][0] = x - 1; newPosition[1][1] = y; newPosition[2][0] = x; newPosition[2][1] = y; newPosition[3][0] = x + 1; newPosition[3][1] = y; rotatePosition = 2; } else if (rotatePosition == 2) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x; newPosition[0][1] = y - 1; newPosition[1][0] = x - 1; newPosition[1][1] = y; newPosition[2][0] = x; newPosition[2][1] = y; newPosition[3][0] = x; newPosition[3][1] = y + 1; rotatePosition = 3; } else if (rotatePosition == 3) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x - 1; newPosition[0][1] = y; newPosition[1][0] = x + 1; newPosition[1][1] = y; newPosition[2][0] = x; newPosition[2][1] = y; newPosition[3][0] = x; newPosition[3][1] = y - 1; rotatePosition = 0; } return newPosition; case 4: if (rotatePosition == 0) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x; newPosition[0][1] = y; newPosition[1][0] = x + 1; newPosition[1][1] = y; newPosition[2][0] = x + 2; newPosition[2][1] = y; newPosition[3][0] = x + 2; newPosition[3][1] = y - 1; rotatePosition = 1; } else if (rotatePosition == 1) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x - 1; newPosition[0][1] = y - 2; newPosition[1][0] = x; newPosition[1][1] = y - 2; newPosition[2][0] = x; newPosition[2][1] = y - 1; newPosition[3][0] = x; newPosition[3][1] = y; rotatePosition = 2; } else if (rotatePosition == 2) { x = currentPosition[1][0]; y = currentPosition[1][1]; newPosition[0][0] = x - 2; newPosition[0][1] = y + 1; newPosition[1][0] = x - 2; newPosition[1][1] = y; newPosition[2][0] = x - 1; newPosition[2][1] = y; newPosition[3][0] = x; newPosition[3][1] = y; rotatePosition = 3; } else if (rotatePosition == 3) { x = currentPosition[1][0]; y = currentPosition[1][1]; newPosition[0][0] = x; newPosition[0][1] = y; newPosition[1][0] = x; newPosition[1][1] = y + 1; newPosition[2][0] = x; newPosition[2][1] = y + 2; newPosition[3][0] = x + 1; newPosition[3][1] = y + 2; rotatePosition = 0; } return newPosition; case 5: if (rotatePosition == 0) { x = currentPosition[1][0]; y = currentPosition[1][1]; newPosition[0][0] = x - 2; newPosition[0][1] = y - 1; newPosition[1][0] = x - 1; newPosition[1][1] = y - 1; newPosition[2][0] = x; newPosition[2][1] = y - 1; newPosition[3][0] = x; newPosition[3][1] = y; rotatePosition = 1; } else if (rotatePosition == 1) { x = currentPosition[0][0]; y = currentPosition[0][1]; newPosition[0][0] = x; newPosition[0][1] = y; newPosition[1][0] = x + 1; newPosition[1][1] = y; newPosition[2][0] = x; newPosition[2][1] = y + 1; newPosition[3][0] = x; newPosition[3][1] = y + 2; rotatePosition = 2; } else if (rotatePosition == 2) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x; newPosition[0][1] = y; newPosition[1][0] = x; newPosition[1][1] = y + 1; newPosition[2][0] = x + 1; newPosition[2][1] = y + 1; newPosition[3][0] = x + 2; newPosition[3][1] = y + 1; rotatePosition = 3; } else if (rotatePosition == 3) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x; newPosition[0][1] = y; newPosition[1][0] = x + 1; newPosition[1][1] = y; newPosition[2][0] = x + 1; newPosition[2][1] = y - 1; newPosition[3][0] = x + 1; newPosition[3][1] = y - 2; rotatePosition = 0; } return newPosition; case 6: if (rotatePosition == 0) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x - 1; newPosition[0][1] = y; newPosition[1][0] = x; newPosition[1][1] = y + 1; newPosition[2][0] = x; newPosition[2][1] = y; newPosition[3][0] = x + 1; newPosition[3][1] = y + 1; rotatePosition = 1; } else { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x; newPosition[0][1] = y - 1; newPosition[1][0] = x - 1; newPosition[1][1] = y; newPosition[2][0] = x; newPosition[2][1] = y; newPosition[3][0] = x - 1; newPosition[3][1] = y + 1; rotatePosition = 0; } return newPosition; case 7: if (rotatePosition == 0) { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x - 1; newPosition[0][1] = y - 1; newPosition[1][0] = x - 1; newPosition[1][1] = y; newPosition[2][0] = x; newPosition[2][1] = y; newPosition[3][0] = x; newPosition[3][1] = y + 1; rotatePosition = 1; } else { x = currentPosition[2][0]; y = currentPosition[2][1]; newPosition[0][0] = x + 1; newPosition[0][1] = y; newPosition[1][0] = x - 1; newPosition[1][1] = y + 1; newPosition[2][0] = x; newPosition[2][1] = y; newPosition[3][0] = x; newPosition[3][1] = y + 1; rotatePosition = 0; } return newPosition; default: return currentPosition; } } public void noRoate() { rotatePosition--; if (rotatePosition == -1) { rotatePosition = 3; } } public int[][] getStartPosition() { return startPosition; } public void setBlockID(int blockID) { this.blockID = blockID; } public int getBlockID() { return blockID; } } }
package org.loon.game.test; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import org.loon.framework.game.simple.GameScene; import org.loon.framework.game.simple.core.Deploy; import org.loon.framework.game.simple.core.LTimer; import org.loon.framework.game.simple.core.LTimerContext; import org.loon.framework.game.simple.core.Screen; import org.loon.framework.game.simple.utils.GraphicsUtils; /** * Copyright 2008 - 2009 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loonframework * @author chenpeng * @email��[email protected] * @version 0.1 */ public class Main extends Screen { private int curLevel = 1, blockSize = 20; private boolean gameStart; private final static Color emptyColor = new Color(120, 120, 190, 90), gridColor = new Color(255, 255, 255, 25); private LTimer delay; private TetrisField gameField; private Image[] stones = new Image[8]; private Image background, styleImage; public int positionX; public int positionY; public Main() { // 背景图 background = GraphicsUtils.loadImage("images/background2.jpg"); // 装饰图 styleImage = GraphicsUtils.loadImage("images/metalayer.png"); // 获得俄罗斯方块小图 Image[] blocks = GraphicsUtils.getSplitImages("images/block.png", blockSize, blockSize); for (int i = 0; i < blocks.length; i++) { stones[i + 1] = blocks[i]; } setBackground(background); delay = new LTimer(100); } public void initialize() { gameStart = true; // 默认游戏区域(网格)大小为横10,竖24 gameField = new TetrisField(10, 24); gameField.createNextStone(((int) Math.round(Math.random() * 6) + 1)); gameField.createCurrentStone(((int) Math.round(Math.random() * 6) + 1)); } public void alter(LTimerContext timer) { // 自动计时 if (delay.action(timer.getTimeSinceLastUpdate())) { // 已初始化并且非游戏失败 if (gameStart && !gameField.isGameOver()) { if (!gameField.incrementPositionY(true)) { gameField.createCurrentStone(((int) Math.round(Math .random() * 6) + 1)); if (gameField.hasLines()) { curLevel = gameField.getLevel(); } } delay.setDelay(300 / curLevel); } } } /** * 绘制游戏画面 */ public void draw(Graphics2D g) { if (gameStart) { int x, y; // 默认游戏区域(网格)大小为横10,竖24 int[][] arrayStones = gameField.getStonePosition(); for (x = 0; x < gameField.getRow(); x++) { for (y = 0; y < gameField.getCol(); y++) { g.setColor(emptyColor); g.fillRect(x * blockSize, y * blockSize, blockSize, blockSize); g.setColor(gridColor); g.drawRect(x * blockSize, y * blockSize, blockSize, blockSize); if (arrayStones[x][y] != 0) { g.drawImage(stones[arrayStones[x][y]], x * blockSize, y * blockSize, null); } } } if (gameField.isGameOver()) { g.setColor(Color.white); g.drawString("GAME OVER", 120, 160); return; } g.drawImage(styleImage, 210, 30, null); // 绘制游戏方块 gameField.draw(g, stones); g.setColor(Color.white); g.drawString("等级:" + Integer.toString(gameField.getLevel()), 240, 220); g.drawString("消层:" + Integer.toString(gameField.getLines()), 240, 260); g.drawString("得分:" + Integer.toString(gameField.getPoints()), 240, 300); } else { g.setColor(Color.white); g.drawString("GAME START", 110, 160); g.drawString("请按下 [ENTER]", 105, 200); } } /** * 点击鼠标 */ public void leftClick(MouseEvent e) { } public void middleClick(MouseEvent e) { } public void rightClick(MouseEvent e) { } /** * 点击键盘 */ public void onKey(KeyEvent e) { int key = e.getKeyCode(); if (gameStart) { // 转换方向 if (key == KeyEvent.VK_UP) { gameField.rotateStone(); // 向右 } else if (key == KeyEvent.VK_RIGHT) { gameField.rightPositionX(); // 向左 } else if (key == KeyEvent.VK_LEFT) { gameField.leftPositionX(); // 加速向下 } else if (key == KeyEvent.VK_DOWN) { gameField.incrementPositionY(true); // 重启游戏 } else if (key == KeyEvent.VK_ESCAPE) { if (gameField != null && gameField.isGameOver()) { initialize(); } } } else { // 开始游戏 if (key == KeyEvent.VK_ENTER) { initialize(); } } } public void onKeyUp(KeyEvent e) { } public static void main(String[] args) { GameScene frame = new GameScene("俄罗斯方块", 320, 480); Deploy deploy = frame.getDeploy(); deploy.setScreen(new Main()); deploy.setShowFPS(true); deploy.setLogo(false); deploy.setFPS(100); deploy.mainLoop(); frame.showFrame(); } }
然后,是Android版的(TetrisField部分除Image与Graphics2D外完全一致,故不再粘贴):
package org.loon.framework.android.game; import android.graphics.Color; import android.view.KeyEvent; import android.view.MotionEvent; /** * * Copyright 2008 - 2009 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loonframework * @author chenpeng * @email:[email protected] * @version 0.1 */ public class ScreenTest2 extends LAScreen { private int curLevel = 1, blockSize = 20; private boolean gameStart; private final static int emptyColor = Color.argb(90, 120, 120, 190), gridColor = Color.argb(25, 255, 255, 255); private LTimer delay; private TetrisField gameField; private LAImage[] stones = new LAImage[8]; private LAImage background, styleImage; public int positionX; public int positionY; public ScreenTest2() { // 背景图 background = getLAImage("background2.jpg"); // 装饰图 styleImage = getLAImage("metalayer.png"); // 获得俄罗斯方块小图 LAImage[] blocks = getSplitLAImages("block.png", blockSize, blockSize); for (int i = 0; i < blocks.length; i++) { stones[i + 1] = blocks[i]; } delay = new LTimer(100); } public void initialize() { gameStart = true; // 默认游戏区域(网格)大小为横10,竖24 gameField = new TetrisField(10, 24); gameField.createNextStone(((int) Math.round(Math.random() * 6) + 1)); gameField.createCurrentStone(((int) Math.round(Math.random() * 6) + 1)); } public void alter(LTimerContext timer) { // 自动计时 if (delay.action(timer.getTimeSinceLastUpdate())) { // 已初始化并且非游戏失败 if (gameStart && !gameField.isGameOver()) { if (!gameField.incrementPositionY(true)) { gameField.createCurrentStone(((int) Math.round(Math .random() * 6) + 1)); if (gameField.hasLines()) { curLevel = gameField.getLevel(); } } delay.setDelay(300 / curLevel); } } } /** * 绘制拼图 */ public void draw(LAGraphics g) { g.drawImage(background, 0, 0); if (gameStart) { int x, y; // 默认游戏区域(网格)大小为横10,竖24 int[][] arrayStones = gameField.getStonePosition(); for (x = 0; x < gameField.getRow(); x++) { for (y = 0; y < gameField.getCol(); y++) { g.setColor(emptyColor); g.fillRect(x * blockSize, y * blockSize, blockSize, blockSize); g.setColor(gridColor); g.drawRect(x * blockSize, y * blockSize, blockSize, blockSize); if (arrayStones[x][y] != 0) { g.setAlpha(1.0F); g.drawImage(stones[arrayStones[x][y]], x * blockSize, y * blockSize); } } } g.setAlpha(1.0F); if (gameField.isGameOver()) { g.setColor(Color.WHITE); g.drawString("GAME OVER", 120, 160); return; } g.drawImage(styleImage, 210, 30); // 绘制游戏方块 gameField.draw(g, stones); g.setColor(Color.WHITE); g.drawString("等级:" + Integer.toString(gameField.getLevel()), 240, 220); g.drawString("消层:" + Integer.toString(gameField.getLines()), 240, 260); g.drawString("得分:" + Integer.toString(gameField.getPoints()), 240, 300); } else { g.setColor(Color.WHITE); g.drawString("GAME START", 110, 160); g.drawString("请按下 [ENTER]", 105, 200); } } /** * 点击触摸屏 */ public boolean onTouchDown(MotionEvent e) { return false; } /** * 点击按键 */ public boolean onKeyDown(int keyCode, KeyEvent e) { int key = e.getKeyCode(); if (gameStart) { // 转换方向 if (key == KeyEvent.KEYCODE_DPAD_UP) { gameField.rotateStone(); // 向右 } else if (key == KeyEvent.KEYCODE_DPAD_RIGHT) { gameField.rightPositionX(); // 向左 } else if (key == KeyEvent.KEYCODE_DPAD_LEFT) { gameField.leftPositionX(); // 加速向下 } else if (key == KeyEvent.KEYCODE_DPAD_DOWN) { gameField.incrementPositionY(true); // 重启游戏 } else if (key == KeyEvent.KEYCODE_ENTER) { if (gameField != null && gameField.isGameOver()) { initialize(); } } } else { // 开始游戏 if (key == KeyEvent.KEYCODE_ENTER) { initialize(); } } return false; } public boolean onKeyUp(int keyCode, KeyEvent e) { return false; } public boolean onTouchMove(MotionEvent e) { return false; } public boolean onTouchUp(MotionEvent e) { return false; } }
示例源码下载地址: http://code.google.com/p/loon-simple/downloads/list
与前面的实例一样,都是先在PC上通过LGame-Simple调好,而后做函数替换移植到Android,写PC版用了一个小时,移植过去5分钟不到,吼吼吼……