坦克能移动了,接下来就是发射子弹了。
于是我们需要一个子弹类
public class Bullet {
// 位置
int local_x;
int local_y;
// 大小
int width = 3;
int height = 3;
// 方向
Direction dir;
// 存活
boolean is_Dead;
// 敌我
boolean is_enemy;
// 图片
Image BulletIamge;
public int getLocal_x() {
return local_x;
}
public void setLocal_x(int local_x) {
this.local_x = local_x;
}
public int getLocal_y() {
return local_y;
}
public void setLocal_y(int local_y) {
this.local_y = local_y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public Direction getDir() {
return dir;
}
public void setDir(Direction dir) {
this.dir = dir;
}
public boolean isIs_Dead() {
return is_Dead;
}
public void setIs_Dead(boolean is_Dead) {
this.is_Dead = is_Dead;
}
public boolean isIs_enemy() {
return is_enemy;
}
public void setIs_enemy(boolean is_enemy) {
this.is_enemy = is_enemy;
}
public Image getBulletIamge() {
return BulletIamge;
}
public void setBulletIamge(Image bulletIamge) {
BulletIamge = bulletIamge;
}
public Bullet(int local_x, int local_y, Direction dir, boolean is_enemy) {
super();
this.local_x = local_x;
this.local_y = local_y;
this.dir = dir;
this.is_enemy = is_enemy;
}
public void draw() {// 获取子弹图片
if (!isIs_enemy()) {
setBulletIamge(Toolkit.getDefaultToolkit().getImage("tankmissile"));
} else {
setBulletIamge(Toolkit.getDefaultToolkit().getImage("tankmissile"));
}
}
}
设定按空格键时开火,在KeyContral中添加控制开火键,因为坦克和子弹是对应的,于是在Tank类中加一个子弹属性,又由于是一群子弹,故用ArrayList实现。
//子弹集
ArrayList bullets = new ArrayList<>();
public abstract void fire();//开火
在MyTank中重写fire();
@Override
public void fire() {
this.bullets.add(new Bullet(local_x + (width - Bullet.width) / 2, local_y + (height - Bullet.height) / 2, pdir,
is_enemy));
}
在keyPressed方法中添加fire()
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_SPACE://空格开火
fire();
break;
case KeyEvent.VK_UP:
pdir = dir = Direction.U;
break;
case KeyEvent.VK_DOWN:
pdir = dir = Direction.D;
break;
case KeyEvent.VK_LEFT:
pdir = dir = Direction.L;
break;
case KeyEvent.VK_RIGHT:
pdir = dir = Direction.R;
break;
default:
pdir = dir = Direction.Stop;
}
}
子弹出生便一直移动,直到死亡,目前没有敌机,所以碰墙死亡,用move()实现
public void move(){
if(this.local_x<0||this.local_x>TankFrame.Frame_Width||this.local_y<0||this.local_y>TankFrame.Frame_Height){
setIs_Dead(true);
}else{
switch(dir){
case U: setLocal_y(local_y-speed);break;
case D: setLocal_y(local_y+speed);break;
case L: setLocal_x(local_x-speed);break;
case R: setLocal_y(local_x+speed);break;
default: setLocal_y(local_x+speed);
}
}
}
子弹被new在出来后要绘制出来才能看见,在TankPanel中添加绘制代码(所有绘制都在其中)
// 绘制我方子弹
for (int i = 0; i < mtank.getBullets().size(); i++) {
Bullet b = mtank.getBullets().get(i);
if (b.isIs_Dead() == true) {
mtank.getBullets().remove(i);// 死亡则移除
} else {
b.draw();
g.drawImage(b.getBulletIamge(), b.getLocal_x(), b.getLocal_y(), Bullet.width, Bullet.height, this);
b.move();
}
}
效果如下:
完整源码如下:
TankFrame:
public class TankFrame extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public static int Frame_Width = 500;
public static int Frame_Height = 500;
TankPanel TP = new TankPanel();
public void launchFrame() {
// 窗口大小及位置
setSize(Frame_Width, Frame_Height);
setLocation(1000, 100);
add(TP);
addKeyListener(TP.mtank.kc);// 添加键盘控制
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
new Thread(TP).start();// 启动线程
}
public static void main(String[] args) {
new TankFrame().launchFrame();
}
}
TankPanel:
public class TankPanel extends JPanel implements Runnable {
/**
*
*/
private static final long serialVersionUID = 1L;
MyTank mtank = new MyTank(100, 100, false);
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(0, 0, TankFrame.Frame_Width, TankFrame.Frame_Height);
// 绘制我方坦克
mtank.draw();
g.drawImage(mtank.getTankImage(), mtank.getLocal_x(), mtank.getLocal_y(), mtank.getWidth(), mtank.getHeight(),
this);
mtank.move();
// 绘制我方子弹
for (int i = 0; i < mtank.getBullets().size(); i++) {
Bullet b = mtank.getBullets().get(i);
if (b.isIs_Dead() == true) {
mtank.getBullets().remove(i);// 死亡则移除
} else {
b.draw();
g.drawImage(b.getBulletIamge(), b.getLocal_x(), b.getLocal_y(), Bullet.width, Bullet.height, this);
b.move();
}
}
}
@Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Tank:
public abstract class Tank {
// 位置
int local_x;
int local_y;
// 大小
int width = 20;
int height = 20;
// 速度
int speed = 5;
// 运动方向
Direction dir;
// 炮筒方向
Direction pdir;
// 坦克图片
Image tankImage;
// 敌我
boolean is_enemy;
// 死亡
boolean is_Dead;
// 子弹集
ArrayList bullets = new ArrayList<>();
public int getLocal_x() {
return local_x;
}
public void setLocal_x(int local_x) {
this.local_x = local_x;
}
public int getLocal_y() {
return local_y;
}
public void setLocal_y(int local_y) {
this.local_y = local_y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public Direction getDir() {
return dir;
}
public void setDir(Direction dir) {
this.dir = dir;
}
public Direction getPdir() {
return pdir;
}
public void setPdir(Direction pdir) {
this.pdir = pdir;
}
public Image getTankImage() {
return tankImage;
}
public void setTankImage(Image tankImage) {
this.tankImage = tankImage;
}
public boolean isIs_enemy() {
return is_enemy;
}
public void setIs_enemy(boolean is_enemy) {
this.is_enemy = is_enemy;
}
public boolean isIs_Dead() {
return is_Dead;
}
public void setIs_Dead(boolean is_Dead) {
this.is_Dead = is_Dead;
}
public ArrayList getBullets() {
return bullets;
}
public void setBullets(ArrayList bullets) {
this.bullets = bullets;
}
public Tank(int local_x, int local_y, boolean is_enemy) {
super();
this.local_x = local_x;
this.local_y = local_y;
this.is_enemy = is_enemy;
}
public abstract void draw();// 绘制相关函数(获取图片)
public abstract void move();// 移动函数
public abstract void fire();// 开火
public abstract Rectangle getRec();// 获取当前位置,返回对应矩形
public abstract Rectangle getNextRec();// 获取移动后的位置,返回对应矩形
}
MyTank:
public class MyTank extends Tank {
// 坦克移动方向
Direction dir = Direction.Stop;
// 坦克炮筒方向
Direction pdir = Direction.U;
public KeyContral kc = new KeyContral();
public MyTank(int local_x, int local_y, boolean is_enemy) {
super(local_x, local_y, is_enemy);
// TODO Auto-generated constructor stub
}
@Override
public void draw() {
switch (pdir) {
case U:// 注意不能用Direction.U
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankU.gif"));
break;
case D:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankD.gif"));
break;
case L:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankL.gif"));
break;
case R:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankR.gif"));
break;
default:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankU.gif"));
}
}
@Override
public void move() {// 实现移动,并控制不越界
if (dir == Direction.U) {
if (local_y - speed >= 0)
setLocal_y(local_y - speed);
} else if (dir == Direction.D) {
if (local_y + speed <= TankFrame.Frame_Height - (height * 2 + height / 3))
setLocal_y(local_y + speed);
} else if (dir == Direction.L) {
if (local_x - speed >= 0)
setLocal_x(local_x - speed);
} else if (dir == Direction.R) {
if (local_x + speed <= TankFrame.Frame_Width - (width + width / 3))
setLocal_x(local_x + speed);
} else {
}
}
@Override
public Rectangle getRec() {
return null;
}
@Override
public Rectangle getNextRec() {
return null;
}
public class KeyContral extends KeyAdapter {// 按下方向改变
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_SPACE:// 空格开火
fire();
break;
case KeyEvent.VK_UP:
pdir = dir = Direction.U;
break;
case KeyEvent.VK_DOWN:
pdir = dir = Direction.D;
break;
case KeyEvent.VK_LEFT:
pdir = dir = Direction.L;
break;
case KeyEvent.VK_RIGHT:
pdir = dir = Direction.R;
break;
default:
dir = Direction.Stop;
}
}
@Override
public void keyReleased(KeyEvent e) {// 释放移动方向改变恢复,指向不改变
super.keyReleased(e);
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_UP:
dir = Direction.Stop;
break;
case KeyEvent.VK_DOWN:
dir = Direction.Stop;
break;
case KeyEvent.VK_LEFT:
dir = Direction.Stop;
break;
case KeyEvent.VK_RIGHT:
dir = Direction.Stop;
break;
}
}
}
@Override
public void fire() {
this.bullets.add(new Bullet(local_x + (width - Bullet.width) / 2, local_y + (height - Bullet.height) / 2, pdir,
is_enemy));
}
}
Bullet:
public class Bullet {
// 位置
int local_x;
int local_y;
// 大小
public static int width = 4;
public static int height = 4;
// 方向
Direction dir;
// 速度
int speed = 8;
// 存活
boolean is_Dead;
// 敌我
boolean is_enemy;
// 图片
Image BulletIamge;
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public int getLocal_x() {
return local_x;
}
public void setLocal_x(int local_x) {
this.local_x = local_x;
}
public int getLocal_y() {
return local_y;
}
public void setLocal_y(int local_y) {
this.local_y = local_y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Direction getDir() {
return dir;
}
public void setDir(Direction dir) {
this.dir = dir;
}
public boolean isIs_Dead() {
return is_Dead;
}
public void setIs_Dead(boolean is_Dead) {
this.is_Dead = is_Dead;
}
public boolean isIs_enemy() {
return is_enemy;
}
public void setIs_enemy(boolean is_enemy) {
this.is_enemy = is_enemy;
}
public Image getBulletIamge() {
return BulletIamge;
}
public void setBulletIamge(Image bulletIamge) {
BulletIamge = bulletIamge;
}
public Bullet(int local_x, int local_y, Direction dir, boolean is_enemy) {
super();
this.local_x = local_x;
this.local_y = local_y;
this.dir = dir;
this.is_enemy = is_enemy;
}
public void draw() {// 获取子弹图片
if (!isIs_enemy()) {
setBulletIamge(Toolkit.getDefaultToolkit().getImage("tankmissile.gif"));
} else {
setBulletIamge(Toolkit.getDefaultToolkit().getImage("enemymissile.gif"));
}
}
public void move() {
if (this.local_x < 0 || this.local_x > TankFrame.Frame_Width || this.local_y < 0
|| this.local_y > TankFrame.Frame_Height) {
setIs_Dead(true);// 触边界死亡
} else {
switch (this.dir) {
case U:
setLocal_y(local_y - speed);
break;
case D:
setLocal_y(local_y + speed);
break;
case L:
setLocal_x(local_x - speed);
break;
case R:
setLocal_x(local_x + speed);
break;
default:
setLocal_y(local_y - speed);
}
}
}
}
Direction:
public enum Direction {
U,D,L,R,Stop
}