基于java的坦克大战实例
原创性声明
此博文的出处 为 http://blog.csdn.net/zhujunxxxxx/article/details/40460931如果进行转载请注明出处。本文作者原创,邮箱[email protected],如有问题请联系作者
前言
原理
坦克类
import java.awt.*; import java.awt.event.*; import java.util.*; public class Tank { public static final int XSPEED = 5; public static final int YSPEED = 5; public static final int WIDTH = 30; public static final int HEIGHT = 30; TankClient tc; private int x, y;//坦克的坐标,即位置 private int oldX, oldY;//用来保存上一步的坐标,撞墙的时候调整方向用的 private boolean bL=false, bU=false, bR=false, bD = false;//方向的标志变量 enum Direction {L, LU, U, RU, R, RD, D, LD, STOP};//方向的枚举 private Direction dir = Direction.STOP;//我方坦克,初始方向 private Direction ptDir = Direction.D;//敌方坦克初始方向,向下 private int step = r.nextInt(12) + 3; private boolean isSuper=false; public boolean isSuper() { return isSuper; } public void setSuper(boolean isSuper) { this.isSuper = isSuper; } private static Random r = new Random();//随机数产生器 private boolean good;//区分好坏的变量 private boolean boss; public boolean isBoss() { return boss; } public boolean isGood() { return good; } public void setGood(boolean good) { this.good = good; } private BloodBar bb=new BloodBar();//血条 //坦克生命值的变量 private int life=100; public int getLife() { return life; } public void setLife(int life) { this.life = life; } //坦克生死的变量 private boolean live=true; public boolean isLive() { return live; } public void setLive(boolean live) { this.live = live; } //坦克的构造方法 public Tank(int x, int y,boolean good) { this.x = x; this.y = y; this.oldX = x; this.oldY = y; this.good=good; } public Tank(int x, int y,boolean good,Direction dir, TankClient tc) { this(x, y,good); this.dir=dir; this.tc = tc; } public Tank(int x, int y,boolean good,boolean boss, Direction dir, TankClient tc) { this(x, y,good); this.dir=dir; this.boss=boss; this.tc = tc; } //画坦克的方法 public void draw(Graphics g) { if(!live) return;//Tank死了就不在重画了 Color c = g.getColor(); if(good)//通过好坏设置颜色 { g.setColor(Color.CYAN); } else if(boss) { g.setColor(Color.RED); } else { g.setColor(Color.BLUE); } g.fillOval(x, y, WIDTH, HEIGHT); g.setColor(c); if(good) bb.draw(g);//我方坦克有血条 if(boss) bb.draw(g);//boss有血条 switch(ptDir) {//通过方位判断,画炮筒位置 case L: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y + Tank.HEIGHT/2); break; 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; } move();//重画时,进行移动 } //坦克的移动方法,在重画的时候,通过方向定位来进行移动 void move() { this.oldX = x; this.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(this.dir != Direction.STOP) {//炮筒位置的定位,和行动方向一致 this.ptDir = this.dir; } //判断坦克是否出界,遇到边界则停止 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.HEIGHT > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT - Tank.HEIGHT; //坏蛋坦克的随机移动,以及发子弹的时间 if(!good&&!boss) { 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(); } //boss坦克的攻击方法 if(!good&&boss) { 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) > 20)this.fire(); } } //按下键时进行设置键位标志,用于方向定位判断 public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); switch(key) { case KeyEvent.VK_CAPS_LOCK: this.setSuper(!this.isSuper()); case KeyEvent.VK_F2 : if(!this.live) { this.live = true; this.life = 100; } case KeyEvent.VK_CONTROL: fire(); 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();//每次按键后就判断方向 } //Tank的方向定位,通过按键后设置的标志进行判断 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; } //方向键抬起来时的,恢复键位标志,也进行方向判断 public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); switch(key) { 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(); } //发出一发子弹的方法,向missiles里面添加子弹 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; if(good&&this.isSuper())//判断是不是超级炮弹 { m = new Missile(x, y,good, ptDir,this.tc,true); } else { m = new Missile(x, y,good, ptDir,this.tc); } tc.missiles.add(m); return m; } //SuperFire向每个方向发子弹的方法 public Missile fire(Direction Dir) { 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, Dir,this.tc); tc.missiles.add(m); return m; } private void superFire() { Direction[] dirs = Direction.values(); for(int i=0;i<8;i++) { //tc.missiles.add(fire(dirs[i])); fire(dirs[i]); } } //判断相撞的方法所需的 public Rectangle getRect() { return new Rectangle(x, y, WIDTH, HEIGHT); } //与坦克和墙相撞时停下来的方法 private void stay() { x = oldX; y = oldY; } //判断坦克是否与墙相撞的方法 public boolean collidesWithWall(Wall w) { if(this.live && this.getRect().intersects(w.getRect())) { this.stay(); return true; } return false; } //判断坦克是否与坦克相撞的方法 public boolean collidesWithTanks(java.util.List<Tank> tanks) { for(int i=0; i<tanks.size(); i++) { Tank t = tanks.get(i); if(this != t) { if(this.live && t.isLive() && this.getRect().intersects(t.getRect())) { this.stay(); t.stay(); return true; } } } return false; } //血条的内部类 private class BloodBar { public void draw(Graphics g) { Color c = g.getColor(); g.setColor(Color.orange); g.drawRect(x, y-10, WIDTH, 10); int w = WIDTH * life/100 ; g.fillRect(x, y-10, w, 10); g.setColor(c); } } //吃血块的方法 public boolean eat(Blood b) { if(this.live && b.isLive() && this.getRect().intersects(b.getRect())) { this.life = 100; b.setLive(false); return true; } return false; } }
子弹类
import java.awt.*; import java.util.List; public class Missile { public static final int XSPEED = 10;//子弹速度的变量 public static final int YSPEED = 10; public static int WIDTH = 10;//子弹大小 public static int HEIGHT = 10; int x, y; private TankClient tc; Tank.Direction dir;//方向变量 private boolean isSuper; private boolean live = true;//子弹的生死变量 public boolean isLive() { return live; } private boolean good;//坦克的好坏之分变量 public boolean isGood() { return good; } //Missile的两个构造方法 public Missile(int x, int y, Tank.Direction dir) { this.x = x; this.y = y; this.dir = dir; } public Missile(int x, int y,boolean good, Tank.Direction dir, TankClient tc) { this(x, y, dir); this.tc = tc; this.good=good; } public Missile(int x, int y,boolean good, Tank.Direction dir, TankClient tc,boolean isSuper) { this(x, y, dir); this.tc = tc; this.isSuper=isSuper; this.good=good; } //画子弹的方法 public void draw(Graphics g) { if(!live) { tc.missiles.remove(this); return; } Color c = g.getColor(); if(good&&isSuper)//是超级炮弹就变大 { g.setColor(Color.YELLOW); g.fillOval(x-5, y-5, 20, 20); } else if(good&&!isSuper) { g.setColor(Color.YELLOW); g.fillOval(x, y, WIDTH, HEIGHT); } else { g.setColor(Color.RED); 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 -= 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; tc.missiles.remove(this); } } public Rectangle getRect() { return new Rectangle(x, y, WIDTH, HEIGHT); } //子弹与子弹相撞的方法,且子弹分好坏 public boolean hitMissile(Missile m) { if(this.live && this.getRect().intersects(m.getRect()) && m.isLive() && this.good !=m.isGood() ) { this.live=false; m.live=false; return true; } return false; } public boolean hitMissiles(List<Missile> missiles) { for(int i=0; i<missiles.size(); i++) { if(hitMissile(missiles.get(i))) {//调用了hitMissile方法 missiles.remove(missiles.get(i)); return true; } } return false; } public boolean hitTank(Tank t) { if(this.live && this.getRect().intersects(t.getRect()) && t.isLive() && this.good !=t.isGood() ) { if(t.isGood())//自己被击中减血 { t.setLife(t.getLife()-20); if(t.getLife()<=0) t.setLive(false); } else if(t.isBoss())//BOSS被击中 { if(this.isSuper)//被超级炮弹击中 { t.setLife(t.getLife()-33); if(t.getLife()<=0) t.setLive(false); } else { t.setLife(t.getLife()-5); if(t.getLife()<=0) t.setLive(false); } } else//坏人直接死 t.setLive(false); //t.setLive(false); this.live = false; Explode e = new Explode(x, y, tc); tc.explodes.add(e); return true; } return false; } //子弹与坦克相撞,且子弹分好坏(打敌人坦克的方法) public boolean hitTanks(List<Tank> tanks) { for(int i=0; i<tanks.size(); i++) { if(hitTank(tanks.get(i))) {//调用了hitTank方法 tanks.remove(tanks.get(i)); return true; } } return false; } //子弹与墙相撞的方法 public boolean hitWall(Wall w) { if(this.live && this.getRect().intersects(w.getRect())) { this.live = false; return true; } return false; } }
主程序类
import java.awt.*; import java.awt.event.*; import java.util.List; import java.util.ArrayList; import org.omg.CORBA.PUBLIC_MEMBER; public class TankClient extends Frame{ public static int GAME_WIDTH = 800; public static int GAME_HEIGHT = 600; Tank myTank = new Tank(200, 300,true,Tank.Direction.STOP, this); Tank BossTank = new Tank(60, 50,false,true,Tank.Direction.D,this); List<Missile> missiles=new ArrayList<Missile>();//装子弹的容器 List<Explode> explodes = new ArrayList<Explode>();//装爆炸的容器 List<Tank> tanks = new ArrayList<Tank>();//装敌方坦克的容器 Blood b = new Blood();//实例化一个血块 //实例化两个墙 Wall w1=new Wall(300, 200, 20,150, this); Wall w2=new Wall(200, 100, 20,150, this); //双缓冲技术,消除频闪 Image offScreenImage = null; 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.gray); gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); gOffScreen.setColor(c); paint(gOffScreen); g.drawImage(offScreenImage, 0, 0, null); } public void paint(Graphics g)//会自动调用这个方法 { g.drawString("tanks count:" + tanks.size(), 10, 35); g.drawString("explodes count:" + explodes.size(), 10, 50); g.drawString("missiles count:" + missiles.size(), 10, 65); g.drawString("Tank life:" + myTank.getLife(), 10, 80); if(tanks.size() <= 0) { for(int i=0; i<5; i++) { tanks.add(new Tank(50 + 40*(i+1), 50, false, Tank.Direction.D, this)); } } //把容器里面的子弹都画出来 for(int i=0;i<missiles.size();i++) { Missile m=missiles.get(i); m.hitTanks(tanks);//添加子弹打坦克的方法 m.hitTank(myTank); m.hitTank(BossTank); m.hitWall(w1); m.hitWall(w2); m.hitMissiles(missiles);//调用子弹撞子弹方法 m.draw(g); } //把容器里面的爆炸全部画出来 for(int i=0; i<explodes.size(); i++) { Explode e = explodes.get(i); e.draw(g); //e.ExplodehitTanks(tanks); //e.ExplodehitTank(BossTank); } //把容器里面的坦克全部画出来 for(int i=0; i<tanks.size(); i++) { Tank t = tanks.get(i); t.collidesWithWall(w1); t.collidesWithWall(w2); t.collidesWithTanks(tanks); t.draw(g); } b.draw(g);//血块画出来 BossTank.draw(g); BossTank.collidesWithWall(w1); BossTank.collidesWithWall(w2); BossTank.collidesWithTanks(tanks); //我方坦克画出来并添加方法 myTank.draw(g); myTank.eat(b); myTank.collidesWithWall(w1); myTank.collidesWithWall(w2); //画出墙来 w1.draw(g); w2.draw(g); } //初始化游戏窗口的方法 public void lauchFrame(){ //初始化坦克,添加进容器 for(int i=0;i<10;i++) { tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this)); } this.setLocation(300, 100); this.setSize(GAME_WIDTH,GAME_HEIGHT); this.setTitle("zz TankWar"); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); this.setBackground(Color.GREEN); this.setResizable(false); this.addKeyListener(new KeyMonitor()); this.setVisible(true); new Thread(new PaintThread()).start(); } 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); } } public static void main(String[] args) { TankClient t=new TankClient(); t.lauchFrame(); } }
总结
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。