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

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

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

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

下面就结合代码一个一个地介绍这些点的实现:
[b]1. 键盘事件的处理[/b]
键盘事件的处理包括5个部分:
a)向左
	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)空格键直接下降到底部

[color=blue][b]按下空格键一直向下的操作,其实就是在可以动的范围下,一直调用moveDown()方法[/b][/color]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) {
}
}


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

当有满行情况出现的时候,需要进行消除和计分操作。
[color=blue][b]
消除行的一个做法就是将该行以上的行通通往下移,移动之后在将第一行的flag全部置为0.[/b][/color]
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;

}
}

}


[b]3. 游戏结束判断[/b]

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


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

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

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

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

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


[img]http://dl2.iteye.com/upload/attachment/0087/5443/0b1b8a79-522a-37f4-ae21-84fff0dda7ad.jpg[/img]


[img]http://dl2.iteye.com/upload/attachment/0087/5445/88bbd495-50c8-3f8a-9c50-322cb394e7d2.jpg[/img]


[img]http://dl2.iteye.com/upload/attachment/0087/5447/632e569e-e762-3597-924d-f89244615d10.jpg[/img]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值