坦克大战java版

时间:2023-03-09 14:34:24
坦克大战java版

吃了可以加血的血块类

import java.awt.*;

public class Blood {

    //血块移动的路径
int[][] pos = {
{450,250},{450,252},{450,254},{450,256},{450,258},{450,260},
{450,310},{452,300},{454,300},{456,300},{458,300},{460,300}
}; int x,y,w,h;
TankClient tc;
int step = 0;
private boolean live = true; /**
* 判断血块是否存在
* @return 返回真存在 假则不存在
*/
public boolean isLive() {
return live;
} /**
* 设置血块是否存在
* @param live 真则存在 假则不存在
*/
public void setLive(boolean live) {
this.live = live;
} /**
* 构造方法
* @param tc TankClient的引用
*/
public Blood(TankClient tc) {
this.w = 15;
this.h = 15;
this.x = pos[0][0];
this.y = pos[0][1];
this.tc = tc;
} /**
* 根据血块的位置画出血块
* @param g 画笔
*/
public void draw(Graphics g){
if(!live) return;
Color c = g.getColor();
g.setColor(Color.darkGray);
g.fillRect(x, y, w, h);
g.setColor(c);
move();
} /**
* 改变血块的位置
*/
public void move(){
if(step == pos.length) step = 0;
x = pos[step][0];
y = pos[step][1];
step++;
} /**
* 获得血块外围的矩形 检测碰撞使用
* @return Rectangle 矩形
*/
public Rectangle getRect(){
return new Rectangle(x,y,w,h);
} }

方向枚举

/**
* 定义方向的一个类
*/
public enum Direction {
L, LU, U, RU, R, RD, D, LD, STOP
}

负责爆炸绘图的类

import java.awt.*;
/**
* 爆炸的类
*
*/
public class Explode {
private int x,y;
private boolean live = true;
TankClient tc;
private int step = 0; private static Toolkit tk = Toolkit.getDefaultToolkit();
private static Image[] images = {
tk.getImage(Explode.class.getClassLoader().getResource("images/0.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/1.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/2.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/3.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/4.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/5.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/6.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/7.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/8.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/9.gif")),
tk.getImage(Explode.class.getClassLoader().getResource("images/10.gif"))
}; private boolean loaded = false; /**
* 构造方法
* @param x 爆炸的x坐标
* @param y 爆炸的y坐标
* @param tc TankClient的引用
*/
public Explode(int x,int y,TankClient tc){
this.x = x;
this.y = y;
this.tc = tc;
} /**
* 画出爆炸
* @param g 画笔
*/
public void draw(Graphics g){ if(!loaded) {
for (int i = 0; i < images.length; i++) {
g.drawImage(images[i], -100, -100, null);
}
loaded = true;
} if(!live) {
tc.explodes.remove(this);
return;
}
if(step == images.length){
live = false;
step = 0;
return;
}
g.drawImage(images[step], x, y, null); step++;
} }

子弹类

