本章目标
- 应用炮筒来确定坦克目前的方向
- 让坦克发射多发炮弹问题
一、画出炮筒
个别坦克初始地位是不同的,然而咱们目前的射击方向是与挪动方向统一的
这就导致比拟怪异,咱们应该是初始时有一个射击方向,比如说:左边
class Tank{
// 省略其余关键性代码....
// 默认设计方向为左边
private Direction ptdir = Direction.R;
}
而咱们的射击方向有了,还须要与挪动时方向统一同步并且画进去
这里咱们只须要画出一条直线即可,能够应用 drawLine 办法
咱们须要晓得两点来确定一条直线,而在坐标中由横 (X)、纵坐标(y) 确定一个点。
而这 drawLine 办法的四参数理论就是确定两个点,要画的直线的起始点横纵坐标和起点的横纵坐标
X1,Y1 是确定直线的起始点,即横坐标为 x1,纵坐标为 y1 的点。
同理 x2,y2 确定直线的起点。
例:
A(x1,y1) B(x2,y2) 就能够画出直线 AB 了。
参数:
x1 – 第一个点的 x 坐标。
y1 – 第一个点的 y 坐标。
x2 – 第二个点的 x 坐标。
y2 – 第二个点的 y 坐标。
而咱们的坦克中,想要画出对应方向的直线,则能够应用公式计算相应的坐标
class Tank{
// 省略其余关键性代码....
// 增加办法实现坦克的绘画
public void draw(Graphics g) {
// 省略其余关键性代码....
switch (ptdir) {
case L:
g.drawLine(x + Tank.WIDTH/2,y + Tank.HEIGHT/2,x,y + Tank. HEIGHT/2);
break;
case LU:
g.drawLine(x + Tank.WIDTH/2,y + Tank.HEIGHT/2,x,y);
break;
case U:
g.drawLine(x + Tank.WIDTH/2,y + Tank.HEIGHT/2,x + Tank.WIDTH/2,y);
break;
case RU:
g.drawLine(x + Tank.WIDTH/2,y + Tank.HEIGHT/2,x + Tank.WIDTH,y);
break;
case R:
g.drawLine(x + Tank.WIDTH/2,y + Tank.HEIGHT/2,x + Tank.WIDTH,y + Tank. HEIGHT/2);
break;
case RD:
g.drawLine(x + Tank.WIDTH/2,y + Tank.HEIGHT/2,x + Tank.WIDTH,y + Tank. HEIGHT);
break;
case D:
g.drawLine(x + Tank.WIDTH/2,y + Tank.HEIGHT/2,x + Tank.WIDTH/2,y + Tank. HEIGHT);
break;
case LD:
g.drawLine(x + Tank.WIDTH/2,y + Tank.HEIGHT/2,x,y + Tank. HEIGHT);
break;
}
}
}
这时咱们运行起来就发现,咱们的坦克炮筒曾经进去了
然而为什么它没有随着咱们的挪动方向而扭转射击方向呢?
那么因为咱们没有依据挪动方向来进行调整,咱们当初增加调整一下看看
class Tank{
// 省略其余关键性代码....
void move() {
// 省略其余关键性代码....
if(this.dir !=Direction.STOP){this.ptdir = dir;}
}
}
而之前咱们依据坦克的方向进行发射炮弹,会有一个问题不晓得大家发现没有
比如说当咱们不动的时候,是无奈发射炮弹进去的
那么当初咱们依据射击方向进行发射,就能够解决这个问题
class Tank{
// 省略其余关键性代码....
// 坦克发射子弹.....
public Missle fire(){
// 省略其余关键性代码....
Missle missle = new Missle(x,y,ptdir);
return missle;
}
}
这时即便咱们不动,也能够发射炮弹了
步骤总结
- ✧Tank 类减少新的属性 ptDir
- ✧每次 move 后依据 Tank 新的方向确定炮筒的方向
- ✧将炮简用直线的模式体现进去
二、让坦克发射多发炮弹
目前咱们的坦克按下 Ctrl 键时,就会发射一发炮弹
然而当咱们再按下 Ctrl 键时,就会发现坦克收回的炮弹又从头开始了
这是因为咱们目前只保护了一发炮弹的发射状态
那么怎么解决这个问题呢?
咱们想想能不能将收回去的炮弹用一个容器将它装起来呢?
public class TankClient extends Frame {
// 应用汇合容器治理炮弹
List<Missle> missles = new ArrayList<Missle>();
@Override
public void paint(Graphics g) {
// 画出容器里的子弹
for (int i = 0; i < missles.size();i++){Missle m = missles.get(i);
m.draw(g);
}
// 画出坦克
mytank.draw(g);
}
// 省略其余关键性代码....
}
同时当咱们按下 Ctrl 键时,咱们就将炮弹放入汇合容器中
class Tank{
// 坦克发射子弹.....
public Missle fire(){
// 省略其余关键性代码.......
Missle missle =new Missle(x,y,ptdir);
tc.missles.add(missle);
return missle;
}
}
这时咱们运行起来就能够发现,咱们能够间断打出多发炮弹了
然而有一个小问题:如果始终按住 Ctrl 键收回的炮弹就会没有距离
这样的状况咱们有两种解决形式:
- 第一种:每一枚炮弹设置间隔时间
- 第二种:将发射炮弹改为按下抬起开释 Ctrl 键发射炮弹
咱们采纳 Ctrl 键按下抬起发射炮弹来解决这个问题
class Tank{
// 省略其余关键性代码....
// 坦克键盘按下抬起监听器
public void keyReleased(KeyEvent e) {int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_CONTROL:
fire();
break;
}
// 省略其余关键性代码.......
}
}
步骤总结
- ✧应用容器装炮弹
- ✧每当抬起 Ctr 键就往容器中退出新的炮弹
- ✧逐个画出每一发炮弹
三、让炮弹沦亡
因为咱们目前采纳汇合容器的形式来治理发射的炮弹
若咱们对于这个游戏始终玩个几小时,那么就会造成很多很多的炮弹积攒在外面
咱们当初在游戏的窗口中将咱们以后的炮弹数量显示进去
public class TankClient extends Frame {
// 省略其余关键性代码....
@Override
public void paint(Graphics g) {
// 省略其余关键性代码....
// 展现炮弹容器以后数量
g.drawString("missiles count:" + missles.size()+"",10,50);
}
}
这下咱们以后容器里的子弹数量就能显示进去了
刚刚咱们说到若咱们对于这个游戏始终玩个几小时,那么就会造成很多很多的炮弹积攒在外面
那么咱们什么时候就要让子弹沦亡呢?
- 击中敌方坦克时
- 超出游戏边界时
咱们为 Missle 子弹类增加属性区别存活状态、并且当超出边界时设置为沦亡状态
class Missle{
// 辨别子弹的存活
private boolean live = true;
public boolean isLive() {return live;}
void move() {
// 省略其余关键性代码....
// 当子弹的 x、y 坐标小于 0 或者大于游戏窗口的宽度与高度则沦亡状态
if (x < 0 || y < 0 || x > TankClient.WIDTH || y > TankClient.HEIGHT) {live = false;}
}
// 省略其余关键性代码....
}
而在咱们的游戏界面中的绘画办法,对于沦亡的子弹咱们从容器中里去除
class Missle{
// 引入 TankClient 治理子弹容器
private TankClient tc;
public Missle(int x, int y, Tank.Direction dir, TankClient tc) {
this.x = x;
this.y = y;
this.dir = dir;
this.tc = tc;
}
void move() {
// 省略其余关键性代码....
// 当子弹的 x、y 坐标小于 0 或者大于游戏窗口的宽度与高度则沦亡状态
if (x < 0 || y < 0 || x > TankClient.GAME_WINDTH || y > TankClient.GAME_HEIGHT) {
this.live = false;
tc.missles.remove(this);
}
// 省略其余关键性代码....
}
同时当咱们收回炮弹的时候,将 tc 传给炮弹,让炮弹在沦亡的时候本人去除
class Tank{
// 省略其余关键性代码....
// 坦克发射子弹.....
public Missle fire(){
// 省略其余关键性代码.......
Missle missle =new Missle(x,y,ptdir,tc);
tc.missles.add(missle);
return missle;
}
}
步骤总结
- ✧退出管制炮弹生死的量 Live (Missle)
- ✧当炮弹曾经死去就不须要对其重画
- ✧当炮弹飞出边界就死亡
- ✧当炮弹死亡就从容器中去除
参考资料
尚学堂:坦克大战(马士兵老师)