1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 俄罗斯方块游戏开发 ——图形化编程java swing 项目

俄罗斯方块游戏开发 ——图形化编程java swing 项目

时间:2023-05-22 20:56:46

相关推荐

俄罗斯方块游戏开发 ——图形化编程java swing 项目

通过java swing技术开发的俄罗斯方块游戏,实现了基础的游戏绘制、移动逻辑、消除逻辑、得分统计、死亡判定、预测方块等功能。

成果展示截图:

项目源码及 可执行文件jar 下载 :

/echowz/Teris

游戏介绍:

俄罗斯方块的规则:

玩家不断操作下落的不同板块,直达底部,并刷新新的板块。在操作时通过调整位置和旋转方向,使得落下的方块可以填满一整层,每当一层填满,则该层会消失,上方所积累的方块会落下,同时积累分数,当累积到上方空间不足以刷新新的方块,且整个空间无法消除时,则游戏结束

游戏场地10×20的平面网格地图。每个单位为相同宽度的小正方形。

操作图形:一组固定由4个小正方形组成的不同规则的图形,称为Tetromino。共有6种形态,通过字母象形分别记作:I, J, L, S, Z, O, T。

I:

连续的4个方块组成一长条图形,形如字母I。一次最多可以消除4层。共有2种旋转状态。

J:

形如字母J,一次最多可以消除3层,共有4种旋转状态。

L:

形如字母L,J的对称形状,一次最多可以消除3层,共有4种旋转状态

O:

形如字母O,4个小正方形堆叠形成的大正方形,一次最多可以消除2层,仅有一种旋转状态。

S:

形如字母S,一次最多可以消除2层,共有2种旋转状态

T:

形如字母T,一次最多可以消除2层,有4种旋转状态。

Z:

形如字母Z,一次最多可以消除2层,共有2种旋转状态

分数累计:一次消除层数的平方*10,1层为10分,2层为40分,3层为90分,4层为160分。

项目结构:

主框体程序结构:

GamePanel即框体左侧的游戏本体部分,继承自模块Jpanel,负责绘制游戏平面显示。

Menu即框体右侧的菜单信息部分,继承自模块Jpanel负责展示信息。

MainFrame为整个框体,继承自Jframe。

Main 主类中负责创建和编写游戏流程等逻辑。

方块样式结构:

抽象类Tetromino描述了一个类型方块的基本特征,坐标,移动方法,旋转方法等。

cell类描述一个单独的小方块,记录坐标。

7个实现类都以Cell组成,记录其各个子小方块所处的位置,从而组成了整个方块的形态。

每个Cell方块都拥有其坐标属性

如 I 方块的组成可以表示为:以其中一个靠中的方块(x,y)作为整体I方块的坐标表示,

生成I 方块对象时,将生成四个Cell对象来组成整体。此时,I 方块的其中一个旋转状态便表示完毕,但每个类型的方块都可能有多个旋转状态,因此

项目介绍

框体部分:

GamePanel

该区域绘制整个版面,用成员变量二维数组graph记录10*20的网格中的信息,当网格的值为0时表示该网格为空,其他正值分别表示不同的颜色,若为-1则该网格为界外网格,也是不显示的网格。由于gamepanel只创建一次,其成员变量采用静态方法,方便全局调用。

成员变量部分:

public static int[][] graph; //地图的二维数组映射public static Color[] colors; //7种方块7种颜色,便于区分和识别。

构造部分:

