引言:这几天我由于生病,影响了写代码的进度,十分遗憾!好了,我会接住上一篇的继续写下去,希望和我一样不顾一切喜欢、热爱软件和游戏开发的朋友们继续支持我,你们的回帖就是对我最大的支持,要说明的是:如果发现文章或代码中的错误之处请指出,欢迎所有阅读这篇文章的人,我们一起进步,一起提高!
步入正题:这篇讲的是方块生成与坐标控制模块TetrisBlock类。
在TetrisBlock类中定义了7种方块的不同形状和对应的颜色,都有一个对应的ID,分别为1—7,且对于每种方块来说,其颜色均是固定,方块由16个4*4的小方格组成,故在逻辑上可以使用4*4的二维数组表示,又由于每个方块都有4种旋转变化,故可以用4*4*4的三维数组表示一个方块的所有状态。
例如,“T”形方块可由如下的数组来表示:
protected int blockpattern1[][][]={//blockpattern1:“T”字及四种旋转形状
{{0,0,0,0},{1,1,1,0},{0,1,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}}
};
小tips:这一章代码是俄罗斯方块生成与控制算法,应该是比较重要的,所以我的注释写得尽可能的多,希望所有的人都能看得明白!
1.方块生成与坐标控制模块(TetrisBlock类)
程序源代码如下:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package game.teris;
import java.util.Random;
import javax.microedition.lcdui.Graphics;
/**
*
* @author dongdong
*/
public class TetrisBlock {
//各种方块,1-7为活动方块的颜色,8为砖墙的颜色
public static final int[] BRICK_COLORS = {
0x00FF0000,
0x0000FF00,
0x00FFFF00,
0x000000FF,
0x00FF00FF,
0x0000FFFF,
0x00C0DCC0,
0x00808080
};
/**
* blockpattern的编码规则:blockpattern表示一种方块的形状
* 每种方块的颜色是固定的
* 对于一个方块,用一个三维数组表示,第一维用rot表示(旋转值),第二维用
* x表示(行),第三维用y表示(列)
* 第一维最重要即rot,表示旋转值
*/
protected int blockpattern1[][][]={//blockpattern1:“T”字及四种旋转形状
{{0,0,0,0},{1,1,1,0},{0,1,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}}
};
protected int blockpattern2[][][]={//blockpattern2:“田”字及四种旋转形状
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}
};
protected int blockpattern3[][][]={//blockpattern3:“L”字及四种旋转形状
{{1,1,0,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}},
{{0,0,1,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,0,0,0},{1,1,0,0},{0,0,0,0}},
{{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}}
};
protected int blockpattern4[][][]={//blockpattern4:反“L”字及四种旋转形状
{{1,1,0,0},{1,0,0,0},{1,0,0,0},{0,0,0,0}},
{{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{0,1,0,0},{1,1,0,0},{0,0,0,0}},
{{1,0,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}}
};
protected int blockpattern5[][][]={//blockpattern5:反“Z”字及四种旋转形状
{{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},
{{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},
{{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}
};
protected int blockpattern6[][][]={//blockpattern6:“Z”字及四种旋转形状
{{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}},
{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},
{{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}},
{{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}}
};
protected int blockpattern7[][][]={//blockpattern7:“1”字及四种旋转形状
{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}},
{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
{{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}}
};
/*当前下坠方块形状,为以上定义的7种方块之一*/
private int blockpattern[][][];
/*下一个方块形状,显示在游戏容器的右边*/
private int blockNextpattern[][][];
//blockpattern左上角x坐标
//x=i表示左上角距离游戏容器左上角x轴上i个小砖块单位
private int x;
//blockpattern左上角y坐标
//y=i表示左上角距离游戏容器左上角y轴上i个小砖块单位
private int y;
//x的旧值
private int oldx;
//y的旧值
private int oldy;
//旋转值,0-3
private int rot;
//旋转旧值
private int oldrot;
/*当前下坠方块*/
private int pattern;
/*下一个下坠方块*/
private int next;
private final int UNDEFINED=99;
private TetrisMap map;
protected Random rand;
public int gamearea_x;
public int gamearea_y;
public int brick_Width;
/*构造函数,保存map,初始化blockimage、rand、next*/
public TetrisBlock(TetrisMap map,boolean isMaster){
this.map=map;
if(isMaster){
rand= new Random();
//随机生成的pattern和next在1-7之间,8为墙
next=Math.abs(rand.nextInt())%7+1;
pattern=next;
next=Math.abs(rand.nextInt())%7+1;
}
else{
//如果本TetrisBlock代表的是附屏
//则当前下坠方块和下一个下坠方块由远端设备决定
pattern=UNDEFINED;
next=UNDEFINED;
}
setParameter();
}
/**
* 用来设置附屏对应的TetrisBlock对象
* @param pattern_2
* @param next_2
*/
public void setPN(int pattern_2,int next_2){
pattern=pattern_2;
next=next_2;
}
public void setParameter(){
gamearea_x=map.gamearea_x;
gamearea_y=map.gamearea_y;
brick_Width=map.brick_Width;
}
/*初始化*/
protected void init(){
}
/**
* 读取当前下坠方块
* @param nowblock int[][][] 七种方块常量之一
*/
private void readPattern(int[][][] nowblock){
blockpattern=new int[4][4][4];
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
for(int k=0;k<4;k++){
blockpattern[i][j][k]=nowblock[i][j][k];
}
}
}
}
/**
* 读取下一个下坠方块
* 只需要保存4种旋转变化中的第一种即可,所以rot=0
* @param nowblock int[][][] 7种方块之一
*/
private void readNextPattern(int[][][] nowblock){
blockNextpattern=new int[0][4][4];
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
blockNextpattern[0][i][j]=nowblock[0][i][j];
}
}
}
/*旋转方块*/
protected void rotBlock(){
}
/**
* 绘制方块,包括清除下坠方块的旧图像,调用绘制下坠方块新图像
* 本地方法
* @param g Graphics
*/
public void paint(Graphics g){
//如果三维都没有变化,则无需重画
if( (oldrot!=rot)||(oldx!=x)||(oldy!=y) ){
//清除旧图形
g.setColor(TetrisCanvas.BACKGROUND);
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(blockpattern[oldrot][i][j] == 1){
g.fillRect(gamearea_x +
(oldx + j) * brick_Width,
gamearea_y +
(oldy + i) * brick_Width,
brick_Width, brick_Width);
}
}
}
drawBlock(g);
oldrot=rot;
oldx=x;
oldy=y;
}
}
/**
* 绘制下坠方块
* @param g Graphics
* 本地、远端均可使用
*/
public void drawBlock(Graphics g){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(blockpattern[rot][i][j] == 1){
drawBrick(gamearea_x +
(x + j) * brick_Width,
gamearea_y +
(y + i) * brick_Width,g,pattern - 1);
}
}
}
}
/**
* 远端用户使用、清除当前下坠的方块
*/
public void eraseBlock(Graphics g){
}
/**
* 判断下坠方块是不是和map种已有的砖块重叠,为了处理gameover的情况,只需画出部分
* 下坠方块的情况
* @return true:有重叠;false:无重叠
*/
public boolean isCrashAtBegin(){
//行
for(int i=3;i>=0;i--){
//列
for(int j=0;j<4;j++){
int mx=x + j;
int my=y + i;
if(my<0){
my=0;
}
if(blockpattern[rot][i][j] == 1 && map.get(mx, my) != 8 &&
map.get(mx, my) != 0){
return true;
}
}
}
return false;
}
/**
* 画小砖块
* @param px x坐标
* @param py y坐标
* @param g Graphics
* @param colorIndex颜色索引值
*/
public void drawBrick(int px, int py, Graphics g, int colorIndex){
//画白边
g.setColor(255, 255, 255);
g.fillRect(px, py, 1, brick_Width);
g.fillRect(px, py, brick_Width, 1);
//画中心
int color=BRICK_COLORS[colorIndex];
g.setColor(color);
g.fillRect(px+1, py+1, brick_Width-1,
brick_Width-1);
//画灰边
g.setColor(0x00c0c0c0);
g.fillRect(px + brick_Width - 1, py + 1, 1,
brick_Width - 1);
g.fillRect(px + 1, py + brick_Width - 1,
brick_Width - 2, 1);
}
/**
* 在游戏容器的右边绘出下一个下坠物形状
* @param g Graphics
*/
public void drawNextBlock(Graphics g){
}
/**
* 判断下坠方块是否能下移
*/
public boolean checkDown(){
boolean check = true;
/*分别扫描下坠物的4行,从最下面的那行开始*/
for(int i = 0;i < 4;i++){
int row=3;
while(row >= 0){
if(blockpattern[rot][row][i] == 1){
if(map.get(x + i, y + row + 1) !=0){
check = false;
}
row = -1; //终止循环
}
else{
row--;
}
}
}
return check;
}
/*下坠物下移1行*/
public void down(){
}
/*判断是否能旋转*/
public boolean checkRot(){
boolean check = true;
int tmpRot = rot + 1;
if(tmpRot == 4){
tmpRot = 0;
}
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
if(blockpattern[tmpRot][i][j] == 1){
if(map.get(x + j, y + i) != 0){
check = false;
}
}
}
}
return check;
}
/*判断下坠物是否可以移动*/
public boolean checkMove(int direct){
boolean check = true;
//分别扫描下坠物的4行
for(int i = 0; i < 4; i++){
if(direct == 1){ //左移
int row = 0;
while(row <= 3){
if(blockpattern[rot][i][row] == 1){
if(map.get(x + row - 1, y + i) != 0){
check = false;
}
row = 4;//终止循环
}
else{
row++;
}
}
}
else{ //右移
int row = 3;
while(row >= 0){
if(blockpattern[rot][i][row] == 1){
if(map.get(x + row +1, y + i) != 0){
check = false;
}
row = -1; //终止循环
}
else{
row--;
}
}
}
}
return check;
}
/*左右移动*/
public void move(int direct){
}
public int getY(){
}
/**
* 根据下坠物的当前位置设置地图数据
*/
public void fixBlock(){
}
public int getPattern(){
}
public int getNext(){
}
/**
* 空中的方块落下后,则产生新的方块
*/
public void generatePN(){
pattern=next;
next=Math.abs(rand.nextInt())%7+1;
}
}
未完待续。。。
分享到:
相关推荐
"俄罗斯方块"是一款经典的益智游戏,玩家需要控制不同形状的方块下落,并在合适的位置排列组合以消除整行。将其作为J2ME的例子,可以深入理解游戏开发中的基本概念,如图形渲染、事件处理、游戏逻辑以及用户交互等。...
例如,使用Java的Graphics类绘制方块,监听键盘输入控制方块移动和旋转,通过Timer类控制方块的下落速度。 5. **优化和性能**:J2ME平台资源有限,优化代码以降低内存占用和提高运行效率至关重要。例如,合理使用...
3. **方块生成与旋转逻辑**:游戏中有多种不同形状的方块,每种方块的生成和旋转都需要精确的算法来实现,确保在有限的空间内合理布局。 4. **用户输入处理**:J2ME平台上的用户输入通常是通过键盘或者触摸屏,这...
3. **定时器**:为了控制方块的下落速度,我们需要一个定时器来定期更新游戏状态。J2ME的Timer类可以实现这个功能。 4. **数据结构**:为了存储游戏状态,如当前方块的位置和旋转状态,以及游戏板上的已堆积方块,...
5. **用户输入处理**:J2ME通过`KeyListener`或`Command`接口处理用户输入,如方向键控制方块移动和旋转。开发者需要编写事件监听器来响应这些输入并更新游戏状态。 6. **状态管理**:游戏具有不同的状态,如游戏...
《J2ME-OPPOF15俄罗斯方块》是一款基于Java 2 Micro Edition (J2ME) 平台开发的、适用于OPPO F15手机的经典游戏。它以其独特的可扩展性和源码开放性,为开发者提供了学习和研究移动游戏开发的宝贵资源。 首先,我们...
2. **方块下落**:游戏循环中,通过定时器控制方块的下落速度。每次迭代,检查方块是否可以向下移动,如果可以,则更新方块的位置。 3. **方块旋转**:当玩家点击旋转按钮,方块应按预设的旋转规则进行旋转。这涉及...
《J2ME版俄罗斯方块:解构与学习》 在移动设备的早期时代,Java 2 Micro Edition(J2ME)是开发游戏和应用程序的主流平台之一。今天,我们有机会深入研究一个基于J2ME的俄罗斯方块游戏源码,这为我们提供了宝贵的...
检查项目中的所有类文件,确保它们都是由与JBuilder配置相同的JDK版本生成的。 3. **库依赖问题**:第三方库或API可能与你的开发环境存在版本冲突。确认所有使用的库都是与JBuilder和JDK版本兼容的,并且已经正确...
《J2ME版俄罗斯方块:数组实现与技术解析》 在移动设备上,游戏开发一直是一大热门领域,尤其在Java ME(J2ME)时代,轻量级的平台和广泛的设备支持使得开发者能够创建出各种各样的游戏。本文将深入探讨一个基于...
《J2ME版俄罗斯方块:游戏开发与技术解析》 在移动通信技术飞速发展的今天,J2ME(Java 2 Micro Edition)作为一种轻量级的Java平台,广泛应用于移动设备,如早期的智能手机和平板电脑。本项目——"j2me俄罗斯方块...
**J2ME游戏源码详解:打造移动版俄罗斯方块** **一、J2ME简介** J2ME(Java 2 Platform, Micro Edition)是Java平台的一个子集,专为资源有限的移动设备如手机、PDA等设计。它提供了一个可移植的运行环境,使得...
《J2me俄罗斯方块设计报告》是一份深入解析如何使用Java 2 Micro Edition (J2ME) 技术开发经典游戏俄罗斯方块的详细文档。这份报告涵盖了从项目规划到实现过程的各个环节,旨在帮助学习者理解移动平台游戏开发的基础...
用户可以通过键盘(在模拟器或功能手机上)控制方块的左右移动和快速下落,以及旋转方块。源码会监听这些输入事件,更新方块的状态并反映到屏幕上。 6. **分数系统** 消除一行方块会增加分数,连续消除多行(如...
《J2ME实战:探索俄罗斯方块的编程艺术》 J2ME,全称为Java Micro Edition,是Java平台的一个重要分支,主要用于移动设备和嵌入式系统的开发。在这个专题中,我们将深入探讨如何使用J2ME来实现经典游戏——俄罗斯...
根据给定的信息,我们可以分析并总结出关于J2ME(Java 2 Micro Edition)手机游戏——俄罗斯方块的重要知识点。 ### J2ME简介 J2ME(Java 2 Platform, Micro Edition)是Sun Microsystems为嵌入式设备和移动设备...
10. **案例分析与实践**:教材可能会包含一些基础游戏的实例,如贪吃蛇、俄罗斯方块等,帮助读者将理论知识转化为实际操作能力。 总的来说,“J2ME&Gaming中文版”是一本引导初学者进入J2ME游戏开发领域的教程,它...
在这个特定的压缩包中,我们拥有的是一款基于J2ME开发的俄罗斯方块游戏的源代码。通过研究这个源码,我们可以深入理解如何在移动设备上构建游戏应用。 首先,我们要了解J2ME的基本结构。J2ME由配置(Configurations...
《J2ME版俄罗斯方块:手机游戏开发的探索与实践》 J2ME,全称为Java 2 Micro Edition,是Java平台的一个子集,专为小型设备如移动电话、智能手表等设计,用于开发和运行移动应用程序。在这个标题为“j2me俄罗斯方块...
### J2ME与LUA结合开发俄罗斯方块游戏 #### 一、项目背景与技术选型 本项目基于2007年底开发的一款经典游戏——俄罗斯方块,它利用了J2ME(Java 2 Micro Edition)作为底层的运行环境,并结合了LUA脚本来实现游戏...