package liu.yajie;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
/**
* 坦克类
* @author liuyajie
*
*/
public class Tank {
private int x, y;
//定义坦克移动的前一步
private int oldX, oldY;
//取出当前游戏窗口的句柄
TankClient tc;
/*
* 定义自己坦克的血量为100
* 创建自己坦克头顶的血条
*/
private int life = 100;
private BloodBar bb = new BloodBar();
/*
* 定义good来控制坦克类创建出的坦克是自己还是敌人,good为true时表示自己,否则为敌人
* 定义坦克的生死,live为true时为活着,否则为死掉
*/
private boolean good = true;
private boolean live = true;
//定义坦克水平和竖直方向移动速度
private static final int XSPEED = 5;
private static final int YSPEED = 5;
//坦克的宽、高
public static final int tWIDTH = 30;
public static final int tHEIGHT = 30;
//定义一个随机数
public static Random r = new Random();
//定义step为敌方坦克每次改变方向前移动随机数步
private int step = r.nextInt(12) + 3;
/*
* 键盘按键上、下、左、右被按下时bL、bU、bR、bD为true,否则为false
* 使用枚举定义坦克移动的方向
*/
private boolean bL = false, bU = false, bR = false, bD = false;
/*
* 开始坦克移动为STOP
* 定义坦克炮筒方向ptDir向上
*/
private direction dir = direction.STOP;
private direction ptDir = direction.U;
/**
* Tank构造方法
* @param x 坦克的x坐标
* @param y 坦克的y坐标
* @param good 坦克为自己(good=true)还是敌人(good=false)
* 记录坦克移动的前一步坐标,保存在oldX、oldY中
*/
public Tank(int x, int y, boolean good) {
this.x = x;
this.y = y;
this.oldX = x;
this.oldY = y;
this.good = good;
}
/**
* Tank 构造重载
* @param x 坦克x坐标
* @param y 坦克y坐标
* @param good 自己还是敌人
* @param dir 坦克初始方向
* @param tc 游戏窗口句柄
*/
public Tank(int x, int y, boolean good, direction dir, TankClient tc) {
this(x, y, good);
this.dir = dir;
this.tc = tc;
}
/**
* 绘制Tank函数
* @param g 参数画笔g
*/
public void draw(Graphics g) {
//敌方坦克死掉时随机产生一个血条
if(!live) {
if(!good) {
tc.tanks.remove(this);
if(this.r.nextInt(40) > 35) {
Blood b = new Blood(this.x, this.y , direction.D, tc);
b.setLive(true);
tc.bloods.add(b);
}
return;
}
return;
}
Color c = g.getColor();
if(good) g.setColor(Color.RED);
else g.setColor(Color.BLUE);
g.fillOval(x, y, tWIDTH, tHEIGHT);
g.setColor(c);
if(this.good) bb.draw(g);
//根据坦克的位置绘制坦克炮筒
switch(ptDir) {
case L:
g.drawLine(x + Tank.tWIDTH/2, y + Tank.tHEIGHT/2, x, y + Tank.tHEIGHT/2);
break;
case LU:
g.drawLine(x + Tank.tWIDTH/2, y + Tank.tHEIGHT/2, x, y);
break;
case U:
g.drawLine(x + Tank.tWIDTH/2, y + Tank.tHEIGHT/2, x + Tank.tWIDTH/2, y);
break;
case RU:
g.drawLine(x + Tank.tWIDTH/2, y + Tank.tHEIGHT/2, x + Tank.tWIDTH, y);
break;
case R:
g.drawLine(x + Tank.tWIDTH/2, y + Tank.tHEIGHT/2, x + Tank.tWIDTH, y + Tank.tHEIGHT/2);
break;
case RD:
g.drawLine(x + Tank.tWIDTH/2, y + Tank.tHEIGHT/2, x + Tank.tWIDTH, y + Tank.tHEIGHT);
break;
case D:
g.drawLine(x + Tank.tWIDTH/2, y + Tank.tHEIGHT/2, x + Tank.tWIDTH/2, y + Tank.tHEIGHT);
break;
case LD:
g.drawLine(x + Tank.tWIDTH/2, y + Tank.tHEIGHT/2, x, y + Tank.tHEIGHT);
break;
}
//调用Tank的move方法
move();
}
/**
* 根据坦克方向处理坦克的移动
* 记录坦克移动的前一个位置保存在oldX、oldY中
*/
public void move() {
oldX = x;
oldY = y;
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;
case STOP:
break;
}
//当坦克状态不是停止时,将坦克方向传递给炮筒
if(dir != direction.STOP) {
ptDir = dir;
}
/*
* 当坦克移动到游戏窗口的边界时,改变坦克的位置坐标
*/
int distance = 3;
if(x < distance) x = distance;
if(y < 30) y = 30;
if(x > TankClient.GAME_WIDTH - Tank.tWIDTH - distance) x = TankClient.GAME_WIDTH - Tank.tWIDTH - distance;
if(y > TankClient.GAME_HEIGTH - Tank.tHEIGHT - distance) y = TankClient.GAME_HEIGTH - Tank.tHEIGHT - distance;
/*
* 敌方坦克随机的给定方向枚举中一个随机方向dirs[rn]
* 并且在改变方向前移动随机step步
* 当随机数r.nextInt(40)>38时让敌方坦克发出炮弹
*/
if(!good) {
direction[] dirs = direction.values();
if(step == 0) {
step = r.nextInt(12) + 3;
int rn = r.nextInt(dirs.length);
dir = dirs[rn];
}
step --;
if(r.nextInt(40) > 38) this.fire();
}
}
/**
* 利用已定义的四个boolean类型的ture与false判断坦克移动方向
*/
void locateDirection() {
if(bL && !bU && !bR && !bD) dir = direction.L;
if(bL && bU && !bR && !bD) dir = direction.LU;
if(!bL && bU && !bR && !bD) dir = direction.U;
if(!bL && bU && bR && !bD) dir = direction.RU;
if(!bL && !bU && bR && !bD) dir = direction.R;
if(!bL && !bU && bR && bD) dir = direction.RD;
if(!bL && !bU && !bR && bD) dir = direction.D;
if(bL && !bU && !bR && bD) dir = direction.LD;
if(!bL && !bU && !bR && !bD) dir = direction.STOP;
}
/**
* 处理键盘方向按键消息
* @param e KeyEvent事件
*/
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch(key) {
case KeyEvent.VK_F2:
if(!this.live) {
this.live = true;
this.life = 100;
}
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();
}
/**
* 当键盘按键被释放时,处理键盘按键消息
* @param e KeyEvent事件
*/
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
switch(key) {
//释放ctrl键时,自己坦克发射炮弹
case KeyEvent.VK_CONTROL:
fire();
break;
case KeyEvent.VK_LEFT:
bL = false;
break;
case KeyEvent.VK_UP:
bU = false;
break;
case KeyEvent.VK_RIGHT:
bR = false;
break;
case KeyEvent.VK_DOWN:
bD = false;
break;
case KeyEvent.VK_A:
superFire();
break;
}
//定位坦克的方向
locateDirection();
}
/**
* 当坦克碰撞到墙壁、坦克时,让坦克移动到前一位置
*/
private void stay() {
this.x = this.oldX;
this.y = this.oldY;
}
/**
* 当坦克活着时,计算子弹的发射位置,子弹方向与炮筒方向一致,并将发射的子弹加入TankClient定义的容器missiles中
* @return 返回发射的子弹
*/
public Missile fire() {
if(!this.isLive()){
return null;
}
int mX = x + Tank.tWIDTH/2 - Missile.mWIDTH/2;
int mY = y + Tank.tHEIGHT/2 - Missile.mHEIGHT/2;
Missile m = new Missile(mX, mY, good, ptDir, this.tc);
tc.missiles.add(m);
return m;
}
/**
* 坦克发射子弹时给子弹一个坦克方向
* @param dir 当前坦克移动方向
* @return 一个子弹
*/
public Missile fire(direction dir) {
if(!this.isLive()){
return null;
}
int mX = x + Tank.tWIDTH/2 - Missile.mWIDTH/2;
int mY = y + Tank.tHEIGHT/2 - Missile.mHEIGHT/2;
Missile m = new Missile(mX, mY, good, dir, this.tc);
tc.missiles.add(m);
return m;
}
/**
* 得到坦克当前生死状态
* @return 返回boolean类型,true为活着,false为死掉
*/
public boolean isLive() {
return live;
}
/**
* 设置坦克的生死
* @param live 坦克live生死值(bool类型)
*/
public void setLive(boolean live) {
this.live = live;
}
/**
* 得到坦克的矩形区域
* @return 坦克矩形区域
*/
public Rectangle getTankRect() {
return new Rectangle(x, y, Tank.tWIDTH, Tank.t
评论0