import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map; public class Missile {
/**
* 子弹x方向上的速度
*/
public static final int XSPEED = 20;
/**
* 子弹y方向上的速度
*/
public static final int YSPEED = 20; /**
* 子弹的宽度
*/
public static final int WIDTH = 10;
/**
* 子弹的高度
*/
public static final int HEIGHT = 10;
/**
* 敌方子弹的攻击力
*/
public static final int ATK = 20; int x, y;
Direction dir; private TankClient tc; private boolean live = true; private boolean good; private static Toolkit tk = Toolkit.getDefaultToolkit();
private static Image[] images = null;
private static Map<String, Image> imgs = new HashMap<String, Image>(); static{
images = new Image[]{
tk.getImage(Tank.class.getClassLoader().getResource("images/missileL.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/missileLU.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/missileU.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/missileRU.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/missileR.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/missileRD.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/missileD.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/missileLD.gif"))
};
imgs.put("L", images[0]);
imgs.put("LU",images[1]);
imgs.put("U", images[2]);
imgs.put("RU",images[3]);
imgs.put("R", images[4]);
imgs.put("RD",images[5]);
imgs.put("D", images[6]);
imgs.put("LD",images[7]);
} /**
* 判断子弹是否存在
* @return 返回真则存在 假则不存在
*/
public boolean isLive() {
return live;
} /**
* 构造方法
* @param x 子弹的x坐标
* @param y 子弹的y坐标
* @param dir 子弹的方向
*/
public Missile(int x, int y, Direction dir) {
this.x = x;
this.y = y;
this.dir = dir;
} /**
* 构造方法
* @param x 子弹的x坐标
* @param y 子弹的y坐标
* @param good 子弹的阵营(是哪个阵营的坦克打出来的)
* @param direction 方向
* @param tc TankClient的引用
*/
public Missile(int x,int y,boolean good,Direction direction ,TankClient tc){
this(x, y, direction);
this.tc = tc;
this.good =good;
} /**
* 根据子弹的位置画出子弹
* @param g
*/
public void draw(Graphics g) {
if(!live){
tc.missiles.remove(this);
return;
} switch(dir) {
case L:
g.drawImage(imgs.get("L"), x, y, null);
break;
case LU:
g.drawImage(imgs.get("LU"), x, y, null);
break;
case U:
g.drawImage(imgs.get("U"), x, y, null);
break;
case RU:
g.drawImage(imgs.get("RU"), x, y, null);
break;
case R:
g.drawImage(imgs.get("R"), x, y, null);
break;
case RD:
g.drawImage(imgs.get("RD"), x, y, null);
break;
case D:
g.drawImage(imgs.get("D"), x, y, null);
break;
case LD:
g.drawImage(imgs.get("LD"), x, y, null);
break;
} move();
} /**
* 改变子弹当前的位置
*/
public void move() {
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( x<0 || y<0 || x > TankClient.GAME_WIDTH || y > TankClient.GAME_HEIGHT){
live = false;
} } /**
* 获得子弹外围的矩形,用来检测碰撞
* @return Rectangle 矩形
*/
public Rectangle getRec(){
return new Rectangle(x,y,WIDTH,HEIGHT);
} /**
* 检测是否撞上了坦克
* @param t 坦克
* @return 返回真则击中坦克 假则没有击中坦克
*/
public boolean hitTank(Tank t){
if(this.live && this.getRec().intersects(t.getRec()) && t.isLive() && this.good != t.isGood()){
if(t.isGood()){
t.setLife(t.getLife() - ATK);
if(t.getLife() <= 0) t.setLive(false);
}else{
t.setLive(false);
}
this.live = false;
Explode e = new Explode(x, y, this.tc);
tc.explodes.add(e);
return true;
}
return false;
} /**
* 检测是否和其他坦克相撞
* @param tanks 储存所有坦克的顺序表
* @return 返回真则撞上 假则没有与任何坦克相撞
*/
public boolean hitTanks(List<Tank> tanks){
for(int i = 0;i<tanks.size();i++){
if(hitTank(tanks.get(i))){
return true;
}
}
return false;
} /**
* 检测是否撞墙
* @param w 墙
* @return 返回真则撞墙 假则没有撞墙
*/
public boolean hitWall(Wall w){
if(live && this.getRec().intersects(w.getRect())){
this.live = false;
return true;
}
return false;
} /**
* 检测子弹是否撞上了子弹
* @param missiles 所有的子弹
* @return 为真则撞上 假则没有撞上
*/
public boolean hitMissiles(java.util.List<Missile> missiles){
for(int i = 0 ; i<missiles.size();i++){
Missile m = missiles.get(i);
if(m.good && good) return false;
if(!m.good && !good) return false;
else if(m != this ){
if(live && m.isLive() &&this.getRec().intersects(m.getRec())){
live = false;
m.live = false;
return true;
}
}
}
return false;
}
}

