//存在缺陷:敌军偶尔会隐身,有些地方要改进下,如加入墙的方式
package com.liuqinlin.TankWar图片版;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
/**
* 这个类是游戏的主窗口
* 它控制着子弹、坦克、墙、爆炸和血块的引用
*/
public class TankWarClient extends Frame{
/**
* 显示游戏窗口的大小
*/
public static final int Game_WIDTH=820;
public static final int Game_HEIGTH=660;
Image OffScreenImage=null;
Image image=null ;
Image GameOver=null ;
Tank MyTank=new Tank(290, 622, this, true ,direction.STOP);
Boold bd=new Boold();
/**
* 对我军坦克超级炮弹数量的控制
*/
int multiCounts=5 ;
int superCounts=8 ;
//为打不烂的墙专门设置对象
/**
* 设置两堵墙的大小和方位
*/
Tank EnemyTank;
Missile myTank;
/**
* 设置容器来装子弹、爆炸、和敌军坦克
*/
List<Missile> Missiles=new ArrayList<Missile>();
List<Explode> Explodes=new ArrayList<Explode>();
List<Tank> EnemyTanks=new ArrayList<Tank>();
List<Wall>walls=new ArrayList<Wall>();
List<Image>images=new ArrayList<Image>() ;
List<Wall>nonWalls=new ArrayList<Wall>() ;
/**
* 画出血条和显示子弹、坦克、生命值等
* 并获取对坦克类 、子弹类等的引用
*/
public void paint(Graphics g) {
//显示炮弹数量
Color c=g.getColor();
g.setColor(Color.red);
g.drawString("multiMissiles Count: "+multiCounts , 20, 40);
g.drawString("EnemyTanks Count:"+EnemyTanks.size(), 20, 60);
g.drawString("Missiles Count:"+Missiles.size(), 20, 80);
g.setColor(c);
GameOver=Toolkit.getDefaultToolkit().getImage(Tank.class.getClassLoader().getResource("Images/GameOver.jpg") );
/**
* 敌军坦克被消灭光后自动加入8辆敌军坦克
*/
if(EnemyTanks.size()<=0){
for(int i=0; i<8; i++){
EnemyTanks.add(new Tank(50+60*(i+1), 0 , this, false ,direction.D));
}
}
//需要改进
for(int i=0 ; i<images.size(); i++){
image=images.get(i);
g.drawImage(image, 371 , 577 , null);
}
if(images.size()==0){
g.drawImage(GameOver, 3, 25 ,null);
return ;
}
for(int i=0 ; i<walls.size(); i++){
Wall wallt=walls.get(i) ;
wallt.draw(g);
}
for(int i=0 ; i<nonWalls.size(); i++){
Wall nonWall=nonWalls.get(i);
nonWall.draw(g);
}
/**
* 从容器中取出子弹并打击敌军坦克和敌军坦克打击我军坦克
* 对子弹撞墙进行控制处理
*/
for(int i=0;i<Missiles.size();i++){
myTank=Missiles.get(i);
myTank.isHitTanks(EnemyTanks);
myTank.isHitTank(MyTank);
myTank.isHitImage(images);
myTank.isHitWall(walls);
myTank.isHitNonWalls(nonWalls);
myTank.draw(g);
}
/**
* 从爆炸容器中获取爆炸并画出效果
*/
for(int i=0;i<Explodes.size();i++){
Explode e=Explodes.get(i);
e.draw(g);
}
/**
* 从敌军坦克容器中画出坦克
*
*/
for(int i=0; i<EnemyTanks.size() ;i++){
EnemyTank= EnemyTanks.get(i);
/**
* 敌军坦克撞墙处理引用
*/
EnemyTank.isCollidesWithWall(walls);
EnemyTank.isCollidesWithNonWall(nonWalls);
/**
* 敌军坦克间的碰撞处理引用
* 敌军坦克和我军坦克间的碰撞处理引用
*/
EnemyTank.isCollidesWithTanks(EnemyTanks);
EnemyTank.isCollidesWithTank(MyTank);
EnemyTank.draw(g);
}
/**
* 对画出血块的引用
* 画出我军坦克并对其吃血块处理的引用
* 画出两堵墙的引用
*/
MyTank.isCollidesWithWall(walls);
MyTank.isCollidesWithNonWall(nonWalls);
bd.draw(g);
MyTank.draw(g);
MyTank.eatBoold(bd);
}
/**
* 本方法使用双缓冲消除闪烁现象
* 将所有东西画在虚拟图片上,一次性显示出来
*/
public void update(Graphics g) {
/**
* 画出虚拟画布
*/
if(OffScreenImage==null){
OffScreenImage=this.createImage(Game_WIDTH,Game_HEIGTH);
}
Graphics gOffScreenImage=OffScreenImage.getGraphics();
Color c=gOffScreenImage.getColor();
gOffScreenImage.setColor(Color.BLACK);
gOffScreenImage.fillRect(0, 0, Game_WIDTH , Game_HEIGTH);
gOffScreenImage.setColor(c);
/**
* 把虚拟画布的画笔传给paint()方法
* 并用真实画笔g把画布一次性显示出来
*/
paint(gOffScreenImage);
g.drawImage(OffScreenImage, 0, 0, null);
}
public static void main(String[] args) {
new TankWarClient().launchFrame();
}
/**
* 本方法显示游戏主窗口
*/
public void launchFrame(){
Random r=new Random();
images.add(Toolkit.getDefaultToolkit().getImage(Tank.class.getClassLoader().getResource("Images/tou.jpg") )) ;
/**
* 开始游戏时画出10辆敌军坦克
*/
direction []dir=direction.values();
for(int i=0; i<8; i++){
int rn=r.nextInt(dir.length);
EnemyTanks.add(new Tank(50+70*(i+2), 0 , this, false ,dir[rn]));
}
int w=100 ;
int h=80 ;
for(int i=0 ; i<7 ; i++){
walls.add(new Wall(w,h, 30, 30, this) ) ;
h+=30 ;
}
w=130 ;
h=90 ;
for(int i=0 ; i<7; i++){
walls.add(new Wall(w,h, 30, 30, this) ) ;
h+=30 ;
}
w=160 ;
h=120 ;
for(int i=0 ; i<2; i++){
walls.add(new Wall(w,h, 40, 30, this) ) ;
h+=30 ;
}
w=200 ;
h=90 ;
for(int i=0 ; i<7; i++){
walls.add(new Wall(w,h, 30, 30, this) ) ;
h+=30 ;
}
w=230 ;
h=180 ;
for(int i=0 ; i<2 ; i++){
walls.add(new Wall(w,h, 80, 30, this) ) ;
h+=30 ;
}
w=310 ;
h=100 ;
for(int i=0 ; i<7; i++){
walls.add(new Wall(w,h, 30, 30, this) ) ;
h+=30 ;
}
w=340 ;
h=130 ;
for(int i=0 ; i<5 ; i++){
walls.add(new Wall(w,h, 30, 30, this) ) ;
h+=30 ;
}
w=370 ;
h=160 ;
for(int i=0 ; i<2 ; i++){
walls.add(new Wall(w,h, 45, 30, this) ) ;
h+=30 ;
}
w=415 ;
h=160 ;
for(int i=0 ; i<2 ; i++){
walls.add(new Wall(w,h, 45 , 30, this) ) ;
h+=30 ;
}
w=460 ;
h=130 ;
for(int i=0 ; i<5 ; i++){
walls.add(new Wall(w,h, 30, 30, this) ) ;
h+=30 ;
}
w=490 ;
h=100 ;
for(int i=0 ; i<7 ; i++){
walls.add(new Wall(w,h, 30, 30 ,this) ) ;
h+=30 ;
}
w=520 ;
h=180 ;
for(int i=0 ; i<2 ; i++){
walls.add(new Wall(w,h, 80, 30, this) ) ;
h+=30 ;
}
w=600 ;
h=90 ;
for(int i=0 ; i<7 ; i++){
walls.add(new Wall(w,h, 30, 30, this) ) ;
h+=30 ;
}
w=630 ;
h=120 ;
for(int i=0 ; i<2 ; i++){
walls.add(new Wall(w,h, 40, 30, this) ) ;
h+=30 ;
}
w=670 ;
h=100 ;
for(int i=0 ; i<7 ; i++){
walls.add(new Wall(w,h, 30, 30, this) ) ;
h+=30 ;
}
w=700 ;
h=80 ;
for(int i=0 ; i<7 ; i++){
walls.add(new Wall(w,h, 30, 30, this) ) ;
h+=30 ;
}
//下层建筑
w=330 ;
h=546 ;
for(int i=0 ; i<4 ; i++){
walls.add(new Wall(w,h, 20, 30 ,this) ) ;
h+=27 ;
}
w=350 ;
h=577 ;
for(int i=0 ; i<3 ; i++){
walls.add(new Wall(w,h, 20, 30 ,this) ) ;
h+=25 ;
}
w=350 ;
h=546 ;
for(int i=0 ; i<6 ; i++){
walls.add(new Wall(w,h, 20, 30 ,this) ) ;
w+=20 ;
}
w=450 ;
h=576 ;
for(int i=0 ; i<3 ; i++){
walls.add(new Wall(w,h, 20, 30,this ) ) ;
h+=26 ;
}
w=470 ;
h=546 ;
for(int i=0 ; i<4 ; i++){
walls.add(new Wall(w,h, 20, 30,this) ) ;
h+=30 ;
}
w=310 ;
h=515 ;
for(int i=0 ; i<10 ; i++){
walls.add(new Wall(w,h, 20, 30, this) ) ;
w+=20 ;
}
w=360 ;
h=484 ;
for(int i=0 ; i<5 ; i++){
walls.add(new Wall(w,h, 20, 30 , this) ) ;
w+=20 ;
}
w=40 ;
h=330 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
w=90 ;
h=350 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
w=140 ;
h=370 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
w=190 ;
h=390 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
w=240 ;
h=410 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
w=560 ;
h=410 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
w=610 ;
h=390 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
w=660 ;
h=370 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
w=710 ;
h=350 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
w=760 ;
h=330 ;
for(int i=0 ; i<11 ; i++){
walls.add(new Wall(w,h, 20, 20, this) ) ;
h+=19 ;
}
//打不烂的墙
int w0=348 ;
int h0=400 ;
for(int i=0 ; i<6 ; i++){
nonWalls.add(new Wall(w0 ,h0 , 25, 25, this) ) ;
w0+=20 ;
}
/**
* 对游戏窗口的关闭监听处理
*/
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
/**
*设置游戏窗口不可改变
*设置窗口背景、大小、起始位置和标题
*/
this.setResizable(false);
this.setTitle("TankWar");
this.setBackground(Color.BLACK);
this.setSize(Game_WIDTH ,Game_HEIGTH);
setLocation(50,50);
this.addKeyListener(new KeyMonitor());
setVisible(true);
//启动线程
new Thread(new PaintThread()).start();
}
/**
* 调用线程设置刷新频率为50ms
* 并对画面以刷新频率为间隔进行重画
* @author liuqinglin
*
*/
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);
}
}
}
//tank
package com.liuqinlin.TankWar图片版;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
* 本类为制造坦克的类
* 并根据当前myTank的炮筒方向调用子弹进行打击
* @author liuqinglin
*
*/
public class Tank {
private int x, y;
//记录坦克原先的位置,为撞墙处理准备
private int oldx, oldy ;
/**
* 超级炮弹的起始数量设置
*/
public int superCounts=0 ;
public int multiCounts=0 ;
private int life=100 ;
//给敌军坦克改变方向前的移动距离
private int step=rn.nextInt(15)+4 ;
private boolean live=true ;
private boolean good;
/**
* 控制坦克速度和坦克大小
*/
private static Random rn=new Random();
/**
* 对按键方向的Boolean判断
*/
boolean BL=false,BU=false,BR=false,BD=false;
/**
* 新建一个方向的枚举类,控制9个方向
* @author liuqinglin
*
*/
//dir为坦克的起始方向
direction dir=direction.STOP;
//ptDir为炮筒的起始方向
direction ptDir=direction.U;
//ptd:记录坦克的方向
direction ptd;
Missile m ;
TankWarClient tc;
Tank t ;
private static Toolkit tk=Toolkit.getDefaultToolkit();
private static Map<String , Image> imgs=new HashMap<String , Image >();
static Image[] enemyTankImages=null ;
static{//静态区域里可以写代码
enemyTankImages=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", enemyTankImages[0]);
imgs.put("LU", enemyTankImages[1]);
imgs.put("U", enemyTankImages[2]);
imgs.put("RU", enemyTankImages[3]);
imgs.put("R", enemyTankImages[4]);
imgs.put("RD", enemyTankImages[5]);
imgs.put("D", enemyTankImages[6]);
imgs.put("LD", enemyTankImages[7]);
}
public static final int XSPEED=4 , YSPEED=4 ;
public static final int WIDTH=35 ;
public static final int HEIGHT=35 ;
public Tank(int x, int y, boolean good) {
this.x = x;
this.y = y;
this.good=good;
}
/**
* 判断敌我,画出坦克
* @param x 坦克方位x顶坐标
* @param y 坦克方位y顶坐标
* @param tc 主窗口的控制引用
* @param good 敌我识别
* @param dir 坦克的初始方向状态
*/
public Tank(int x, int y, TankWarClient tc, boolean good, direction dir) {
this(x, y,good );//调用上面那个构造函数
this.dir=dir ;
this.tc=tc;
/**
* 记录坦克的方位,为碰撞处理准备
*/
oldx=x;
oldy=y ;
}
/**
*
* @param g 画坦克和炮筒的画笔
*/
public void draw(Graphics g){
/**
* 如果坦克被击中 则不再重画
* 如为敌军坦克,还从敌军坦克容器中移除
*/
if(! live){
if(! good){
tc.EnemyTanks.remove(this);
return ;
}
return ;
}
//画出血条
if(good){
Color cs=g.getColor();
g.setColor(Color.red);
g.draw3DRect(x+1 , y-6 , 100/3 , 5, true);
g.fill3DRect(x+1 , y-6 , getLife()/3 ,5, true);
g.setColor(cs);
}
/**
* 获取坦克stop前的方向,为坦克stop时确定炮筒的方向
*/
ptd=ptDir ;
/**
* 根据炮筒方向画出炮筒
*/
switch(ptDir){
case L :
g.drawImage(imgs.get("L"),x ,y, null);
break;
case U :
g.drawImage(imgs.get("U"),x ,y, null);
break;
case R :
g.drawImage(imgs.get("R"),x ,y, null);
break;
case D :
g.drawImage(imgs.get("D"),x ,y, null);
break;
case STOP :
break;
}
move();
}
/**
* 坦克移动前先记录下方位
*/
public void move(){
oldx=x; oldy=y ;
switch(dir){
case L :
x-=XSPEED ;
break;
case U :
y-=YSPEED ;
break;
case R :
x+=XSPEED ;
break;
case D :
y+=YSPEED ;
break;
case STOP :
break;
}
/**
* 若坦克越界则置为相应边缘位置
*/
if(x<0)x=0;
if(y<20)y=20 ;
if(x+ WIDTH >=TankWarClient.Game_WIDTH) { x=TankWarClient.Game_WIDTH - WIDTH ;}
if(y +HEIGHT>=TankWarClient.Game_HEIGTH){ y=TankWarClient.Game_HEIGTH - HEIGHT ;}
/**
* 一次运动完后判断是否为敌军
* 若为敌军,则进行step判断,若step已经走完为0
* 则重新为step随机置一个值,重新赋予一个随机运动方向
*/
if(! good){
/**
* 不能对枚举类直接进行下标访问
* 对其建立数组装好9个方向
*/
direction []dirs=direction.values();
if(step==0){
step=rn.nextInt(30)+10 ;
/**
* r 为在9个方向的数组长度进行随机产生 0 到 8的下标
*/
int r=rn.nextInt(dirs.length);
/**
* 由随机产生的下标数生成坦克方向
* 并赋予炮筒方向
*/
dir=dirs[r];
ptDir=dir ;
}
/**
* 由随机数产生 39 时敌军坦克发射子弹
*解决了子弹发射频率过快的 问题
*/
if(rn.nextInt(40)>38){
this.fire();
}
step-- ;
}
}
/**
* 本方法控制碰撞发生时stay
* 回到原来的位置
*/
public void stay(){
x=oldx;
y=oldy;
}
/**
* 控制按键,产生方向
* @param e KeyEvent事件
*/
public void keypressed(KeyEvent e){
int key=e.getKeyCode();
switch(key){
case KeyEvent.VK_A :
BL=true; break;
case KeyEvent.VK_W:
BU=true; break;
case KeyEvent.VK_D :
BR=true; break;
case KeyEvent.VK_S :
BD=true; 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;
}
currentDirection();
}
/**
* 为解决按键fire子弹太密集的问题
* keyreleased后才发射子弹即fire
* @param e KeyEvent 事件
*/
public void keyreleased(KeyEvent e){
int key=e.getKeyCode();
switch(key){
case KeyEvent.VK_A :
BL=false; break;
case KeyEvent.VK_W:
BU=false; break;
case KeyEvent.VK_D :
BR=false; break;
case KeyEvent.VK_S :
BD=false; 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_SPACE :
fire(); break;
case KeyEvent.VK_F :
fires(); break ;
case KeyEvent.VK_F2 :
/**
* 若myTank死亡可按F2重新开始游戏
* 一切重置;myTank没死则不能重新开始
*/
if(! this.live){
live=true ;
this.setLife(100);
tc.multiCounts=5 ;
multiCounts=0 ;
break ;
}else break ;
}
currentDirection();
}
/**
* 各类子弹或者炮弹的发射的统一发射
* @return 返回子弹
*/
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/3 ;
m=new Missile(x, y, ptDir ,tc, good);
tc.Missiles.add(m);
return m ;
}
/**
* 散弹的发射控制最终也得调用fire()
*/
private void fires(){
/**
* 控制8个方向散弹的发射次数
*/
if(multiCounts<5){
multiCounts++ ;
tc.multiCounts-- ;
}else return ;
/**
* 通过数组获取8个方向的发射方向
* 进行for循环朝8个方向开火
*/
direction [] dirs=direction.values();
for(int i=0; i<dirs.length ; i++){
ptDir=dirs[i];
fire();
}
}
/**
* 由按键获得的4个方向的Boolean值更进一步的细分方向为8个方向
* 并简单的设置炮筒方向与坦克方向一致
*/
public void currentDirection(){
if(!BL&&!BU&&!BR&&!BD){
ptDir=ptd ;
dir=direction.STOP ;
}else if(BL&&!BU&&!BR&&!BD){
ptDir=direction.L ;
dir=direction.L ;
}else if(BL&&BU&&!BR&&!BD){
ptDir=direction.U ;
dir=direction.U ;
}else if(!BL&&BU&&!BR&&!BD){
ptDir=direction.U ;
dir=direction.U ;
}else if(!BL&&BU&&BR&&!BD){
ptDir=direction.U ;
dir=direction.U ;
}else if(!BL&&!BU&&BR&&!BD){
ptDir=direction.R ;
dir=direction.R ;
}else if(!BL&&!BU&&BR&&BD){
ptDir=direction.D ;
dir=direction.D ;
}else if(!BL&&!BU&&!BR&&BD){
ptDir=direction.D ;
dir=direction.D ;
}else if(BL&&!BU&&!BR&&BD){
ptDir=direction.D ;
dir=direction.D ;
}
}
public boolean eatBoold(Boold bd){
if(this.live&& bd.isLive() && this.getRect().intersects(bd.getRect())){
if(this.getLife()<=50){
this.setLife(this.getLife()+50);
}else this.setLife(100);
bd.setLive(false);
return true ;
}return false ;
}
public boolean isGood() {
return good;
}
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
public Rectangle getRect(){
return new Rectangle(x, y, WIDTH , HEIGHT);
}
public boolean isCollidesWithImage(Image image){
if(this.live&&this.getRect().intersects(370, 541 ,60, 60)){
stay();
return true ;
}
return false ;
}
public boolean isCollidesWithWall(java.util.List<Wall> walls){
for(int i=0 ; i<tc.walls.size(); i++){
Wall wall=tc.walls.get(i);
if(this.live&&this.getRect().intersects(wall.getRect())){
this.stay();
return true ;
}
}
return false ;
}
//碰撞打不烂的墙
public boolean isCollidesWithNonWall(java.util.List<Wall> nonWalls){
for(int i=0 ; i<nonWalls.size(); i++){
Wall nonWall=nonWalls.get(i);
if(this.live&&this.getRect().intersects(nonWall.getRect())){
this.stay();
return true ;
}
}
return false ;
}
/**
* 处理敌军之间的碰撞
* @param EnemyTanks 敌军一群坦克
* @return 撞上则返回 true ,否则false
*/
public boolean isCollidesWithTanks(java.util.List<Tank>EnemyTanks){
for(int i=0; i<EnemyTanks.size();i++){
t=EnemyTanks.get(i);
//判断不能是同一辆坦克
if(this !=t){
if(this.live&&t.isLive()&&this.getRect().intersects(t.getRect())){
this.stay();
t.stay();
return true ;
}
}
}
return false ;
}
/**
*
* @param t 单个坦克
* @return 撞上墙就返回 true ,否则false
*/
public boolean isCollidesWithTank(Tank t){
if(this.live&&t.isLive()&&this.getRect().intersects(t.getRect())){
this.stay();
t.stay();
return true ;
}
return false ;
}
/**
*
* @return 获取我军坦克生命值
*/
public int getLife() {
return life;
}
/**
*
* @param life 设置我军坦克生命值
*/
public void setLife(int life){
this.life=life ;
}
}
//Missile子弹
package com.liuqinlin.TankWar图片版;
//让坦克动起来
//解决坦克移动方向变化过快的问题。用了记录步数的方法
import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 本类为子弹类,对各种类型子弹进行统一绘制
* 并对碰撞进行处理
* @author liuqinglin
*
*/
public class Missile {
private int x, y;
private boolean live=true;
private boolean good;
private TankWarClient tc;
static direction dr;
direction ptDir;
/**
* 控制子弹速度
*/
public int XSPEED=10,YSPEED=10;
public static final int WIDTH=10;
public static final int HEIGHT=10;
private static Toolkit tk=Toolkit.getDefaultToolkit();
private static Map<String , Image> imgs=new HashMap<String , Image >();
static Image[] missileImages=null ;
static{//静态区域里可以写代码
missileImages=new Image[] {
tk.getImage(Missile.class.getClassLoader().getResource("images/missileL.gif") ) ,
tk.getImage(Missile.class.getClassLoader().getResource("images/missileLU.gif") ) ,
tk.getImage(Missile.class.getClassLoader().getResource("images/missileU.gif") ) ,
tk.getImage(Missile.class.getClassLoader().getResource("images/missileRU.gif") ) ,
tk.getImage(Missile.class.getClassLoader().getResource("images/missileR.gif") ) ,
tk.getImage(Missile.class.getClassLoader().getResource("images/missileRD.gif") ) ,
tk.getImage(Missile.class.getClassLoader().getResource("images/missileD.gif") ) ,
tk.getImage(Missile.class.getClassLoader().getResource("images/missileLD.gif") )
} ;
imgs.put("L", missileImages[0]);
imgs.put("LU", missileImages[1]);
imgs.put("U", missileImages[2]);
imgs.put("RU", missileImages[3]);
imgs.put("R", missileImages[4]);
imgs.put("RD", missileImages[5]);
imgs.put("D", missileImages[6]);
imgs.put("LD", missileImages[7]);
}
/**
*
* @param x
* @param y子弹绘制的位置
* @param WIDTH
* @param HEIGTH
* @param ptDir
*/
public Missile(int x, int y,direction ptDir) {
this.x = x ;
this.y = y ;
this.ptDir=ptDir;
}
/**
* 根据接收到的子弹信息绘制子弹
* @param x 子弹绘制的位置
* @param y 子弹绘制的位置
* @param ptDir myTank的炮筒方向
* @param tc 主窗口的控制引用
* @param good 敌我识别,以判断画出敌军坦克还是我军坦克
*/
public Missile(int x, int y, direction ptDir,TankWarClient tc,boolean good){
this(x, y, ptDir);
this.tc=tc;
this.good=good ;
}
public void draw(Graphics g){
/**
* 如果子弹死亡就从容器中移除
* 就不在重画
*/
if(! live){
tc.Missiles.remove(this);
return ;
}
/**
* 随传递过来的炮筒方向画出炮弹
*/
switch(ptDir){
case L :
g.drawImage(imgs.get("L"), x, y, null);
break ;
case U :
g.drawImage(imgs.get("U"),x, y, null);
break ;
case R :
g.drawImage(imgs.get("R"),x, y, null);
break ;
case D :
g.drawImage(imgs.get("D"),x, y, null);
break ;
}
move();
}
/**
* 根据炮筒方向使相应x 、y方位变化以实现
* 子弹的运动
*/
private void move() {
switch(ptDir){
case L:
x-=XSPEED;
break;
case U:
y-=YSPEED;
break;
case R:
x+=XSPEED;
break;
case D:
y+=YSPEED;
break;
}
/**
* 如果子弹出界就判定死亡
*/
if(x<0 || y<0 || x>TankWarClient.Game_WIDTH || y>TankWarClient.Game_HEIGTH ){
live=false;
}
}
/**
* 由子弹的大小方框进行简单的子弹碰撞处理
* @return 子弹的大小方框
*/
public Rectangle getRect(){
return new Rectangle(x, y, missileImages[4].getWidth(null), missileImages[4].getHeight(null));
}
public boolean isHitImage(List<Image> images){
for(int i=0; i<images.size(); i++){
Image image=images.get(i);
if(this.live&&this.getRect().intersects(371, 577 , 80, 80)){
this.live=false ;
tc.images.remove(image);
return true ;
}
}
return false ;
}
/**
* 对子弹撞墙处理
* @param wall 被子弹撞的墙
* @return 子弹撞上墙则返回true,否则false
*/
public boolean isHitWall(List <Wall> walls){
for(int i=0; i<tc.walls.size(); i++){
Wall wall=tc.walls.get(i);
if(this.live&& wall.isLive()&& this.getRect().intersects(wall.getRect())){
this.live=false ;
wall.setLive(false);
Explode e=new Explode(x, y, tc);
tc.Explodes.add(e);
return true ;
}
}
return false ;
}
//碰撞打不烂的墙
public boolean isHitNonWalls(List <Wall> nonWalls){
for(int i=0; i<nonWalls.size(); i++){
Wall nonWall=nonWalls.get(i);
if(this.live&&this.getRect().intersects(nonWall.getRect())){
this.live=false ;
Explode e=new Explode(x, y, tc);
tc.Explodes.add(e);
return true ;
}
}
return false ;
}
/**
*
* @param t 被子弹打击的坦克
* @return 打中则返回true,否则false
*/
public boolean isHitTank(Tank t){
/**
* 首先确定子弹活着并且要打击的坦克也活着
* 如果子弹小方框和坦克的的方框是否相交
* 若不是同一方的坦克,并且方框相交则子弹和
* 坦克都死亡
*/
if(this.live&&this.getRect().intersects(t.getRect())&&t.isLive()&&this.good !=t.isGood()){
/**
* 如果被打中的坦克为我方坦克则进行血条管理
* 被打中一次减少20滴血,总共100滴
* 若为敌军坦克则直接死亡
*/
if(t.isGood()){
t.setLife(t.getLife()-20) ;
if(t.getLife()<=0) { t.setLive(false); }
}else { t.setLive(false); }
this.live=false ;
/**
* 根据子弹的方位画出爆炸并添加入爆炸容器中
*/
Explode e=new Explode(x, y, tc);
tc.Explodes.add(e);
return true ;
}else
return false ;
}
/**
* myTank要打击每一辆敌军坦克,需要加入装有一批敌军坦克的容器为参数
* @param EnemyTanks 给我军坦克打击的一群敌军坦克
* @return 打中敌军坦克则返回true,否则false
*/
public boolean isHitTanks(List<Tank> EnemyTanks){
for(int i=0 ; i<tc.EnemyTanks.size(); i++){//每次打击循环一遍,查看哪个被打中了
if(isHitTank(tc.EnemyTanks.get(i))){
return true ;
}
}
return false ;
}
}
//explode爆炸
package com.liuqinlin.TankWar图片版;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
/**
* 本类为游戏添加爆炸效果
* @author liuqinglin
*
*/
public class Explode {
int x, y;
private boolean live=true ;
private static boolean init=false ;
int step=0;
private TankWarClient tc ;
//获取当前平台系统的工具包以调用当前系统的东西
private static Toolkit tk=Toolkit.getDefaultToolkit();
//若定义的变量不是静态的,每new一个Explode就重新load一个变量
private static Image[] imgs={
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/3.gif") ) ,
tk.getImage(Explode.class.getClassLoader().getResource("images/5.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") ) ,
} ;
/**
* 由Missile类传递来的击中敌军坦克的子弹方位画出爆炸
* @param x 爆炸的x顶坐标
* @param y 爆炸的y顶坐标
* @param tc 主窗口传递过来的控制引用
*/
public Explode(int x, int y, TankWarClient tc){
this.x=x;
this.y=y;
this.tc=tc;
}
public void draw(Graphics g){
//防止第一发打中没爆炸效果出现
//因为系统可能采用了异步IO方法
//现在采用虚代理方法即先把图片读到内存
//在看不见的方位画出来
if(! init){
for (int j = 0; j < imgs.length; j++) {
g.drawImage(imgs[j], -100 , -100 , null);
}
}
if(! live){
tc.Explodes.remove(this);
return ;
}
if(step==imgs.length){
live=false ;
step=0 ;
}
g.drawImage(imgs[step], x, y, null);
step++ ;
}
}
//wall墙
package com.liuqinlin.TankWar图片版;
import java.awt.*;
/**
* 本类对墙的控制和画出
* @author liuqinglin
*
*/
public class Wall {
private int x , y,w, h ;
private boolean live=true ;
TankWarClient tc ;
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
public Wall(int x, int y, int w, int h, TankWarClient tc) {
this.x = x;
this.y = y;
this.w=w;
this.h=h ;
this.tc=tc ;
}
/**
* 按主窗口传递的方位大小画出墙
* @param g 画笔
*/
public void draw(Graphics g){
if(! live ){
tc.walls.remove(this);
return ;
}
//设置打不烂和打得烂的墙的颜色
Color c=g.getColor();
if(x>=348 && x<=473 &&y >=400&&y<=425){
Color co=new Color(225, 216 ,226);
g.setColor(co);
}else {
Color cs=new Color(200, 100 ,50);
g.setColor(cs);
}
g.draw3DRect(x, y, w, h, true);
g.fill3DRect(x, y, w, h, true);
g.setColor(c);
}
/**
* 获取墙的方框以便进行碰撞处理
* @return 当前墙壁的外形(墙外头的正方形)
*/
public Rectangle getRect() {
return new Rectangle(x, y, w,h);
}
}
//direction方向
package com.liuqinlin.TankWar图片版;
public enum direction {
L, U , R, D, STOP
}
//boold加血的血块
package com.liuqinlin.TankWar图片版;
import java.awt.*;
import java.util.*;
/**
* 本类为游戏添加给我军坦克加血的血块
* @author liuqinglin
*
*/
public class Boold {
private int x, y ;
private int w, h ;
private boolean live=true ;
int step=0 ;
Random rd=new Random();
/**
* 根据pos数组给血块重画的方位定位
*/
int [][]pos={
{200, 200}, {300, 300}, {400, 400}, {500, 500}, {600, 500}, {450, 300}, {300, 150},
{200, 300}, {400, 250}, {150, 100}, {88, 200}, {150, 300},{80, 80}, {400, 100}, {400, 500}
};
public Boold() {
this.x = 200 ;
this.y = 200 ;
this.w = 15 ;
this.h = 15 ;
}
/**
* 画出血块,被吃后消失
* @param g 进行血块的绘制的画笔
*/
public void draw(Graphics g ){
if(! live)return ;
Color c=g.getColor();
g.setColor(Color.MAGENTA);
g.fill3DRect(x, y, w, h, true);
move();
}
/**
* 按血块方位对血块进行自动绘制
* 并利用随机数控制血块的运动频率
*/
public void move(){
int bu=rd.nextInt(88);
if(bu>86){
step++ ;
if(step<pos.length){
x=pos[step][0];
y=pos[step][1];
}else step=0 ;
}
}
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
public Rectangle getRect() {
return new Rectangle(x, y, w, h);
}
}