一.通过分析游戏界面,抽象出几种类型:
1.Cell(格子类)
2.Tetromino(四格方块类):七种组合的父类
根据父类,定义七种子类:T、I、O、J、L、S、Z
提供静态属性,加载静态资源
Cell
属性:row(行号),col(列号),Image(图片)
Tetromino
方法:
Tetris
方法:paint(Graphics g);//绘制方法
//绘制墙
piantCurrentOne(g);//绘制正在下落的四格方块
//绘制下一个四格方块
将七个子类封装到Tetromino,初始化四格方块的初始位置
以“L”型为例
初始位置:cell[0]=(0,4);
二.类的实现:
cell类:
package com.tetris; import java.awt.image.BufferedImage; /*俄罗斯方块的最小单位:方格 * 特征(属性): * row--行号 * col--列号 * image--对应的图片 * * 行为(方法): * left() * right() * down() */ public class Cell { private int row; private int col; private BufferedImage image; public Cell () {} public Cell(int row, int col, BufferedImage image) { super(); this.row = row; this.col = col; this.image = image; } public int getRow() { return row; } public void setRow(int row) { this.row = row; } public int getCol() { return col; } public void setCol(int col) { this.col = col; } public BufferedImage getImage() { return image; } public void setImage(BufferedImage image) { this.image = image; } @Override public String toString() { return "("+ row + ","+ col + ")"; } /**向左移动*/ public void left() { col--; } /**向右移动*/ public void right() { col++; } /**向下移动*/ public void drop() { row++; }
Tetromino类:
package com.tetris; import java.util.Arrays; /* * 四格方块 * 属性: * ------cells----四个方块 * 行为: * moveLeft() * moveRight() * softDrop() */ public class Tetromino { protected Cell[] cells=new Cell[4]; public void moveLeft() { for(int i=0;i<cells.length;i++) { Cell cell=cells[i]; cell.left(); } } public void moveRight() { for(Cell c:cells) { c.right(); } } public void softDrop() { for(Cell c:cells) { c.drop(); } } @Override public String toString() { return "["+ Arrays.toString(cells) + "]"; } /**随机生成一个四格方块*/ public static Tetromino randomOne() { Tetromino t=null; int num=(int)(Math.random()*7); switch(num) { case 0:t=new T();break; case 1:t=new O();break; case 2:t=new I();break; case 3:t=new J();break; case 4:t=new L();break; case 5:t=new S();break; case 6:t=new Z();break; } return t; } }
Tetris类:
/**属性:正在下落的四格方块*/ private Tetromino currentOne=Tetromino.randomOne(); /**属性:将要下落的四格方块*/ private Tetromino nextOne=Tetromino.randomOne(); /**属性:墙 20行10列的表格 宽度为26*/ private Cell[][] wall=new Cell[20][10];
三.绘制俄罗斯方块图形
加载静态资源:
private static final int CELL_SIZE=26; public static BufferedImage T; public static BufferedImage I; public static BufferedImage O; public static BufferedImage L; public static BufferedImage S; public static BufferedImage Z; public static BufferedImage J; public static BufferedImage Background; static { try { /*getResource(String url) * url:加载图片的路径 * 相对位置是同包下 */ T=ImageIO.read(Tetris.class.getResource("T.png")); O=ImageIO.read(Tetris.class.getResource("O.png")); I=ImageIO.read(Tetris.class.getResource("I.png")); J=ImageIO.read(Tetris.class.getResource("J.png")); S=ImageIO.read(Tetris.class.getResource("S.png")); L=ImageIO.read(Tetris.class.getResource("L.png")); Z=ImageIO.read(Tetris.class.getResource("Z.png")); Background=ImageIO.read(Tetris.class.getResource("tetris.png")); }catch(Exception e) { e.printStackTrace(); } }
生成游戏界面:
public void paint(Graphics g) { //绘制背景 /* * g:画笔 * g.drawImage(image,x,y,null) * image:绘制的图片 * x:开始绘制的横坐标 * y:开始绘制的纵坐标 */ g.drawImage(Background, 0, 0, null); //平移坐标轴 g.translate(15, 15); //绘制墙 paintWall(g); //绘制正在下落的四格方块 piantCurrentOne(g); //绘制下一个四格方块 paintNextOne(g); } public void paintNextOne(Graphics g) { //获取NextOne对象的四个元素 Cell[] cells=nextOne.cells; for(Cell c:cells) { //获取行号和列号 int row=c.getRow(); int col=c.getCol(); //横坐标 int x=col*CELL_SIZE+260; //纵坐标 int y=row*CELL_SIZE+26; g.drawImage(c.getImage(),x,y,null); } } /**绘制正在下落的四格方块 * 取出数组的元素 * 绘制元素的图片 * 横坐标x: * 纵坐标y: * */ public void piantCurrentOne(Graphics g){ Cell[] cells=currentOne.cells; for(Cell c:cells) { int x=c.getCol()*CELL_SIZE; int y=c.getRow()*CELL_SIZE; g.drawImage(c.getImage(),x,y,null); } } /** * 墙是20行10列的表格 * 是个二维数组 * 应该使用双层循环 * 绘制正方形 * */ public void paintWall(Graphics a) { //外层循环控制行数 for(int i=0;i<20;i++) { //内层循环控制列数 for(int j=0;j<10;j++) { int x=j*CELL_SIZE; int y=i*CELL_SIZE; Cell cell=wall[i][j]; if(cell==null) { a.drawRect(x, y, CELL_SIZE, CELL_SIZE); }else { a.drawImage(cell.getImage(),x,y,null); } } } }
添加动态效果和接收键盘指令并响应的能力:
public void start() { //开启键盘监听事件 KeyListener l=new KeyAdapter() { /** * keyPressed()是键盘按钮按下去调用的方法 */ public void keyPressed(KeyEvent e) { //获取一下按键的代号 int code=e.getKeyCode(); switch(code) { case KeyEvent.VK_DOWN: softDropAction();break; case KeyEvent.VK_LEFT: moveLeftAction();break; case KeyEvent.VK_RIGHT: moveRightAction();break; } repaint(); } }; //面板添加监听事件对象 this.addKeyListener(l); //面板对象设置成焦点 this.requestFocus(); while(true) { try { /** * 当程序运行到此,会进入睡眠状态 * 睡眠时间为300毫秒 * 300毫秒后,会自动执行后续代码 */ Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } if(canDrop()) { currentOne.softDrop(); }else { landToWall(); //将下一个下落的四格方块赋值给正在下落的变量 currentOne=nextOne; nextOne=Tetromino.randomOne(); } /** * 下落之后,进行重新绘制,才会看到下落后的方块 * repaint方法 也是JPanel类中提供的 * 此方法中调用了paint方法 */ repaint(); } } //使用向下键控制向下的行为 public void softDropAction() { if(canDrop()) { currentOne.softDrop(); }else { landToWall(); currentOne=nextOne; nextOne=Tetromino.randomOne(); } } //使用LEFT控制向左的行为 public void moveLeftAction() { currentOne.moveLeft(); if(outOfBounds()||coincide()) { currentOne.moveRight(); } } //使用向右键控制向右的行为 protected void moveRightAction() { currentOne.moveRight(); if(outOfBounds()||coincide()) { currentOne.moveLeft(); } } private boolean coincide() { Cell[] cells=currentOne.cells; for(Cell c:cells) { int row=c.getRow(); int col=c.getCol(); if(wall[row][col]!=null) { return true; } } return false; } private boolean outOfBounds() { Cell[] cells=currentOne.cells; for(Cell c:cells) { int col=c.getCol(); if(col<0||col>9) { return true; } } return false; } public boolean canDrop() { Cell[] cells=currentOne.cells; for(Cell c:cells) { //获取每个元素的行号 /** * 判断: * 只要有一个元素的下一行有方块 * 或只要有一个元素到底就不能下落 */ int row=c.getRow(); int col=c.getCol(); if(row==19) { return false; } if(wall[row+1][col]!=null) { return false; } } return true; } /** * 当不能下落时,将四格方块嵌入到墙中 * 也就是储存到二维数组中相应的位置上 */ public void landToWall() { Cell[] cells=currentOne.cells; for(Cell c:cells) { //获取最终的行号和列号 int row=c.getRow(); int col=c.getCol(); wall[row][col]=c; } }
文章来源: 俄罗斯方块笔记