Swing编程-俄罗斯方块游戏

本文详细介绍了俄罗斯方块游戏的设计与实现过程,包括面向对象的分析与设计,游戏框架搭建,图形绘制,边界碰撞检测,障碍物消除及游戏结束判断等关键环节。

1.游戏的面向对象分析与设计

涉及到几个对象()
每个类中包含了什么方法
1.1.游戏的显示面板

GamePanel类

void display(); //显示
1.2.方块

Shap类

void moveLeft(); //左移
void moveRight(); //右移
void moveDown();  //下移
void rotate();  //变形旋转
void drawMe();  //显示

定时向下移动(使用线程实现)
1.3.图形工厂

ShapeFactory类

//生产出不同形状的图形
Shape getShape();
1.4.Ground

Ground类:

void accept()//把一个方块变成障碍物
void drawMe()//显示障碍物
1.4.类之间的关系

在这里插入图片描述

1.4.设置事件监听

图形定时下落,没下落一次后都需要重新显示,图形移动和变形后,也需要重新显示。它又不能直接操作GamePannel,怎么实现呢?

可以通过事件监听建立联系

在这里插入图片描述
ShapeListener接口

void shapeMoveDown(Shape);

2.游戏的初步框架

创建一个工程,搭起整个框架。敲一敲代码。从代码中去理解,去体会

2.1.创建一个工程TetrisGame

在这里插入图片描述

2.1.创建所需的类

Shape类:

package com.bruceliu.entity;

/**
 * @Auther: bruceliu
 * @Classname Shape
 * @Date: 2020/2/26 14:17
 * @Description: TODO
 */
public class Shape {

    public void moveLeft(){
        System.out.println("图形向左移");
    }

    public void moveRight(){
        System.out.println("图形向右移");
    }

    public void moveDown(){
        System.out.println("图形向下移");
    }

    public void rotate(){
        System.out.println("图形旋转");
    }

    public void drawMe(){
        System.out.println("图形画出自己");
    }


