我所知道坦克大战(单机版)之 让子弹飞、让坦克控制子弹开炮

28640

本篇文章目的


  • 让子弹飞
  • 让坦克控制子弹来发射

我们前面实现了让坦克动起来,这次我们需要让坦克进行开出炮弹的效果

一、让子弹飞


让子弹开炮,其实也就子弹,当我们发射的时候,其实也相当于是一个圆在不听的动

image.png

class Missle{

    int x;//子弹的x坐标
    int y;//子弹的y坐标

    Tank.Direction dir;//方向枚举

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

同时当我们坦克按下发射键的时候发射子弹,那么就需要将这个子弹画出来

class Missle{

    //省略其他关键性代码.......
    
    //添加方法完成子弹的绘画
    public void draw(Graphics g) {
        //获取默认的颜色Color
        Color c = g.getColor();
        //将子弹颜色为红色
        g.setColor(Color.black);
        //画一个子弹的大小
        g.fillOval(x, y, 10, 10);
        //将原颜色填充回
        g.setColor(c);   
    }
}

以及当我们发射子弹的时候,子弹是根据坦克的方向进行发射移动,那么也需要move方法

class Missle{

    //省略其他关键性代码.......
    
    //每次移动x坐标的步骤距离
    public static final int XSPEED = 10;

    //每次移动y坐标的步骤距离
    public static final int YSPEED = 10;
    
    //添加方法完成子弹的绘画
    public void draw(Graphics g) {
        
        //省略其他关键性代码.......
        //让坦克动起来
        move();
    }
    
    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;
        }
    }
}

那么我们这时根据思路new一个子弹出来,让它飞起来

public class TankClient extends Frame {
    
    //省略其他关键性代码.......
    
    //创建子弹对象
    Missle missle = new Missle(50,50, Tank.Direction.R);
    
    @Override
    public void paint(Graphics g) {
        //画出坦克....
        mytank.draw(g);
        //画出子弹....
        missle.draw(g);
    }
}

image.png

步骤思路总结

  • ✧添加Missile类
  • ✧添加x,y,dir等属性以及常量
  • ✧添加构造方法,draw方法等必要方法
  • ✧根据不同方向,进行不同的运动
  • ✧在TankClient中模拟一颗子弹
  • ✧new 一颗子弹出来并让他动起来

二、让坦克开炮

刚刚我们成功让子弹在界面上飞起来了,但是它是不听指挥的

那么我们如何完成当我们按下某个键的时候,根据坦克方向发射子弹呢?

第一步:坦克添加发射步骤的方法

public class Tank {
    
    //省略其他关键性代码.......
    
    //坦克发射子弹.....
    public Missle fire(){
        //根据坦克的坐标位置、方向、传给子弹
        Missle missle =new Missle(x,y,dir);
        return missle;
    }
}

第二步:添加Client关联坦克的发射子弹

之前我们的子弹是固定的,现在我们的子弹应该是由坦克来创建发射的

所以我们这里的坦克需要获取到Client,并将创建的子弹传递绘画出来

public class Tank {
    
    TankClient tc;
    
    public Tank(int x, int y, TankClient tc) {
        this(x,y);
        this.tc = tc;
    }
    
    //省略其他关键性代码.......
}

并且要由我们的坦克按下Ctrl键,创建子弹时我们从才进行绘画

public class TankClient extends Frame {
    
    //省略其他关键性代码.......
    Tank mytank = new Tank(50,50,this);
    
    //创建子弹对象
    Missle missle = null;
    
    @Override
    public void paint(Graphics g) {
        //画出坦克....
        mytank.draw(g);
        //画出子弹....
        if(missle != null){missle.draw(g)}
    }
}

第三步:添加坦克键盘按下Ctrl处理事件

public class Tank {
    
    //省略其他关键性代码.......
    //坦克键盘按下监听器
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        switch (key) {
            case KeyEvent.VK_CONTROL:
                tc.missle = fire();
                break;
            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;
        }
        locateDirection();
    }
}

image.png

这下我们的子弹可以由坦克按下Ctrl键进行发射出来了

步骤思路总结

  • ✧增加对Ctrl键的按键处理
  • ✧根据坦克发射子弹的思路,创建方法fire,其返回值为Missle
  • ✧添加构造方法,draw方法等必要方法
  • ✧根据不同方向,进行不同的运动
  • ✧在TankClient中模拟一颗子弹
  • ✧new 一颗子弹出来并让他动起来

但是有没有发现我们的子弹是由坦克的坐标左上角x,y的位置出发的

那么能不能由坦克的正中间出发呢?

三、优化坦克控制子弹开炮


image.png

将子弹、坦克的高度、宽度都设置为成员变量,给予固定

public class Tank {
    
    //坦克的宽度
    public static final int WIDTH = 30;
    //坦克的高度
    public static final int HEIGHT = 30;
    
    //添加方法完成坦克的绘画
    public void draw(Graphics g) {
        //省略其他关键性代码.......
        g.fillOval(x, y, WIDTH, HEIGHT);
    }
    //省略其他关键性代码.......
}
class Missle{

    //子弹的宽度
    public static final int WIDTH = 10;
    //子弹的高度
    public static final int HEIGHT = 10;
    
    //添加方法完成坦克的绘画
    public void draw(Graphics g) {
        //省略其他关键性代码.......
        g.fillOval(x, y, WIDTH, HEIGHT);
    }
    //省略其他关键性代码.......
}

修改坦克的fire方法,重新定位子弹的起始位置

public class Tank {
    
    //坦克发射子弹.....
    public Missle fire(){
        //根据坦克的坐标位置、方向、传给子弹
        int x = (this.x + WIDTH / 2) - Missle.WIDTH/2;
        int y = (this.y + HEIGHT / 2) - Missle.HEIGHT/2;
        Missle missle =new Missle(x,y,dir);
        return missle;
    }
    
    //省略其他关键性代码.......
}

参考资料


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

阅读 1.4k

心有多大,舞台就有多大

110 声望
23 粉丝
0 条评论

心有多大,舞台就有多大

110 声望
23 粉丝
文章目录
宣传栏