我所知道坦克大战(单机版)之封装坦克类、让坦克八个方向行走、

前言需求


以我们目前的思路文章,我们发现只有一个坦克圆点,若我们需要多个坦克时,则无法清楚怎么添加?

比如说100个坦克,那么就需要有100个坦克的位置

若使用数组存放100个坦克的位置,那么当坦克有不同属性:圆点颜色、名称、阵营等

则也需要添加相对应的数组去管理,所以这时我们需要使用面向对象来创建一个坦克类

一、坦克类存放属性


class Tank{

    int x;//坦克x坐标

    int y ;//坦克y坐标

    public Tank(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

这时我们在使用一辆坦克的时候,则直接创建即可

public class TankClient extends Frame {

    Tank mytank = new Tank(50,50);
    
    @Override
    public void paint(Graphics g) {

        //获取默认的颜色Color
        Color c = g.getColor();
        //将坦克颜色为红色
        g.setColor(Color.red);
        //画一个圆
        g.fillOval(mytank.x,mytank.y,30,30);
        //将原颜色填充回
        g.setColor(c);
    }    
    
    //省略其他关键性代码....
}

我们发现如果使用这种方式去绘画一个坦克的话,是没有问题的

但是若有100个坦克的时候,反而还需要去管理这个绘画的方法

那么我们可不可以使用一种思维,让坦克自己去绘制自己呢?

class Tank{

   //省略其他关键性代码....
    
    //添加方法完成坦克的绘画
    public void draw(Graphics g){
        //获取默认的颜色Color
        Color c = g.getColor();
        //将坦克颜色为红色
        g.setColor(Color.red);
        //画一个圆
        g.fillOval(x, y, 30, 30);
        //将原颜色填充回
        g.setColor(c);
        //刷新圆点位置
        x += 5;//x坐标
        y += 5;//y坐标
    }
}
public class TankClient extends Frame {

    Tank mytank = new Tank(50,50);
    
    @Override
    public void paint(Graphics g) {
        mytank.draw(g)
    }    
    //省略其他关键性代码....
}

同时我们的键盘控制也是,这样我们后面机器人自己动的时候则无需管理

class Tank{

   //省略其他关键性代码....
   public void keyPressed(KeyEvent e) {
      int key = e.getKeyCode();
      switch (key) {
         case KeyEvent.VK_LEFT:
            x -= 5;
            break;
         case KeyEvent.VK_UP:
            y -= 5;
            break;
         case KeyEvent.VK_RIGHT:
            x += 5;
            break;
         case KeyEvent.VK_DOWN:
            y += 5;
            break;
       }
   }
}
public class TankClient extends Frame {

    Tank mytank = new Tank(50,50);
    
    //继承抽象类完成键盘监听
    private class KeyMonitor extends KeyAdapter {
        @Override
        public void keyPressed(KeyEvent e) {
            mytank.keyPressed(e);//这样起到中间人的作用
        }
    }
    //省略其他关键性代码....
}

这样当我们管理一辆坦克的时候,也是可以跑起来的,多个的时候也可

我所知道坦克大战(单机版)之封装坦克类、让坦克八个方向行走、_第1张图片

二、让坦克八个方向走

之前我们有篇文章是让坦克可以上下左右的移动,但是我们发有一些方向漏掉了,并且没有提供给坦克移动

比如说:左上、右上、左下、右下

我们刚刚在前面封装了坦克的类,这时我们怎么添加这四个方向呢?

同时我们一般完成左上走方式在键盘里是怎么做到的呢?

是不是需要先按住左、再按上,这样形成左上走的斜线操作

第一步:添加↑↓←→方向是否被按下的标识符

class Tank{

    //省略其他关键性代码....

    //↑↓←→的四个方向键
    private boolean BU = false;
    private boolean BD = false;
    private boolean BL = false;
    private boolean BR = false;
    
}

当按下对应的方向,位置标识符则更改为true,同时提供八个方向的枚举

class Tank{

    //省略其他关键性代码....

    //定义枚举八个方向:上、下、左、右、左上、右上、右下、左下、停止不动
    enum Direction{L,LU,U,RU,R,RD,D,LD,STOP}
    
    //默认动作方向为停止不动
    private Direction dir = Direction.STOP;
    
}

当我们触发八个方向的时候,则根据方向进行移动修改距离

class Tank{

    //省略其他关键性代码....

    //每次移动x坐标的步骤距离
    public static final int XSPEED = 5;

    //每次移动y坐标的步骤距离
    public static final int YSPEED = 5;
    
    void move() {
        switch (dir) {
            case L:
                x -= XSPEED;
                break;
            case LU:
                x -= XSPEED;
                y -= YSPEED;
                break;
            case U:
                y -= YSPEED;
                break;
            case RU:
                x += XSPEED;
                y -= YSPEED;
                break;
            case R:
                x += XSPEED;
                break;
            case RD:
                x += XSPEED;
                y += YSPEED;
                break;
            case D :
                y += YSPEED;
                break;
            case LD:
                x -= XSPEED;
                y += YSPEED;
                break;
            case STOP:
                break;
        }
    }
}

同时当我们重新绘画的时候,进行移动位置,以及键盘按下修改标识符

class Tank{

    //省略其他关键性代码....
    
    //添加方法完成坦克的绘画
    public void draw(Graphics g){
        //省略其他关键性代码....
        move();
    }
    
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        switch (key) {
            case KeyEvent.VK_LEFT :
                BL = true;break;
            case KeyEvent.VK_UP :
                BU = true;
                break;
            case KeyEvent.VK_RIGHT :
                BR = true;
                break;
            case KeyEvent.VK_DOWN :
                BD = true;
                break;
        }
    }
}

这时我们则可以根据标识符,来组合具体的坦克方向位置了

比如说我们按键顺序:左、上,这时我们的方向应该是左上

void locateDirection() {
        //当按下 ← 键
        if (BL && !BU && !BR && !BD) dir = Direction.L;
        //当按下 ← 键 + ↑键
        else if (BL && BU && !BR && !BD) dir = Direction.LU;
        //当按下 ↑键
        else if (!BL && BU && !BR && !BD) dir = Direction.U;
        //当按下 → 键 + ↑键
        else if (!BL && BU && BR && !BD) dir = Direction.RU;
        //当按下 → 键
        else if (!BL && !BU && BR && !BD) dir = Direction.R;
        //当按下 → 键 + ↓键
        else if (!BL && !BU && BR && BD) dir = Direction.RD;
        //当按下 ↓键
        else if (!BL && !BU && !BR && BD) dir = Direction.D;
        //当按下 ← 键 + ↓键
        else if (BL && !BU && !BR && BD) dir = Direction.LD;
        //当啥都没按时
        else if (!BL && !BU && !BR && !BD) dir = Direction.STOP;
    }

步骤思路总结