坦克类

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.util.List;
import java.awt.Toolkit;
import java.util.*; public class Tank {
/**
* 坦克x方向上的速度
*/
public static final int XSPEED = 5;
/**
* 坦克y方向上的速度
*/
public static final int YSPEED = 5;
/**
* 坦克的宽度
*/
public static final int WIDTH = 30;
/**
* 坦克的高度
*/
public static final int HEIGHT = 30; /**
* 难度
*/
public static final int HARD = 15; TankClient tc; private static Random rn = new Random(); private boolean good ; private static Toolkit tk = Toolkit.getDefaultToolkit();
private static Image[] images = null;
private static Map<String, Image> imgs = new HashMap<String, Image>();
static{
images = new Image[]{
tk.getImage(Tank.class.getClassLoader().getResource("images/tankL.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/tankLU.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/tankU.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/tankRU.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/tankR.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/tankRD.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/tankD.gif")),
tk.getImage(Tank.class.getClassLoader().getResource("images/tankLD.gif"))
};
imgs.put("L", images[0]);
imgs.put("LU",images[1]);
imgs.put("U", images[2]);
imgs.put("RU",images[3]);
imgs.put("R", images[4]);
imgs.put("RD",images[5]);
imgs.put("D", images[6]);
imgs.put("LD",images[7]);
} /**
* 用来判断坦克的阵营
* @return good 为真则为友方 为假则为敌方
*/
public boolean isGood() {
return good;
} private boolean live = true; private int step = rn.nextInt(12)+3; private int life = 100; //坦克头上的血条
private BloodBar bb = new BloodBar(); /**
* 获得当前坦克的生命值
* @return life
*/
public int getLife() {
return life;
}
/**
* 设置坦克的生命值
* @param life
*/
public void setLife(int life) {
this.life = life;
} /**
* 判断坦克是否活着
* @return 返回真 则活着 假 则死亡
*/
public boolean isLive() {
return live;
} /**
* 设置坦克的生死 true为生 false为死
* @param live
*/
public void setLive(boolean live) {
this.live = live;
}
//当前坦克的位置
private int x, y;
//坦克前一次的位置
private int oldX,oldY; private boolean bL=false, bU=false, bR=false, bD = false; private Direction dir = Direction.STOP;
private Direction ptDir = Direction.D; /**
* 构造函数
* @param x 坦克的x坐标
* @param y 坦克的y坐标
* @param good 坦克的阵营(好坏)true为友方 false为敌方
*/
public Tank(int x, int y,boolean good) {
this.x = x;
this.y = y;
this.oldX = x;
this.oldY = y;
this.good = good;
} /**
* 构造函数
* @param x 坦克的x坐标
* @param y 坦克的y坐标
* @param good 坦克的阵营(好坏)true为友方 false为敌方
* @param dir 坦克初始化时的方向
* @param tc TankClient类的一个引用
*/
public Tank(int x, int y, boolean good,Direction dir, TankClient tc) {
this(x, y, good);
this.tc = tc;
this.dir = dir;
} /**
* 根据坦克的位置状态画出此坦克
* @param g 画笔
*/
public void draw(Graphics g) {
if(!isLive()) {
if(!good) tc.tanks.remove(this);
return;
}
//画血条
if(good) bb.draw(g); switch(ptDir) {
case L:
g.drawImage(imgs.get("L"), x, y, null);
break;
case LU:
g.drawImage(imgs.get("LU"), x, y, null);
break;
case U:
g.drawImage(imgs.get("U"), x, y, null);
break;
case RU:
g.drawImage(imgs.get("RU"), x, y, null);
break;
case R:
g.drawImage(imgs.get("R"), x, y, null);
break;
case RD:
g.drawImage(imgs.get("RD"), x, y, null);
break;
case D:
g.drawImage(imgs.get("D"), x, y, null);
break;
case LD:
g.drawImage(imgs.get("LD"), x, y, null);
break;
}
//记录前一步的位置
oldX = x;
oldY = y;
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(y+Tank.WIDTH > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT-Tank.HEIGHT;
} /**
* 坦克向前移动一步
*/
public void move() {
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(this.dir != Direction.STOP) {
this.ptDir = this.dir;
} if(!good){
if(step == 0){
step = rn.nextInt(12)+3;
Direction[] dirs = Direction.values();
int i = rn.nextInt(dirs.length);
this.dir = dirs[i];
}
step--;
if(rn.nextInt(40)>HARD) this.fire();
}
} /**
* 键盘按下的响应方法
* @param e 键盘事件
*/
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch(key) {
case KeyEvent.VK_LEFT :
bL = true;
break;
case KeyEvent.VK_1:
if(tc.myTank.getLife() == 0){
tc.myTank = new Tank(600, 600,true,Direction.STOP, tc);
}
break;
case KeyEvent.VK_UP :
bU = true;
break;
case KeyEvent.VK_RIGHT :
bR = true;
break;
case KeyEvent.VK_DOWN :
bD = true;
break;
/*case KeyEvent.VK_A:
superFire();
break;*/
}
locateDirection();
} /**
* 确定并设置坦克的移动方向
*/
void locateDirection() {
if(bL && !bU && !bR && !bD) dir = Direction.L;
else if(bL && bU && !bR && !bD) dir = Direction.LU;
else if(!bL && bU && !bR && !bD) dir = Direction.U;
else if(!bL && bU && bR && !bD) dir = Direction.RU;
else if(!bL && !bU && bR && !bD) dir = Direction.R;
else if(!bL && !bU && bR && bD) dir = Direction.RD;
else if(!bL && !bU && !bR && bD) dir = Direction.D;
else if(bL && !bU && !bR && bD) dir = Direction.LD;
else if(!bL && !bU && !bR && !bD) dir = Direction.STOP;
} /**
* 键盘松开的响应方法
* @param e 键盘事件
*/
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
switch(key) {
case KeyEvent.VK_SPACE:
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;
}
locateDirection();
} /**
* 沿着坦克的正方向发出一发炮弹
* @return Missile 返回炮弹的引用
*/
public Missile fire() {
if(!live) return null;
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, good, ptDir,this.tc);
tc.missiles.add(m);
return m;
} /**
* 设置一个方向 坦克开火 发射一枚炮弹
* @param dirsp 方向
* @return Missile 返回炮弹的引用
*/
public Missile fire(Direction dirsp) {
if(!live) return null;
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, good, dirsp,this.tc);
tc.missiles.add(m);
return m;
} /**
* 获取当前坦克的矩形
* @return Rectangle 矩形的引用
*/
public Rectangle getRec(){
return new Rectangle(x,y,WIDTH,HEIGHT);
} //回到前一次的位置
private void stay(){
x = oldX;
y = oldY;
} /**
* 是否撞上了墙
* @param w 被撞的墙
* @return 返回真则撞上 假则没有撞上
*/
public boolean hitWall(Wall w){
if(live && this.getRec().intersects(w.getRect())){
stay();
return true;
}
return false;
} /**
* 检测是否撞上了其他坦克
* @param tanks 储存其他坦克的顺序表
* @return 返回真则撞上 假则没有撞上
*/
public boolean hitTank(List<Tank> tanks){
for(int i = 0 ; i<tanks.size();i++){
if(tanks.get(i) != this){
if(live && tanks.get(i).isLive() &&this.getRec().intersects(tanks.get(i).getRec())){
stay();
return true;
}
}
}
return false;
} /**
* 向八个方向发射一枚炮弹
*/
public void superFire(){
Direction[] dirs = Direction.values();
for(int i = 0 ; i< 8 ;i++){
fire(dirs[i]);
}
} //画一个血条
private class BloodBar{
public void draw(Graphics g){
Color c = g.getColor();
g.setColor(Color.RED);
g.drawRect(x, y-5, WIDTH, 5);
int w = WIDTH * life/100;
g.fillRect(x, y-5, w, 5);
g.setColor(c);
}
} /**
* 吃血块 瞬间回满血量
* @param b 要吃的血块
* @return 返回真则吃到 假则没有吃到
*/
public boolean eatBlood(Blood b){
if(live && b.isLive() && this.getRec().intersects(b.getRect())){
b.setLive(false);
this.life = 100;
return true;
}
return false;
}
}

