本篇文章目的
- 让子弹飞
- 让坦克控制子弹来发射
我们前面实现了让坦克动起来,这次我们需要让坦克进行开出炮弹的效果
一、让子弹飞
让子弹开炮,其实也就子弹,当我们发射的时候,其实也相当于是一个圆在不听的动
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);
}
}
步骤思路总结
- ✧添加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();
}
}
这下我们的子弹可以由坦克按下Ctrl键进行发射出来了
步骤思路总结
- ✧增加对Ctrl键的按键处理
- ✧根据坦克发射子弹的思路,创建方法fire,其返回值为Missle
- ✧添加构造方法,draw方法等必要方法
- ✧根据不同方向,进行不同的运动
- ✧在TankClient中模拟一颗子弹
- ✧new 一颗子弹出来并让他动起来
但是有没有发现我们的子弹是由坦克的坐标左上角x,y的位置出发的
那么能不能由坦克的正中间出发呢?
三、优化坦克控制子弹开炮
将子弹、坦克的高度、宽度都设置为成员变量,给予固定
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;
}
//省略其他关键性代码.......
}
参考资料
尚学堂:坦克大战(马士兵老师)