Swing俄罗斯方块游戏(二): 需要处理的关键点_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Swing俄罗斯方块游戏(二): 需要处理的关键点

Swing俄罗斯方块游戏(二): 需要处理的关键点

 2013/7/28 18:12:17  MouseLearnJava  程序员俱乐部  我要评论(0)
  • 摘要:上一篇博文介绍了俄罗斯方块游戏的图形选择与变换:Swing俄罗斯方块游戏(一):图形选择与变换-->[url]http://mouselearnjava.iteye.com/blog/1914513[/url].本文将介绍实现俄罗斯方块需要处理的关键点,这些关键点有如下几点:1.键盘事件的处理2.满行及其消行操作3.游戏结束判断4.游戏进度存储和加载5.游戏玩家得分排行榜......下面就结合代码一个一个地介绍这些点的实现:1.键盘事件的处理键盘事件的处理包括5个部分:a
  • 标签:游戏 Swing

上一篇博文介绍了俄罗斯方块游戏的图形选择与变换:
Swing俄罗斯方块游戏(一): 图形选择与变换 --> [url]http://mouselearnjava.iteye.com/blog/1914513 [/url]
.

本文将介绍实现俄罗斯方块需要处理的关键点,这些关键点有如下几点:

1. 键盘事件的处理
2. 满行及其消行操作
3. 游戏结束判断
4. 游戏进度存储和加载
5. 游戏玩家得分排行榜
... ...

下面就结合代码一个一个地介绍这些点的实现:
1. 键盘事件的处理
键盘事件的处理包括5个部分:
a)向左
class="java">	public void moveLeft(int flag[][]) {
		if (!isAlive) {
			return;
		}

		for (int i = 0; i < grid.length; i++) {
			tempX[i] = grid[i].x - 1;
			tempY[i] = grid[i].y;
		}

		if (tempX[0] >= RussiaGameConstant.LEFT
				&& flag[tempX[0]][tempY[0]] == 0
				&& tempX[1] >= RussiaGameConstant.LEFT
				&& flag[tempX[1]][tempY[1]] == 0
				&& tempX[2] >= RussiaGameConstant.LEFT
				&& flag[tempX[2]][tempY[2]] == 0
				&& tempX[3] >= RussiaGameConstant.LEFT
				&& flag[tempX[3]][tempY[3]] == 0) {
			for (int i = 0; i < grid.length; i++) {
				grid[i].x = tempX[i];
			}
		}
	}


b)向右与向左类似
c)向下与向下类似
d)空格键直接下降到底部

按下空格键一直向下的操作,其实就是在可以动的范围下,一直调用moveDown()方法e)向上键处理图形变换

每个图形,或有一种变换,或者有2种或者有四种变换,可以根据图形的特性进行处理。
比如,将“T字型”图型按照顺时针旋转,拥有四种变换,创建对象的时候已经确定了state是多少(state确定初始的位置是哪里),此后的变换只要对state加1并对4求余就可以知道怎么变换。
/**
 * @author Eric
 * @vesion 1.0
 * @desc T字型方块
 */
public class RussiaSquareThree extends RussiaSquare {

	private static final long serialVersionUID = -180232612076846292L;

	public RussiaSquareThree(){
		state = (int)(Math.random() * 4);
		switch(state)
		{
			case 0:
				grid[0].x = 4;
				grid[0].y = 0;
				grid[1].x = grid[0].x - 1;
				grid[1].y = grid[0].y + 1;
				grid[2].x = grid[0].x;
				grid[2].y = grid[0].y + 1;
				grid[3].x = grid[0].x + 1;
				grid[3].y = grid[0].y + 1;
				break;
				
			case 1:
				grid[0].x = 4;
				grid[0].y = 0;
				grid[1].x = grid[0].x;
				grid[1].y = grid[0].y + 1;
				grid[2].x = grid[0].x + 1;
				grid[2].y = grid[0].y + 1;
				grid[3].x = grid[0].x;
				grid[3].y = grid[0].y + 2;
				break;
				
			case 2:
				grid[0].x = 4;
				grid[0].y = 0;
				grid[1].x = grid[0].x + 1;
				grid[1].y = grid[0].y;
				grid[2].x = grid[0].x + 2;
				grid[2].y = grid[0].y;
				grid[3].x = grid[0].x + 1;
				grid[3].y = grid[0].y + 1;
				break;
				
			case 3:
				grid[0].x = 4;
				grid[0].y = 0;
				grid[1].x = grid[0].x - 1;
				grid[1].y = grid[0].y + 1;
				grid[2].x = grid[0].x;
				grid[2].y = grid[0].y + 1;
				grid[3].x = grid[0].x;
				grid[3].y = grid[0].y + 2;
				break;
				
			default:
				break;
		}
	}
	
	public void changeState(int flag[][])
	{
		switch(state)
		{
			case 0:
				tempX[0] = grid[0].x;
				tempY[0] = grid[0].y;
				tempX[1] = tempX[0];
				tempY[1] = tempY[0] + 1;
				tempX[2] = tempX[0] + 1;
				tempY[2] = tempY[0] + 1;
				tempX[3] = tempX[0];
				tempY[3] = tempY[0] + 2;
				isAllowChangeState(flag, 4);
				break;
				
			case 1:
				tempX[0] = grid[0].x - 1;
				tempY[0] = grid[0].y + 1;
				tempX[1] = tempX[0] + 1;
				tempY[1] = tempY[0];
				tempX[2] = tempX[0] + 2;
				tempY[2] = tempY[0];
				tempX[3] = tempX[0] + 1;
				tempY[3] = tempY[0] + 1;
				isAllowChangeState(flag, 4);
				break;
			case 2:
				tempX[0] = grid[0].x + 1;
				tempY[0] = grid[0].y - 1;
				tempX[1] = tempX[0] - 1;
				tempY[1] = tempY[0] + 1;
				tempX[2] = tempX[0];
				tempY[2] = tempY[0] + 1;
				tempX[3] = tempX[0];
				tempY[3] = tempY[0] + 2;
				isAllowChangeState(flag, 4);
				break;
				
			case 3:
				tempX[0] = grid[0].x;
				tempY[0] = grid[0].y;
				tempX[1] = tempX[0] - 1;
				tempY[1] = tempY[0] + 1;
				tempX[2] = tempX[0];
				tempY[2] = tempY[0] + 1;
				tempX[3] = tempX[0] + 1;
				tempY[3] = tempY[0] + 1;
				isAllowChangeState(flag, 4);
				break;
				
			default:
				break;
		}
	}
}