public GamePanel(){init();setBackground(Color.CYAN);//背景色设为淡蓝 方格填充后作为淡蓝色网格线setBounds(new Rectangle(0,0,MainFrame.width*2/3,MainFrame.height));//设置panel区域的长宽和位置,为整个框体的左三分之二处setVisible(true);}public void init() //初始化辅助参数,颜色集,地图等。{colors=new Color[]{ //初始化颜色数组Color.white, //默认静态final变量,返回的是白色的Color对象new Color(0,240,240),new Color(0,0,240),new Color(240,160,0),new Color(240,240,0),new Color(0,240,0),new Color(160,0,240),new Color(240,0,0)};graph = new int[25][15]; //初始化地图大小for(int i=0;i<=22;i++)Arrays.fill(graph[i], -1); //先全部初始化-1,再将合法区域初始化为0for(int i=1;i<=20;i++)//地图的合法区域为x:1-20 y:1-10;for(int j=1;j<=10;j++)graph[i][j]=0;//经初始化,-1为出界。}

重写paint方法,整个程序的核心绘制,整个版面的显示:

@Overridepublic void paint(Graphics g){super.paint(g);for(int i=1;i<=20;i++)for(int j=1;j<=10;j++){g.setColor(colors[graph[i][j]]);int x=MainFrame.width/40+(j-1)*MainFrame.width/16;int y=MainFrame.width/20+(i-1)*MainFrame.width/16;int width=MainFrame.width/16-2,height=MainFrame.width/16-2;g.fillRect(x,y,width,height);}}

Menu

menu区域用作信息显示,不作重点讲解,预测下一个方块的功能有一定代码逻辑。与Tetromino的构造结合应用。由于Menu只会创建一个,其成员变量采用静态方式。

成员变量:

public static int score; //当前分数public static ArrayList<Image> imageList; //用于显示下一个方块的图片,打印在menu中public static int currentPicture; //当前需要打印的图片为

构造方法中初始化信息,paint中绘制界面。

MainFrame

定义了整个程序需要参考的参数:宽、高

public static final int height=800;public static final int width=height*3/4;

构造函数中设置框体的基本属性即可。

Main

主类中创建的全局变量为:

public static Tetromino select; //当前操控的方块设置为selectpublic static Menu menu;public static GamePanel gamePanel;public static MainFrame mainFrame;public static final Object object = new Object(); //用作synchronized 参数,用于线程阻塞,循环下降操作的等待过程。public static int pauseTime=500; //自动下落的间隔时间,用于控制速度,间隔越短下落速度越快。

main方法中创建gamepanel、menu后添加到创建的mainframe中,并添加一个新线程用作不断重绘两个板块:gamepanel和menu中的内容。

public static void main(String[] args) {System.out.println("运行开始");gamePanel = new GamePanel();menu = new Menu();mainFrame = new MainFrame();//Mainframe需要在后,因为其中有需要调用到panel的成员的语句mainFrame.add(gamePanel);mainFrame.add(menu);new Thread(()-> {while (true) {gamePanel.repaint();menu.repaint();}}).start(); //持续刷新画布的线程。updateTet();Thread downs = new Thread(()->{ //不断循环下落的线程。try {while (true) {synchronized (object) {down();object.wait(pauseTime/2); //下落速度object.wait(pauseTime/2);}}}catch (Exception e) {e.printStackTrace();}});downs.start();......}

在main中添加键盘监听,完善游戏的操作逻辑。

mainFrame.addKeyListener(new KeyAdapter() { //监听玩家操作@Overridepublic void keyPressed(KeyEvent e) {switch (e.getKeyChar()) { //获取键盘活动的char值case 'a': //左右移动的逻辑,当前选定的Tetromino方块 有抽象方法移动和旋转,移动传递参数01分别为左右移动。case 'A':select.move(0);break;case 'd':case 'D':select.move(1);break;case 's': //s用作单次点击加速下落case 'S':down();break;case ' ': //调用当前选定的Tetromino方块的自我旋转方法,实现旋转select.spin();break;case 'w': //触发/取消 暂停下落case 'W':if (downs.isAlive())synchronized (object) {object.notify(); //下落速度}if (pauseTime == 500) pauseTime = 2000000;else pauseTime = 500; //通过改变下落间隔实现暂停和继续的功能break;}}});

方块部分:

小方块Cell类

成员变量

即记录当前小方块所处坐标的x和y

public int x;public int y;

成员方法

setColor() 将当前小方块所处的位置的单元格上色。

isBorder()是否处于边界(根据将要移动的方向来判断,即可能是边界,也可能是另一个已填充的方块)

legal()判断这个小方块当前的位置是否是合法的。(在染色前判断,该位置应该是空的才会被染色,因为俄罗斯方块中不存在覆盖颜色的行为,所有只有不出界且为空才合法);

public void setColor(int color) { //给当前小方块所在位置上色GamePanel.graph[Math.max(0,x)][Math.max(0,y)]=color;}public boolean isBorder(int dir) { //参数 0向左移动,1向右移动 2向下 通过该小方块的移动判断整体移动后是否会撞击边界或其他方块 作为碰撞判定的一部分if(dir==0) return GamePanel.graph[x][y-1] != 0;else if(dir==1) return GamePanel.graph[x][y+1]!=0;else if(dir==2) return GamePanel.graph[x+1][y]!=0;return true;}public boolean legal(){//判断该方块当前位置是否合法。 //合法返回真if(x <1 || x > 20 || y <1 || y > 10)return false;return GamePanel.graph[x][y]==0;}

抽象类Tetromino

拥有的成员变量为:

public int color; //颜色public int x; //当前方块的坐标public int y;public int status; //当前方块处于的旋转状态为public int statusNum=4; //当前方块一定有几个状态public static int currentTetromino=new Random().nextInt(7);//当前选定的方块,通过随机数选定。public Cell[][] cells; //当前方块的i个状态,每个状态4个小方块,所记录的小方块信息。//旋转时将在第一维,不同的状态之间切换; 移动时将在第二维,对当前状态下的4个方块进行遍历,查看是否可以移动,和修改其位置信息。

Tetromino的核心方法为move方法和spin方法,移动和旋转是俄罗斯方块的核心操作方式,是画面的主要改变方式。

move(int dir)接收参数,通过参数值的不同实现左右下三个方向的移动。遍历所含的4个小方块,假定朝既定方向移动,判断移动后的位置是否合法,如果都合法则实现移动,有不合法的则撤销。

spin()不接收参数,将当前操控的方块进行顺时针90°的旋转。

在实现层面上讲,是将当前选定方块切换至下一个旋转状态,因为每个方块都有成员cell【】【】,也就是每个旋转状态的每个小方块儿子属性,在旋转时遍历所含的小方块判定下个状态是否合法,合法则旋转。

public void move(int dir) { //0左 1右 2下setColor(0); //将该方块移除for(int j=0;j<4;j++) if(cells[status%statusNum][j].isBorder(dir)) { //是否为底部,即下面一个单位是否有元素。setColor(color);return;}if (dir == 0) y--;else if(dir==1) y++;else if(dir==2) x++;setCells(x,y);setColor(color);}public void spin() { //旋转setColor(0);//实现逻辑为先假设旋转,先移除旧的,再切换状态,然后判断旋转后的方块所处位置是否合法(全为0)。如果合法则应用填色,不合法则恢复status++; //下一个状态for (int j = 0; j < 4; j++) { //所有小方块合法才改变。if (!cells[status%statusNum][j].legal()) {status--;setColor(color);return;}}setColor(color);}

7个实现类

都实现了父类的setcells方法,初始化各个状态的信息。以J方块举例,其完整代码如下:

public class J extends Tetromino{public J(int x, int y) {super(x,y);statusNum=4;color=2;}@Overridepublic void setCells(int x, int y) { //各个形状如下:cells[0][0].setLocation(x-1, y-1);// *cells[0][1].setLocation(x, y);// * * *cells[0][2].setLocation(x, y -1);cells[0][3].setLocation(x, y +1);cells[1][0].setLocation(x-1, y);// * *cells[1][1].setLocation(x, y); // *cells[1][2].setLocation(x + 1, y); // *cells[1][3].setLocation(x -1, y+1);cells[2][0].setLocation(x+1, y+1); // * * *cells[2][1].setLocation(x, y); //*cells[2][2].setLocation(x , y-1);cells[2][3].setLocation(x , y+1);cells[3][0].setLocation(x-1, y);// *cells[3][1].setLocation(x, y); // *cells[3][2].setLocation(x +1, y);// * *cells[3][3].setLocation(x +1, y-1);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。