欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java制作简单的坦克大战

程序员文章站 2024-03-02 16:52:28
详情请参照注释,这里就不多废话了,实现一下儿时的经典而已。 blood.java package com.hkm.tankwar; import java.a...

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

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);
  }
   
}

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