  • ✧添加记录按键状态的布尔量
  • ✧添加代表方向的量(使用枚举)
  • ✧根据按键状态确定Tank方向
  • ✧根据方向进行下一步的移动(move)

但是当我们运行main方法的时候,发现只需要按下方向键确实走了

我所知道坦克大战(单机版)之封装坦克类、让坦克八个方向行走、_第2张图片

比如说我们按先按右再按下,发现他是斜着走的?这是什么情况呢?

我所知道坦克大战(单机版)之封装坦克类、让坦克八个方向行走、_第3张图片

原因是:当我们按下方向键时就为True,释放时并没有更改为false

所以当我们按下右,再按下时,右和下都为Ture了

第二步:添加键盘释放的监听器事件

给坦克添加键盘释放的监听事件,当我们抬起键盘的时候更改为false

public void keyReleased(KeyEvent e) {
    int key = e.getKeyCode();
    switch (key) {
        case KeyEvent.VK_LEFT:
            BL = false;
            break;
        case KeyEvent.VK_UP:
            BU = false;
            break;
        case KeyEvent.VK_RIGHT:
            BR = false;
            break;
        case KeyEvent.VK_DOWN:
            BD = false;
            break;
    }
    locateDirection();
}
public class TankClient extends Frame {
    
    //省略其他关键性代码.......
    //继承抽象类完成键盘监听
    private class KeyMonitor extends KeyAdapter {
        //当键盘按下的事件
        @Override
        public void keyPressed(KeyEvent e) {
            mytank.keyPressed(e);//这样起到中间人的作用
        }
        //当键盘抬起的事件
        @Override
        public void keyReleased(KeyEvent e) {
            mytank.keyReleased(e);//这样起到中间人的作用
        }
    }
}

这下我们的坦克就可以完成坦克的八个方向行走了

我所知道坦克大战(单机版)之封装坦克类、让坦克八个方向行走、_第4张图片

步骤思路总结

  • ✧处理键抬起的消息
  • ✧修改TankClient相关代码(键盘监听器重写键盘抬起事件)

参考资料


尚学堂:坦克大战(马士兵老师)

你可能感兴趣的:(我所知道坦克大战(单机版)之封装坦克类、让坦克八个方向行走、)