主界面

import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Random; public class TankClient extends Frame {
/**
* 游戏面板的宽度
*/
public static final int GAME_WIDTH = 800;
/**
* 游戏面板的高度
*/
public static final int GAME_HEIGHT = 600; //构建一个我方坦克
Tank myTank = new Tank(600, 600,true,Direction.STOP, this);
//构建一堵墙
Wall w1 = new Wall(100, 300, 300, 20, this);
//构建第二堵墙
Wall w2 = new Wall(200, 400, 20, 300, this);
//构建储存敌方坦克的顺序表
List<Tank> tanks = new ArrayList<Tank>();
//构建储存爆炸的顺序表
List<Explode> explodes = new ArrayList<Explode>();
//构建保存子弹的顺序表
List<Missile> missiles = new ArrayList<Missile>();
//构建一个加血的血块
Blood blood = new Blood(this);
//构建一个虚拟图像,作缓冲
Image offScreenImage = null;
/**
* 画出游戏窗体及之上的物体
*/
public void paint(Graphics g) {
/**
* 显示子弹,爆炸,坦克的数目及坦克的血量
*/
g.drawString("missiles count:" + missiles.size(), 10, 50);
g.drawString("explors count:" + explodes.size(), 10, 70);
g.drawString("tanks count:" + tanks.size(), 10, 90);
g.drawString("mytank life:" + myTank.getLife(), 10, 110); //挨个的将子弹画出来
for(int i=0; i<missiles.size(); i++) {
Missile m = missiles.get(i);
m.hitTanks(tanks);
m.hitTank(myTank);
m.hitWall(w1);
m.hitWall(w2);
m.hitMissiles(missiles);
m.draw(g);
} //重新构建出6个地方坦克
if(tanks.size() == 0){
for(int i=0;i<6;i++){
Tank t = new Tank(50+(i+1)*50,50,false,Direction.D,this);
tanks.add(t);
}
} //挨个的画出爆炸
for(int i=0;i<explodes.size();i++){
Explode e = explodes.get(i);
e.draw(g);
} //挨个的画出敌方坦克
for(int i=0 ; i<tanks.size();i++){
Tank t = tanks.get(i);
t.hitWall(w1);
t.hitWall(w2);
t.hitTank(tanks);
t.draw(g);
} //画出我方坦克
myTank.draw(g); /**
*画出两堵墙
*/
w1.draw(g);
w2.draw(g); myTank.eatBlood(blood);
blood.draw(g);
} /**
* 更新当前的窗口
*/
public void update(Graphics g) {
if(offScreenImage == null) {
offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);
}
Graphics gOffScreen = offScreenImage.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.BLACK);
gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage, 0, 0, null);
} /**
* 创建游戏窗体
*/
public void lauchFrame() { //游戏开始构建出10辆敌方坦克
for(int i=0;i<10;i++){
Tank t = new Tank(50+(i+1)*50,50,false,Direction.D,this);
tanks.add(t);
} /**
* 设置窗口的属性
* 增加消息监听
*/
this.setSize(GAME_WIDTH, GAME_HEIGHT);
this.setTitle("TankWar");
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.setResizable(false);
this.setBackground(Color.BLACK);
this.addKeyListener(new KeyMonitor());
setVisible(true); //添加一个消息监听线程
new Thread(new PaintThread()).start();
} /**
* 程序运行的主方法
* @param args
*/
public static void main(String[] args) {
TankClient tc = new TankClient();
tc.lauchFrame();
} /**
* 私有的线程类
* 用来控制床口的重画
*/
private class PaintThread implements Runnable { public void run() {
while(true) {
repaint();
try {
//设置窗口重画的时间间隔
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} /**
* 私有的监听类
* 用来监听一些按键响应
*/
private class KeyMonitor extends KeyAdapter { /**
* 松开按键的响应函数
*/
public void keyReleased(KeyEvent e) {
myTank.keyReleased(e);
} /**
* 按下键盘的响应函数
*/
public void keyPressed(KeyEvent e) {
myTank.keyPressed(e);
} }
}

墙的类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle; /**
* 墙的类
*/
public class Wall {
int x,y,w,h;
TankClient tc; /**
* 构造方法
* @param x 墙的x坐标
* @param y 墙的y坐标
* @param w 墙的宽度
* @param h 墙的高度
* @param tc TankClient的引用
*/
public Wall(int x, int y, int w, int h, TankClient tc) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.tc = tc;
} /**
* 画出这堵墙
* @param g 画笔
*/
public void draw(Graphics g){
Color color =g.getColor();
g.setColor(Color.PINK);
g.fillRect(x, y, w, h);
g.setColor(color);
} /**
* 获取这堵墙的外围矩形 用来检测碰撞使用
* @return Rectangle 矩形
*/
public Rectangle getRect(){
return new Rectangle(x,y,w,h);
} }

附带的图片 点击这里下载