private class KeyHandler implements KeyListener {
		public void keyPressed(KeyEvent event) {
			if (!gameState.isRunState()) {
				return;
			}

			int keyCode = event.getKeyCode();
			switch (keyCode) {
			case KeyEvent.VK_LEFT:
				sr1.moveLeft(flag);
				break;

			case KeyEvent.VK_RIGHT:
				sr1.moveRight(flag);
				break;

			case KeyEvent.VK_UP:
				sr1.changeState(flag);
				break;

			case KeyEvent.VK_DOWN:
				sr1.moveDown(flag);
				break;
			case KeyEvent.VK_SPACE:
				while (sr1.isAlive) {
					sr1.moveDown(flag);
				}
			default:
				break;
			}
			repaint();
		}

		public void keyReleased(KeyEvent event) {
		}

		public void keyTyped(KeyEvent event) {
		}
	}


2. 满行及其消行操作
用一个二维数组记录当前屏幕上的方块状态,0表示没有方块,1表示有方块。
满行的判断就归结到某一行1的个数是否等于该行列的总数,如果是就满足满行条件。

当有满行情况出现的时候,需要进行消除和计分操作。

消除行的一个做法就是将该行以上的行通通往下移,移动之后在将第一行的flag全部置为0.
public class RussiaGamePanel extends JPanel {
	private class TimerAction implements ActionListener, Serializable {

		private static final long serialVersionUID = -6117702515382009989L;

		public void actionPerformed(ActionEvent event) {
			if (!gameState.isRunState()) {
				return;
			}

			//满行的个数
			int num = 0;
			
			sr1.moveDown(flag);

			if (!sr1.isAlive) {
				for (int i = 0; i < 4; i++) {
					flag[sr1.grid[i].x][sr1.grid[i].y] = 1;
					color[sr1.grid[i].x][sr1.grid[i].y] = sr1.color;
				}

				judgeGameOver();

				for (int i = RussiaGameConstant.UP; i <= RussiaGameConstant.DOWN; i++) {
					int count = 0;
					for (int j = RussiaGameConstant.LEFT; j <= RussiaGameConstant.RIGHT; j++) {
						count += flag[j][i];
					}

					/*
					 * flag[i][j] =1 表示这个位置有小方块,如果一行的位置都有小方块,那么满行的个数num加1.
					 * 并且消除行。
					 */
					if (count == RussiaGameConstant.GRID_COLUMN_NUMBER) {
						num++;

						/**
						 * 消除行操作。
						 */
						for (int m = i; m > RussiaGameConstant.UP; m--) {
							for (int n = RussiaGameConstant.LEFT; n <= RussiaGameConstant.RIGHT; n++) {
								flag[n][m] = flag[n][m - 1];
								color[n][m] = color[n][m - 1];
							}
						}
						/*
						 * 重新将第一行的flag[s][0]置为0
						 */
						for (int s = RussiaGameConstant.LEFT; s <= RussiaGameConstant.RIGHT; s++) {
							flag[s][RussiaGameConstant.UP] = 0;
						}
					}
				}
				
				/*
				 * 将下一个图形作为当前运动的图形,并随机产生下一个图形。
				 */
				sr1 = sr2;
				sr2 = RussiaSquareFactory.generateNextRussiaSquareByRandom();
			}
			// 计算分数
			calculateScore(num);

			repaint();
		}
	}
	
	/**
	 * @param num
	 *            方块满行的个数
	 */
	private void calculateScore(int num)
	{
		switch(num)
		{
		case 1: score += 10; break;
		case 2: score += 20; break;
		case 3: score += 50; break;
		case 4: score += 100; break;
		default: break;
		
		}
	}

}


3. 游戏结束判断

俄罗斯方块游戏结束的判断其实很简单,只要判断第一行的标记位是否有1即可。
	private boolean isTopTouched() {
		for (int i = RussiaGameConstant.LEFT; i <= RussiaGameConstant.RIGHT; i++) {
			if (flag[i][RussiaGameConstant.UP] == 1) {
				return true;
			}
		}
		return false;
	}


4. 游戏进度存储和加载
5. 游戏玩家得分排行榜


关于4,5两点,本文不在这里展开,因为这些功能以前在写贪吃蛇游戏的博文中介绍了。
Swing贪吃蛇游戏(三):增加游戏进度存储和加载功能 >>>
http://mouselearnjava.iteye.com/blog/1914225

Swing贪吃蛇游戏(四):增加游戏得分排行榜功能  >>>
http://mouselearnjava.iteye.com/blog/1914316

拥有所有功能的详细代码请参考附件MyRussiaGame.7z

俄罗斯方块游戏的界面如下:










  • 大小: 34.2 KB
  • 大小: 24.4 KB
  • 大小: 9.9 KB
  • MyRussiaGame.7z (27.3 KB)
  • 下载次数: 1
  • 查看图片附件
发表评论
用户名: 匿名