    private class ShapeDriver implements Runnable{
        @Override
        public void run() {
            // 定时向下落
            while(true){
                moveDown();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

ShapeFactory类:

/**
 * @Auther: bruceliu
 * @Classname ShapeFactory
 * @Date: 2020/2/26 14:18
 * @Description: TODO
 */
public class ShapeFactory {

    public Shape getShape(){
        System.out.println("产生一个方块");
        return new Shape();
    }
  
}

Ground类:

/**
 * @Auther: bruceliu
 * @Classname Ground
 * @Date: 2020/2/26 14:19
 * @Description: TODO
 */
public class Ground {

    public void accept(Shape shape){
        System.out.println("把方块变成障碍物");
    }
    
    public void drawMe(){
        System.out.println("画出障碍物");
    }
}

GamePanel类

/**
 * @Auther: bruceliu
 * @Classname GamePanel
 * @Date: 2020/2/26 14:20
 * @Description: TODO
 */
public class GamePanel extends JPanel {

    private Ground ground;
    private com.bruceliu.entity.Shape shape;

    public void display(Ground ground,Shape shape){
        System.out.println("GamePanel 显示");
        this.ground=ground;
        this.shape=shape;
        this.repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        //重新显示
        super.paintComponent(g);
        if(shape!=null && ground!=null){
            shape.drawMe();
            ground.drawMe();
        }
    }

}

Controller类

/**
 * @Auther: bruceliu
 * @Classname Controller
 * @Date: 2020/2/26 14:23
 * @Description: TODO
 */
public class Controller extends KeyAdapter {

    private Shape shape;
    private ShapeFactory shapeFactory;
    private Ground ground;
    private GamePanel gamePanel;

    @Override
    public void keyPressed(KeyEvent e){
        super.keyPressed(e);
        switch (e.getKeyCode()) {
            case KeyEvent.VK_LEFT:
                shape.moveLeft();
                break;
            case KeyEvent.VK_UP:
                shape.rotate();
                break;
            case KeyEvent.VK_RIGHT:
                shape.moveRight();
                break;
            default:
                break;
        }
        gamePanel.display(ground, shape);
    }
}

创建ShapeListener监听器

/**
 * @Auther: bruceliu
 * @Classname ShapeListener
 * @Date: 2020/2/26 14:28
 * @Description: TODO
 */
public interface ShapeListener {
    
    void shapeMoveDown(Shape shape);
}

在Shape下添加监听器

/**
 * @Auther: bruceliu
 * @Classname Shape
 * @Date: 2020/2/26 14:17
 * @Description: TODO
 */
public class Shape {
    private ShapeListener listener;// **
    public void moveLeft(){
        System.out.println("图形向左移");
    }
    public void moveRight(){
        System.out.println("图形向右移");
    }
    public void moveDown(){
        System.out.println("图形向下移");
    }
    public void rotate(){
        System.out.println("图形旋转");
    }
    public void drawMe(){
        System.out.println("图形画出自己");
    }
    private class ShapeDriver implements Runnable{

        @Override
        public void run() {
            // 定时向下落
            while(true){
                moveDown();
                listener.shapeMoveDown(Shape.this);//**
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    }
    public Shape(){//**
        new Thread(new ShapeDriver()).start();
    }
    public void addShapeListener(ShapeListener l){//**
        if(null!=l){
            this.listener=l;
        }
    }
}

Controller类实现接口ShapeListener

/**
 * @Auther: bruceliu
 * @Classname Controller
 * @Date: 2020/2/26 14:23
 * @Description: TODO
 */
public class Controller extends KeyAdapter implements ShapeListener {

    private Shape shape;
    private ShapeFactory shapeFactory;
    private Ground ground;
    private GamePanel gamePanel;

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        super.keyPressed(e);
        switch (e.getKeyCode()) {
            case KeyEvent.VK_LEFT:
                shape.moveLeft();
                break;
            case KeyEvent.VK_UP:
                shape.rotate();
                break;
            case KeyEvent.VK_RIGHT:
                shape.moveRight();
                break;
            default:
                break;
        }
        gamePanel.display(ground, shape);
    }

    @Override
    public void shapeMoveDown(Shape shape) {
        gamePanel.display(ground, shape);
    }

}

为方块工厂产生的方块添加监听

/**
 * @Auther: bruceliu
 * @Classname ShapeFactory
 * @Date: 2020/2/26 14:18
 * @Description: TODO
 */
public class ShapeFactory {
    
    public Shape getShape(ShapeListener listener){//**
        System.out.println("产生一个方块");
        Shape shape=new Shape();
        shape.addShapeListener(listener);//**
        return shape;
    }
}

Controller.java添加产生新游戏 的方法

public void newGame(){
    shape=shapeFactory.getShape(this);
}

public Controller(ShapeFactory shapeFactory,
                  Ground ground,GamePanel gamePanel){
    this.shapeFactory=shapeFactory;
    this.ground=ground;
    this.gamePanel=gamePanel;
}

设置GamePanel大小

public GamePanel(){
    this.setSize(300,300);
}

测试类GamePlay

/**
 * @Auther: bruceliu
 * @Classname GamePlay
 * @Date: 2020/2/26 14:32
 * @Description: TODO
 */
public class GamePlay {

    /**
     * @param args
     */
    public static void main(String[] args) {

        ShapeFactory shapeFactory=new ShapeFactory();
        Ground ground=new Ground();
        GamePanel gamePanel=new GamePanel();
        Controller controller=new Controller(shapeFactory, ground,gamePanel);
        JFrame frame=new JFrame();
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(gamePanel.getSize().width+10,
                gamePanel.getSize().height+30);
        frame.add(gamePanel);
        gamePanel.addKeyListener(controller);
        frame.setVisible(true);
        controller.newGame();
    }

}

启动测试
在这里插入图片描述
测试结果就是个空面板。控制台就会输出各种相关操作的信息。

3.游戏的图形绘制

3.1.图形和障碍物表示

在这里插入图片描述

3.2.图形状态的表示

在这里插入图片描述
在这里插入图片描述

图形变形就是一一个状态

图形的多种状态:
在这里插入图片描述

3.4.图形绝对坐标和相对坐标

在这里插入图片描述

3.5.图形的移动

图形类里面保存自己的位置,用left表示图形到左边边界的距离,使用top表示图形到顶部的距离,图形系统就是改变left和top值
在这里插入图片描述

3.6.代码实现

在方块类Shape.java中添加二维标志,状态标志

private int[][] body;
private int status;
public void setBody(int body[][]){
    this.body=body;
}
public void setStatus(int status) {
        this.status = status;
}

在方块工厂ShapeFactory.java添加创建方块样式

/**
 * @Auther: bruceliu
 * @Classname ShapeFactory
 * @Date: 2020/2/26 14:18
 * @Description: TODO
 */
public class ShapeFactory {
    protected static int shapes[][][] = new int[][][] {//**
            /* 第一种 */{ /** ***** */
            { 1, 1, 0, 0, 1, 1, 0, 0, 0, 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 },

                    { 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } },
            /* 第三种 */
            { /** ******* */
                    { 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },

                    { 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, 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, } },
            /* 第五种 */
            { /** ******** */
                    { 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, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },

                    { 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },

                    { 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },

                    { 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 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 } },

    };
    public Shape getShape(ShapeListener listener){
        System.out.println("产生一个方块");
        Shape shape=new Shape();
        shape.addShapeListener(listener);
        int type=new Random().nextInt(shapes.length);
        shape.setBody(shapes[type]);//**
        shape.setStatus(0);//**
        return shape;
    }

}

在Shape类中表示坐标的方法

/**
 * @Auther: bruceliu
 * @Classname Shape
 * @Date: 2020/2/26 14:17
 * @Description: TODO
 */
public class Shape {

    private int[][] body;
    private int status;
    private int left;//**
    private int top;//**

    public void setBody(int body[][]){
        this.body=body;
    }
    public void setStatus(int status) {
        this.status = status;
    }

    private ShapeListener listener;
    public void moveLeft(){
        System.out.println("图形向左移");
        left--;//**
    }
    public void moveRight(){
        System.out.println("图形向右移");
        left++;//**
    }
    public void moveDown(){
        System.out.println("图形向下移");
        top++;//**
    }
    public void rotate() {
        System.out.println("图形旋转");
        status = (status + 1) % body.length;//**
    }

    public void drawMe(){
        System.out.println("图形画出自己");
    }
    private class ShapeDriver implements Runnable{

        @Override
        public void run() {
            // 定时向下落
            while(true){
                moveDown();
                listener.shapeMoveDown(Shape.this);//**
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    }
    public Shape(){//**
        new Thread(new ShapeDriver()).start();
    }
    public void addShapeListener(ShapeListener l){//**
        if(null!=l){
            this.listener=l;
        }
    }
}

开始画出方块

画方阵标志为1的格子。标志为0的不画

修改Shape.java的drawMe()方法

 public void drawMe(Graphics g) {
     System.out.println("图形画出自己");
     g.setColor(Color.RED);//**
     for (int x = 0; x < 4; x++) {//**
         for (int y = 0; y < 4; y++) {
             if (getFlagByPoint(x, y)) {
                 g.fill3DRect((left+x)* Global.CELL_SIZE, (top+y)*Global.CELL_SIZE,
                         Global.CELL_SIZE, Global.CELL_SIZE, true);
             }
         }
     }
 }

 private boolean getFlagByPoint(int x, int y) {//**
     return body[status][y * 4 + x] == 1;
 }

Global类
在这里插入图片描述

/**
 * @Auther: bruceliu
 * @Classname Global
 * @Date: 2020/2/26 15:02
 * @Description: TODO
 */
public class Global {
    public static final int CELL_SIZE=20;
}

修改GamePanel.java

@Override
protected void paintComponent(Graphics g) {
   //重新显示
   super.paintComponent(g);
   g.fillRect(0, 0, 300, 300);//**
   g.setColor(new Color(0xcfcfcf));//**
   if(shape!=null && ground!=null){
       shape.drawMe(g);//**
       ground.drawMe();
   }
}

现在效果:
在这里插入图片描述
修改测试类GamePlay.java。添加控制方向键移动方块的监听事件

 public static void main(String[] args) {
        // TODO Auto-generated method stub
        ShapeFactory shapeFactory=new ShapeFactory();
        Ground ground=new Ground();
        GamePanel gamePanel=new GamePanel();
        Controller controller=new Controller(shapeFactory,
                ground,gamePanel);
        JFrame frame=new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(gamePanel.getSize().width+10,
                gamePanel.getSize().height+30);
        frame.add(gamePanel);
        gamePanel.addKeyListener(controller);
        frame.addKeyListener(controller);//**
        frame.setVisible(true);
        controller.newGame();
    }

现在效果:
在这里插入图片描述
现在可以按方向键,变换方块咯

4.游戏的完善

碰到游戏面板的边界时,要让方块做出反应。碰左壁,不能再向左移。碰右壁,不能再向右移

在Global.java添加两个常量

/**
 * @Auther: bruceliu
 * @Classname Global
 * @Date: 2020/2/26 15:02
 * @Description: TODO
 */
public class Global {
    public static final int CELL_SIZE=20;

    //格子的宽高
    public static final int WIDTH=15;
    public static final int HEIGHT=15;
    
}

修改GamePanel.java的大小

@Override
protected void paintComponent(Graphics g) {
    //重新显示
    super.paintComponent(g);
    //g.fillRect(0, 0, 300, 300);//**
    g.fillRect(0, 0, Global.WIDTH*Global.CELL_SIZE,Global.HEIGHT*Global.CELL_SIZE);
    g.setColor(new Color(0xcfcfcf));//**
    if(shape!=null && ground!=null){
        shape.drawMe(g);//**
        ground.drawMe();
    }
}
   public GamePanel(){
       this.setSize(Global.WIDTH*Global.CELL_SIZE,Global.HEIGHT*Global.CELL_SIZE);
   }

在Shape.java中添加几个方向常量

public static final int ROTATE = 0;
public static final int LEFT = 1;
public static final int RIGHT = 2;
public static final int DOWN = 3;

在Shape.java中添加取得方块坐标的方法和判断是否自己成员的方法

public int getTop() {
      return top;
  }

  public int getLeft() {
      return left;
  }

  public boolean isMember(int x, int y, boolean rotate) {
      int tempStatus = status;
      //发生了旋转
      if (rotate) {
          tempStatus = (status + 1) % body.length;
      }
      return body[tempStatus][y * 4 + x] == 1;
  }

在Ground.java中添加如下方法

  public boolean isMoveable(Shape shape, int action) {
        int left = shape.getLeft();
        int top = shape.getTop();
        switch (action) {
            case Shape.LEFT:
                left--;
                break;
            case Shape.RIGHT:
                left++;
                break;
            case Shape.DOWN:
                top++;
                break;
        }
        //依次取出来图形中的点,判断是否超出显示区域
        for (int x = 0; x < 4; x++) {
            for (int y = 0; y < 4; y++) {
                if (shape.isMember(x, y, action == Shape.ROTATE)) {
                    if (top + y >= Global.HEIGHT || left + x < 0 || left + x >= Global.WIDTH)
                        return false;
                }
            }
        }
        return true;
    }

在Controller.java下添加如下代码

@Override
public void keyPressed(KeyEvent e) {
    // TODO Auto-generated method stub
    super.keyPressed(e);
    switch (e.getKeyCode()) {
        case KeyEvent.VK_LEFT:
            if (ground.isMoveable(shape, Shape.LEFT))
                shape.moveLeft();
            break;
        case KeyEvent.VK_UP:
            if (ground.isMoveable(shape, Shape.ROTATE))
                shape.rotate();
            break;
        case KeyEvent.VK_RIGHT:
            if (ground.isMoveable(shape, Shape.RIGHT))
                shape.moveRight();
            break;
        case KeyEvent.VK_DOWN:
            if (ground.isMoveable(shape, Shape.DOWN))
                shape.moveDown();
            break;
        default:
            break;
    }
    gamePanel.display(ground, shape);
}

测试左右边界,发现现在左右边界控制住了!
在这里插入图片描述
解决图形下落,不出下边界:
在这里插入图片描述
在ShapeListener.java下添加一个抽象方法

/**
 * @Auther: bruceliu
 * @Classname ShapeListener
 * @Date: 2020/2/26 14:28
 * @Description: TODO
 */
public interface ShapeListener {

    void shapeMoveDown(Shape shape);

    boolean isShapeMoveDownable(Shape shape);
}

修改实现该接口的类Controller.java

@Override
public boolean isShapeMoveDownable(Shape shape) {
    boolean result = ground.isMoveable(shape, Shape.DOWN);
    return result;
}

修改Shape.java的定时下落

 private class ShapeDriver implements Runnable {
        @Override
        public void run() {
            // 定时向下落
            while (listener.isShapeMoveDownable(Shape.this)) {
                moveDown();
                listener.shapeMoveDown(Shape.this);//**
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

将图形变成障碍物和显示
修改Controller类的方法isShapeMoveDownable为同步。

 @Override
 public synchronized boolean isShapeMoveDownable(Shape shape) {
     boolean result = ground.isMoveable(shape, Shape.DOWN);
     return result;
 }

测试发现方块落下后停留在底部
在这里插入图片描述

修改Controller类的方法isShapeMoveDownable,图形到达底部,产生新图形

@Override
public synchronized boolean isShapeMoveDownable(Shape shape) {
  if(ground.isMoveable(shape, Shape.DOWN)){
            return true;
  }
     //将图形变为障碍物
     ground.accept(this.shape);
     //重新产生一个图形
     this.shape = shapeFactory.getShape(this);
     return false;
}

在Ground.java中添加增加障碍物,显示障碍物的判断
在这里插入图片描述

 private int[][] obstacles = new int[Global.WIDTH][Global.HEIGHT];

 public void accept(Shape shape) {
     System.out.println("把方块变成障碍物");
     for (int x = 0; x < 4; x++) {
         for (int y = 0; y < 4; y++) {
             if (shape.isMember(x, y, false)) {
                 obstacles[shape.getLeft() + x][shape.getTop() + y] = 1;
             }
         }
     }
 }

 public void drawMe(Graphics g) {
     System.out.println("画出障碍物");
     for (int x = 0; x < Global.WIDTH; x++) {
         for (int y = 0; y < Global.HEIGHT; y++) {
             if (obstacles[x][y] == 1) {
                 g.fill3DRect(x * Global.CELL_SIZE, y * Global.CELL_SIZE, Global.CELL_SIZE, Global.CELL_SIZE, true);
             }
         }
     }
 }

修改GamePanel.java

@Override
protected void paintComponent(Graphics g) {
    //重新显示
    super.paintComponent(g);
    //g.fillRect(0, 0, 300, 300);//**
    g.fillRect(0, 0, Global.WIDTH*Global.CELL_SIZE,Global.HEIGHT*Global.CELL_SIZE);
    g.setColor(new Color(0xcfcfcf));//**
    if(shape!=null && ground!=null){
        shape.drawMe(g);//**
        ground.drawMe(g);
    }
}

当碰到障碍物的时候也停止,修改Ground下的

public boolean isMoveable(Shape shape, int action) {
     int left = shape.getLeft();
     int top = shape.getTop();
     switch (action) {
         case Shape.LEFT:
             left--;
             break;
         case Shape.RIGHT:
             left++;
             break;
         case Shape.DOWN:
             top++;
             break;
     }
     for (int x = 0; x < 4; x++) {
         for (int y = 0; y < 4; y++) {
             if (shape.isMember(x, y, action == Shape.ROTATE)) {
                 if (top + y >= Global.HEIGHT || left + x < 0 || left + x >= Global.WIDTH||1==obstacles[left+x][top+y])
                     return false;
             }
         }
     }
     return true;
 }

消除满行的障碍物
这一行没有空白,则这一行就是满行了。上面所有的行,整体下移一行。

在Ground.java下添加

public void accept(Shape shape) {
    System.out.println("把方块变成障碍物");
    for (int x = 0; x < 4; x++) {
        for (int y = 0; y < 4; y++) {
            if (shape.isMember(x, y, false)) {
                obstacles[shape.getLeft() + x][shape.getTop() + y] = 1;
            }
        }
    }
    deleteFullLine();
}

private void deleteFullLine() {
    for (int y = Global.HEIGHT - 1; y > 0; y--) {
        boolean full = true;
        for (int x = 0; x < Global.WIDTH; x++) {
            if (0 == this.obstacles[x][y]) {
                full = false;
            }
        }
        if (full) {
            deleteLine(y++);
        }
    }
}

private void deleteLine(int lineNum) {
    for (int y = lineNum; y > 0; y--) {
        for (int x = 0; x < Global.WIDTH; x++) {
            this.obstacles[x][y] = this.obstacles[x][y - 1];
        }
    }
    for (int x = 0; x < Global.WIDTH; x++) {
        this.obstacles[x][0] = 0;
    }
}

增加游戏结束功能
如果有的障碍物超出了上边界,就是游戏结束,第一行如果有障碍物,就是游戏结束

在Ground.java下添加

public boolean isFull() {
    for (int x = 0; x < Global.WIDTH; x++) {
        if (1 == this.obstacles[x][0]) {
            return true;
        }
    }
    return false;
}

在Controller.java下判断

@Override
public synchronized boolean isShapeMoveDownable(Shape shape) {
    if (ground.isMoveable(shape, Shape.DOWN))
        return true;
    ground.accept(this.shape);
    if(!ground.isFull()) {
        this.shape = shapeFactory.getShape(this);
    }else{
        System.out.println("game over");
    }
    return false;
}

解决定时下落与按下键同时生成障碍物的问题

在controller.java中修改

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        super.keyPressed(e);
        switch (e.getKeyCode()) {
            case KeyEvent.VK_LEFT:
                if (ground.isMoveable(shape, Shape.LEFT))
                    shape.moveLeft();
                break;
            case KeyEvent.VK_UP:
                if (ground.isMoveable(shape, Shape.ROTATE))
                    shape.rotate();
                break;
            case KeyEvent.VK_RIGHT:
                if (ground.isMoveable(shape, Shape.RIGHT))
                    shape.moveRight();
                break;
            case KeyEvent.VK_DOWN:
                if(this.isShapeMoveDownable(shape))
                    shape.moveDown();
                break;
            default:
                break;
        }
        gamePanel.display(ground, shape);
    }
@Override
public synchronized boolean isShapeMoveDownable(Shape shape) {
    if(this.shape!=shape){
        return false;
    }
    if (ground.isMoveable(shape, Shape.DOWN))
        return true;
    ground.accept(this.shape);
    if(!ground.isFull()) {
        this.shape = shapeFactory.getShape(this);
    }else{
        System.out.println("game over");
    }
    return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

源码小哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值