创建子弹类,根据传入的方向来使子弹坐标改变;
坦克类需要设置一个按键J来发射子弹,发射子弹后把方向传给子弹类得到一个子弹m,再给主类中的m;
主类中的m调用子弹类的draw方法,把子弹画出。
创建子弹类:设置宽高在draw方法中画出子弹,并在此方法中调用move方法使子弹可以移动。
移动的原理是根据传入的方向使x,y加减,加减的值越大子弹速度越快。
如何确定子弹发出的位置和方向:使用构造方法设置参数,在坦克类中调用传参。
import java.awt.*;
public class Missile {
int x,y;
public static final int WIDTH = 10;//子弹的宽
public static final int HEIGHT = 10;//子弹的高
public static final int XSPEED = 10;//子弹移动速度
public static final int YSPEED = 10;
Tank.Direction dir;//子弹方向
public Missile(int x,int y,Tank.Direction dir){
super();
this.x = x;
this.y = y;
this.dir = dir;
}
public void draw(Graphics g){
Color c = g.getColor();
g.setColor(Color.black);
g.fillOval(x,y,WIDTH,HEIGHT);
g.setColor(c);
move();
}
private void move() {
switch (dir) {//判断方向,子弹移动
case L:
x -= XSPEED;
break;
case LU:
x -= XSPEED;
y -= YSPEED;
break;
case U:
y -= XSPEED;
break;
case RU:
x += XSPEED;
y -= YSPEED;
break;
case R:
x += XSPEED;
break;
case RD:
x += XSPEED;
y += YSPEED;
break;
case D:
y += XSPEED;
break;
case LD:
x -= XSPEED;
y += YSPEED;
break;
case STOP:
break;
}
}
}
坦克类增加:
坦克类需要主类,将子弹m传入主类,主类中调用。
TankClient tc;
public Tank(int x,int y,TankClient tc){
this(x,y);
this.tc = tc;
}
private Missile fire(){
int x = this.x+Tank.WIDTH/2-Missile.WIDTH/2;//子弹相对坦克发出的位置
int y = this.y+Tank.HEIGHT/2-Missile.HEIGHT/2;
Missile m = new Missile(x,y,dir);
return m;
}
在按键抬起方法keyReleased()中增加按键J发射子弹:
case KeyEvent.VK_J:tc.m = fire();break;//不在按下,在抬手时发出子弹主类增加:
Missile m = null;//子弹
paint()方法画出子弹()
m.draw(g);
目前子弹可以在坦克移动时发射一颗,但是静止时子弹停止而且只能发射一颗子弹。
二、发射多颗子弹只能发射一颗子弹的原因:主类只能接收一个m。
可以使用集合解决此问题,坦克类发射一颗存入集合,主类中在集合中取出。
坦克类增加/修改:坦克每产生一颗子弹存入集合
fire()方法:
Missile m = new Missile(x,y,dir);
tc.missiles.add(m);
主类增加/修改
创建一个集合
Listmissiles =new ArrayList ();//存放子弹的集合
在paint方法中将m.draw(g)替换掉
可以显示子弹的数量。
g.drawString("子弹数量:"+missiles.size(),10,50);
for(int i = 0;i
三、停止时发射子弹
坦克不能在停止时发射子弹原因:子弹方向和坦克的移动方向是一个,坦克在停止时发射子弹,子弹也是停止的。
需要用另外一个变量来表示子弹的方向。
坦克类增加/修改
private Direction ptDir = Direction.D;//子弹发射方向
move()方法增加
if(this.dir != Direction.STOP){//排除坦克停止时的情况
this.ptDir = this.dir;//使子弹发射的方向为其余八个方向
}
四、增加炮筒
由于坦克只有一个椭圆是非常单调的且无法判断坦克的方向,可以在坦克上增加一个炮筒。
坦克类增加/修改
可以根据子弹的方向来画炮筒的方向
在draw方法中增加
switch (ptDir){//根据子弹方向来画炮筒
case L:g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x,y+Tank.HEIGHT/2);break;//x,y在坦克矩形的左上角
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;
}
五、子弹越界消失
子弹在发出后,是不会消失的。
需要解决子弹离开窗口后在集合移出的问题。
子弹类增加/删除
子弹类需要接收tc的子弹集合
private boolean live = true;//子弹的状态
private TankClient tc;
public Missile(int x,int y,Tank.Direction dir,TankClient tc){
this(x,y,dir);
this.tc =tc;
}
draw()方法增加:
如果子弹live状态为false,则在子弹集合中移出
if(!live){
tc.missiles.remove(this);
return;
}
move()方法增加:
判断子弹位置,如果离开窗口,则改变live状态为false。
//子弹越界
if(x<0||y<0||x>TankClient.GAME_WIDTH||y>TankClient.GAME_HEIGHT){
live = false;
}
坦克类增加/修改:
坦克类需要将tc的子弹集合传给子弹类,然后子弹类再删除。
fire()
Missile m = new Missile(x,y,ptDir,tc);
六、阻止坦克越界
坦克类增加/修改
坦克在将要出界时,改变坦克坐标,回到出界前。
move()方法增加
//阻止坦克越界
if(x<0) x = 0;
if(y<30) y = 30;
if(x+Tank.WIDTH>TankClient.GAME_WIDTH) x = TankClient.GAME_WIDTH-Tank.WIDTH;
if(x+Tank.HEIGHT>TankClient.GAME_HEIGHT) x = TankClient.GAME_HEIGHT-Tank.HEIGHT;
至此,坦克大战界面:(改了一下界面背景)



