本章目标
- 应用炮筒来确定坦克目前的方向
- 让坦克发射多发炮弹问题
一、画出炮筒
个别坦克初始地位是不同的,然而咱们目前的射击方向是与挪动方向统一的
这就导致比拟怪异,咱们应该是初始时有一个射击方向,比如说:左边
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 )
- ✧当炮弹曾经死去就不须要对其重画
- ✧当炮弹飞出边界就死亡
- ✧当炮弹死亡就从容器中去除
参考资料
尚学堂:坦克大战(马士兵老师)