首页 > 编程 > Java > 正文

java制作简单的坦克大战

2019-11-26 15:14:23
字体:
来源:转载
供稿:网友

详情请参照注释,这里就不多废话了,实现一下儿时的经典而已。

Blood.java

package com.hkm.TankWar;import java.awt.*;/** * 血块类,我方坦克吃了可回血; * @author Hekangmin * */public class Blood {  private int x,y,w,h;//血块的位置和宽度高度;     private TankWarClient tc;     private int step=0;//纪录血块移动的步数;     private boolean live=true;  public boolean isLive() {    return live;  }   public void setLive(boolean live) {    this.live = live;  }    /**     * 纪录血块的位置;     */  private int[][] pos={{400,300},{400,320},{420,320},{440,300},{440,330},{480,400},{520,400},{540,400}};          public Blood()  {    x=pos[0][0];    y=pos[0][1];    w=h=18;  }     public void draw(Graphics g)  {    if(!live) return;         Color c=g.getColor();    g.setColor(Color.CYAN);    g.fillOval(x, y, w, h);    g.setColor(c);         move();  }  /**   * 移动血块   */  public void move()  {    step++;    if(step>=pos.length) step=0;    else{    x=pos[step][0];    y=pos[step][1];    }  }        public Rectangle getRect()  {    return new Rectangle(x,y,w,h);  }      }

Explode.java

package com.hkm.TankWar;import java.awt.*;/** * 爆炸类 * @author Hekangmin * */public class Explode {  private int x,y;//爆炸发生的位置     private boolean Live=true;     int dia[]={4,8,12,16,32,40,20,14,4};//用园模拟,代表圆的直径;     int step=0;//区别移到第几个直径     private TankWarClient tc;//持有引用     public Explode(int x,int y,TankWarClient tc)  {    this.x=x;    this.y=y;    this.tc=tc;  }  public void draw(Graphics g)  {    if(!Live)    {      tc.explodes.remove(this);      return;    }    if(step==dia.length)//如果到了最后一个直径爆炸死亡;    {      Live=false;      step=0;      return;    }    Color c=g.getColor();    g.setColor(Color.YELLOW);    g.fillOval(x, y, dia[step], dia[step]);    g.setColor(c);    step++;  }   }

Missile.java

package com.hkm.TankWar;import java.awt.*;import java.awt.Event.*;import java.awt.event.KeyEvent;import java.util.List;/** * 子弹类 * @author Hekangmin * */ public class Missile {    private int x,y;//子弹的位置    private Tank.Direction dir;//坦克方向         private static final int XSPEED=10;//坦克x方向的移动速度,    private static final int YSPEED=10;//坦克y方向的移动速度,         public static final int WIDTH=10;    public static final int HEIGHT=10;         private boolean Live=true;//判断子弹是否活着         private boolean good;//区分敌军子弹和我军子弹         private TankWarClient tc;       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,TankWarClient tc)  {    this(x,y,dir);    this.good=good;//将坦克好坏的属性与子弹还坏属性设为相同;    this.tc=tc;  }     /**   * 画出子弹   * @param g为画笔   */  public void draw(Graphics g)  {    if(!Live)      {      tc.missiles.remove(this);      return;      }    Color c=g.getColor();    if(good)    {      g.setColor(Color.BLUE);    }    else g.setColor(Color.ORANGE);    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;    }         if(x<0||y<0||x>TankWarClient.GAME_WIDTH||y>TankWarClient.GAME_HEIGHT)//子弹越界则让其死亡;    {      Live=false;    }  }        public boolean isLive()  {    return Live;  }   public Rectangle getRect()//获取子弹的矩形区域;  {    return new Rectangle(this.x,this.y,this.WIDTH,this.HEIGHT);  }     /**   * 判断子弹与坦克碰撞;   * @param t为坦克   * @return返回true则表示发生碰撞,否则没有碰撞;   */  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()-10);        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;           }    return false;  }  /**   * 判断子弹与敌军坦克相撞;   * @param tanks敌军坦克   * @returntrue表示相撞,false没有相撞;   */  public boolean hitTanks(List<Tank> tanks)  {    for(int i=0;i<tanks.size();i++)    {      if(hitTank(tc.tanks.get(i)))      {        return true;      }    }         return false;  }     /**   * 判断子弹是否撞墙   * @param w墙   * @returntrue,撞上,false,未撞上;   */  public boolean hitsWall(Wall w)  {    if(this.Live&&this.getRect().intersects(w.getRect()))    {      Live=false;      return true;    }    return false;  }      }

Tank.java

package com.hkm.TankWar;import java.awt.*;import java.awt.event.KeyEvent;import java.util.*;/** * 坦克类 * @author Hekangmin * */public class Tank {  public static final int XSPEED=5;//坦克x方向速度  public static final int YSPEED=5;     public static final int WIDTH=30;  public static final int HEIGHT=30;     private BloodBar bb=new BloodBar();//血条     private int life=100;     public int getLife() {    return life;  }   public void setLife(int life) {    this.life = life;  }    private static Random r=new Random();     private static int step=r.nextInt(12)+3;//定义一个数表示敌军坦克随机东的步数;     private boolean bL=false,bU=false,bR=false,bD=false;     enum Direction{L,LU,U,RU,R,RD,D,LD,STOP};//利用枚举类型定义坦克方向;  private int x,y;     private int oldX,oldY;//纪录上一步坦克的位置;     private boolean live=true;//判断是否活着     public boolean isLive() {    return live;  }   public void setLive(boolean live) {    this.live = live;  }    private boolean good;//坦克是好是坏     public boolean isGood() {    return good;  }    private Direction ptDir=Direction.D;//新增炮筒的方向;     TankWarClient tc;//为了持有对方的引用以可以方便访问其成员变量;     Direction dir=Direction.STOP;//一开始将坦克方向设为stop;           public Tank(int x,int y,boolean good,Direction dir,TankWarClient tc)  {    this.x=x;    this.y=y;    this.oldX=x;    this.oldY=y;    this.good=good;    this.dir=dir;    this.tc=tc;//持有对方的引用;  }        public void draw(Graphics g)  {    if(!live)//如果死亡则不再draw;    {        if(!good)      {        tc.tanks.remove(this);        if(tc.tanks.size()<5)//少于5辆坦克时添加坦克;        {          for(int i=0;i<10;i++)          {            int posX=r.nextInt(800);            int posY=r.nextInt(600);            tc.tanks.add(new Tank(posX,posY,false,Direction.D,tc));//使得坦克出现的位置随机          }        }      }             return;    }         Color c=g.getColor();    if(good)     {      g.setColor(Color.RED);      bb.draw(g);    }    else g.setColor(Color.BLACK);    g.fillOval(x, y, WIDTH, HEIGHT);    g.setColor(c);         switch(ptDir)//画出炮筒的方向;    {    case L:       g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x-10, y+Tank.HEIGHT/2);//画出炮筒,画一条直线代替;      break;    case LU:       g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x-7, y-7);      break;    case U:       g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y-10);      break;    case RU:       g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH+7, y-7);      break;    case R:       g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH+10, y+Tank.HEIGHT/2);      break;    case RD:       g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH+7, y+Tank.HEIGHT+7);      break;    case D:       g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y+Tank.HEIGHT+10);      break;    case LD:       g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x-7, y+HEIGHT+7);      break;    }    move();  }        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(this.dir!=Direction.STOP)      this.ptDir=this.dir;         /**     * 防止坦克越界;     */    if(x<0) x=0;    if(y<25) y=25;    if(x+Tank.WIDTH>TankWarClient.GAME_WIDTH) x=TankWarClient.GAME_WIDTH-30;    if(y+Tank.HEIGHT>TankWarClient.GAME_HEIGHT) y=TankWarClient.GAME_HEIGHT-30;         if(!good)    {      Direction[] dirs=Direction.values();//将枚举类型转化成数组;             if(step==0)      {        step=r.nextInt(12)+3;        int rn=r.nextInt(dirs.length);//产生length以内随机的整数;        dir=dirs[rn];      }      step--;      if(r.nextInt(40)>20) 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_RIGHT:      bR=true;      break;    case KeyEvent.VK_UP:      bU=true;       break;    case KeyEvent.VK_DOWN:      bD=true;      break;    }    locationDir();  }        public void keyReleased(KeyEvent e) {    int key=e.getKeyCode();    switch(key)    {    case KeyEvent.VK_CONTROL:      fire();      break;    case KeyEvent.VK_LEFT:      bL=false;      break;    case KeyEvent.VK_RIGHT:      bR=false;      break;    case KeyEvent.VK_UP:      bU=false;       break;    case KeyEvent.VK_DOWN:      bD=false;      break;    case KeyEvent.VK_A:      superFire();      break;    case KeyEvent.VK_F2:      reBorn();      break;    }    locationDir();  }     /**   * 发射子弹   * @return返回子弹类型   */  public Missile fire() {    if(!live)      return null;    int mx=this.x+Tank.WIDTH/2-Missile.WIDTH/2;//计算子弹发射的位置;    int my=this.y+Tank.HEIGHT/2-Missile.HEIGHT/2;    Missile m=new Missile(mx,my,good,ptDir,this.tc);////根据炮筒方向发射子弹    tc.missiles.add(m);    return m;  }        public Missile fire(Direction dir)  {    if(!live)      return null;    int mx=this.x+Tank.WIDTH/2-Missile.WIDTH/2;    int my=this.y+Tank.HEIGHT/2-Missile.HEIGHT/2;    Missile m=new Missile(mx,my,good,dir,this.tc);//根据坦克的方向发射子弹;    tc.missiles.add(m);    return m;  }     public void superFire()  {    Direction[] dirs=Direction.values();    for(int i=0;i<8;i++)    {      fire(dirs[i]);    }  }        public void locationDir()  {    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 Rectangle getRect()//获取tank的矩形区域  {    return new Rectangle(this.x,this.y,this.WIDTH,this.HEIGHT);  }     /**   * 坦克撞墙   * @param w墙   * @returntrue撞上,false未撞上;   */  public boolean colliedsWithWall(Wall w)  {    if(this.live&&this.getRect().intersects(w.getRect()))    {      this.stay();      return true;    }    return false;  }     /**   * 处理坦克与坦克相撞,防止其互相穿越;   * @param tanks敌军坦克;   * @return true撞上,false未撞上;   */  public boolean colliedsWithTanks(java.util.List<Tank> tanks)  {    for(int i=0;i<tanks.size();i++)    {      Tank t=tanks.get(i);      if(this!=t)      {        if(this.live&&this.isLive()&&this.getRect().intersects(t.getRect()))        {          this.stay();//返回上一步的位置;          t.stay();////返回上一步的位置          return true;        }               }      }    return false;  }      private void stay()  {    x=oldX;    y=oldY;  }     /**   * 为Tank的内部类;血条,显示在我方坦克的头顶上;   * @author Hekangmin   *   */  private class BloodBar  {    public void draw(Graphics g)    {      Color c=g.getColor();      g.setColor(Color.RED);      g.drawRect(x,y-10,WIDTH,10);      int w=WIDTH*life/100;      g.fillRect(x,y-10,w,10);    }  }     /**   * 吃到血块加血;   * @param b血块   * @returntrue吃到,false未吃到;   */  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;  }     /**   * 我军坦克死后复活;   */  public void reBorn()  {    if(this.isGood()&&!this.isLive())    {      this.setLive(true);      this.setLife(100);    }  }}

TankWarClient.java

package com.hkm.TankWar;import java.awt.*;import java.awt.event.*;import java.util.List;import java.util.ArrayList; /** * 这个是游戏的运行窗口; * @author Hekangmin * */public class TankWarClient extends Frame{/** * 游戏窗口的宽度; */  public static final int GAME_WIDTH=800;     /**   * 游戏窗口的高度;   */  public static final int GAME_HEIGHT=600;     Tank MyTank=new Tank(700,400,true,Tank.Direction.STOP,this);  List<Tank> tanks=new ArrayList<Tank>();  List<Explode> explodes=new ArrayList<Explode>();  List<Missile> missiles=new ArrayList<Missile>();  Wall w1=new Wall(300,200,20,200,this);  Wall w2=new Wall(600,300,30,150,this);  Blood b=new Blood();     /**   * 画一张虚拟图片;   */  Image OffScreenImage=null;     public TankWarClient(String name)//设置文字  {    super(name);  }     /**   * 运行窗口;   */     public void launchFrame()  {    for(int i=0;i<10;i++)//添加十辆敌军坦克    {      tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this));    }         this.setBounds(200,100,GAME_WIDTH,GAME_HEIGHT);    this.setBackground(Color.GREEN);    this.addWindowListener(new WindowAdapter()//匿名类    {      public void windowClosing(WindowEvent e)      {        System.exit(0);      }    });    this.addKeyListener(new KeyMonitor());//加入键盘监听器;    this.setResizable(false);//不可改变窗口的大小;         this.setVisible(true);         new Thread(new PaintThread()).start();//新建一个线程;  }     public void paint(Graphics g)  {    g.drawString("Missile count: "+missiles.size(), 10, 50);//显示字符串;    g.drawString("Explodes count: "+explodes.size(),10,70);    g.drawString("tanks count: "+tanks.size(),10,90);    g.drawString("Mytank life: "+MyTank.getLife(),10,110);    /**     * 画出墙;     */    w1.draw(g);    w2.draw(g);         /**     * 检测子弹与各类的事情;     */    for(int i=0;i<missiles.size();i++)    {      Missile m=missiles.get(i);      m.hitsWall(w1);      m.hitsWall(w2);      m.hitTanks(tanks);      m.hitTank(MyTank);      m.draw(g);             //if(!m.isLive())        //missiles.remove(m);      //else m.draw(g);    }    /**     * 画出爆炸;     */    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.colliedsWithWall(w1);      t.colliedsWithWall(w2);      t.colliedsWithTanks(tanks);      t.draw(g);    }         b.draw(g);    MyTank.eat(b);    MyTank.draw(g);  }     /**   * 利用双缓冲技术消除坦克闪烁的现象;   */  public void update(Graphics g) //g为画在屏幕上的画笔;  {    if(OffScreenImage==null)      OffScreenImage=this.createImage(GAME_WIDTH, GAME_HEIGHT);    Graphics gOffScreen=OffScreenImage.getGraphics();//gOffScreen是OffScreenImage的画笔;    Color c=gOffScreen.getColor();    gOffScreen.setColor(Color.GREEN);    gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);    gOffScreen.setColor(c);    paint(gOffScreen);//画在虚拟图片上;    g.drawImage(OffScreenImage,0,0,null);//用g画笔将虚拟图片上的东西画在屏幕上       }        private class PaintThread implements Runnable{     public void run() {      while(true)      {        repaint();//这里的repaint方法是Frame类的        try{        Thread.sleep(100);        }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) {    new TankWarClient("My Tank World").launchFrame();  }            }

Wall.java

package com.hkm.TankWar;import java.awt.*;/** * 生成阻碍物墙这个类; * @author Hekangmin * */ public class Wall {  /**   * x,y为墙的位置,w,h为宽度高度;   */  int x,y,w,h;  /**   * 持有引用   */  TankWarClient tc;     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;  }     public void draw(Graphics g)  {    Color c=g.getColor();    g.setColor(Color.GRAY);    g.fillRect(x,y,w,h);    g.setColor(c);  }     /**   * 得到墙的矩形区域;   * @return   */  public Rectangle getRect()  {    return new Rectangle(x,y,w,h);  }   }

以上所述就是本文的全部内容了,希望大家能够喜欢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表