Java-坦克大战

利用Java语言中的集合、Swing、线程等知识点编写一个坦克大战游戏。
(1) 画出敌我坦克的原理:
在坦克类里面有一个布尔类型变量good。用于判断坦克的阵营,在创建坦克对象时在Tank类的构造方法中传入good的值。在画坦克的时候判断good的值,区分敌我坦克的颜色;
(2) 坦克运动的原理:
在坦克类里写入了监听键盘摁键的响应事件,对监听到的上下左右键进行记录,并合成坦克移动的八个方向的变量。之后对应每个方向的不同对坦克坐标x,y的值做响应的更改实现我方坦克的移动。而敌方坦克则自动移动,通过随机数对敌方坦克移动方向的随机,并且随机出每次移动的次数。两个随机值相结合即实现了敌方坦克的移动。
(3) 坦克发射子弹的原理:
通过键盘监听,检测到发射子弹命令后将主类的子弹类集合中添加一个子弹类。将炮筒的方向以及坦克的位置以及坦克的阵营传入给子弹类,在主类paint画方法中一直循环子弹类集合,如果集合内有子弹,就画出来。这样就实现了发射子弹。
(4) 坦克、子弹、墙的碰撞原理:
在坦克类子弹类墙类中分别getRect方法获取自身的范围,然后在每次画坦克、子弹时都会进行相应的碰撞检测(在坦克类里有与墙和出自己外的坦克相撞的处理方法、在子弹类里有与墙和坦克相碰撞的处理方法。),如果自身与不该碰撞的物体的范围相重合,则代表两物体相撞。
(5)坦克加血的原理:
在血块类中有血块与我方坦克相碰撞的处理方法,如果血块范围与坦克范围重合则血块类死亡,并且坦克类的血量回复置满。
(6)坦克复活的原理:
通过键盘监听,检测到我方坦克复活命令后,如果我方坦克处于死亡状态,则将我方坦克存货状态改为活着并且将我方坦克血量回置满血。

 编程思想:

坦克大战的编程思想在主类开启一个线程,没50毫秒循环一次画方法(绘制整个界面内的所有东西)。画的东西有敌我坦克(颜色区分)、子弹、墙、血块、爆炸。所以总共写出了几个类:Tank坦克类、Missile子弹类、Wall墙类、Blood血块类、TankClient主类。在每一个类中均写有画方法实现本类属性的绘制功能。在主类中有键盘监听事件调用这Tank类的键盘监听事件。通过键盘监听判断出对Tank做出相应的移动,而敌方Tank则是随机运动。并且每次刷新都有调用各类的碰撞方法,判断一些不该碰撞的对象的情况时做出处理。而每个对象的创建例如子弹这些是在触发产生之后将新建子弹类加入一个子弹类集合之中,在绘制的时候判断集合中的数量进行绘制,出界或者打死坦克则在集合中删除。其他类也均相似,不在细说。
代码中每步都注释有相应的解释。

TankClient.java

  1 import java.awt.Color;
  2 import java.awt.Font;
  3 import java.awt.Graphics;
  4 import java.awt.Image;
  5 import java.awt.event.KeyAdapter;
  6 import java.awt.event.KeyEvent;
  7 import java.awt.event.WindowAdapter;
  8 import java.awt.event.WindowEvent;
  9 import java.util.ArrayList;
 10 import java.util.List;
 11 
 12 import javax.swing.JFrame;
 13 
 14 public class TankClient extends JFrame{
 15     /**
 16      * @param args
 17      */
 18     Image OffScrennImage = null;    //双缓冲内存图片存储
 19     /*游戏大小*/
 20     public static final int GAME_WIDTH = 800;    //界面宽
 21     public static final int GAME_HEIGTH = 600;    //界面高
 22     
 23     Tank myTank = new Tank(500,400,true,Color.red,Tank.Direction.STOP, this);//我方坦克类
 24     List<Missile> missiles = new ArrayList<Missile>();//子弹的集合
 25     List<Explode> explode = new ArrayList<Explode>();//爆炸集合
 26     List<Tank> tanks = new ArrayList<Tank>();    //坦克集合
 27     Wall wall1 = new Wall(150,200,20,300,this);    //墙1
 28     Wall wall2 = new Wall(250,500,300,20,this);    //墙2
 29     Wall wall3 = new Wall(650,200,20,300,this);    //墙2
 30     Wall wall4 = new Wall(250,300,300,20,this);    //墙2
 31     Wall wb = new Wall(750,550,40,40,this);    //墙2
 32     Blood b = new Blood();    //血类
 33     
 34     
 35     public static void main(String[] args) {
 36         // TODO Auto-generated method stub
 37         TankClient tc=new TankClient();
 38         tc.lauchFrame();
 39     }
 40 
 41     private void lauchFrame() {
 42         // TODO Auto-generated method stub
 43         for (int i = 0; i < 10; i++){
 44             tanks.add(new Tank(50+40*(i+1), 50, false,Color.blue,Tank.Direction.D, this));
 45         }
 46         this.setLocation(100, 100);    //窗口初始坐标点
 47         this.setSize(GAME_WIDTH, GAME_HEIGTH);        //窗口初始大小
 48         this.setTitle("TankWar");    //窗口名称
 49         /*窗口监听*/
 50         this.addWindowListener(new WindowAdapter() {
 51             @Override
 52             /*点退出叉之后运行*/
 53             public void windowClosing(WindowEvent e) {
 54                 // TODO Auto-generated method stub
 55                 System.exit(0);    //退出
 56             }
 57         });
 58         this.addKeyListener(new KeyMoniton());    //设置键盘监听
 59         this.setVisible(true);    //设置窗口显现
 60         this.setResizable(false);    //设置窗口不可改变大小
 61         this.getContentPane().setBackground(Color.green);    //设置窗口前景色为绿色
 62         new Thread(new PaintThread()).start();    //开始运行PaintThread类run
 63     }
 64 
 65     @Override
 66     public void paint(Graphics g) {
 67         // TODO Auto-generated method stub
 68         //Graphics为画笔类
 69         super.paint(g);
 70         myTank.draw(g);
 71         wall1.draw(g);
 72         wall2.draw(g);
 73         wall3.draw(g);
 74         wall4.draw(g);
 75         wb.draw(g);
 76         b.draw(g);
 77         myTank.eatBlood(b);
 78         myTank.hitWall(wall1);
 79         myTank.hitWall(wall2);
 80         myTank.hitWall(wall3);
 81         myTank.hitWall(wall4);
 82         /*循环子弹集合*/
 83         for (int i = 0; i < missiles.size(); i++){
 84             Missile m = missiles.get(i);    //获取当前子弹
 85             m.hitTanks(tanks);    //自己子弹打死敌方坦克
 86             m.hitWall(wall1);    //子弹与墙
 87             m.hitWall(wall2);
 88             m.hitWall(wall3);
 89             m.hitWall(wall4);
 90             m.hitTank(myTank);//敌人子弹打击自己的坦克
 91             m.draw(g);    //画子弹
 92         }
 93         for    (int i = 0; i < explode.size(); i++){
 94             explode.get(i).draw(g);    //画爆炸
 95         }
 96         for (int i = 0; i < tanks.size(); i++){
 97             Tank t = tanks.get(i);
 98             t.draw(g);    //画敌方坦克
 99             t.hitTanks(tanks);
100             t.hitWall(wall1);    //坦克与墙
101             t.hitWall(wall2);
102             t.hitWall(wall3);
103             t.hitWall(wall4);
104         }
105         //g.setFont(new Font("宋体",Font.BOLD,20));
106         g.drawString("missiles  count:"+missiles.size(), 10, 50);//显示
107         g.drawString("explode  count:"+explode.size(), 10, 80);//显示
108         g.drawString("tanks count:"+tanks.size(),10, 110);
109         g.drawString("myTank Life:"+myTank.getLife(), 10, 130);
110         g.drawString("回血:", 750, 540);
111         g.drawString("方向键移动方向;E:释放移动血快", 10, 590);
112         g.drawString("z:发射东风-31;a:发射东风-41;", 10, 570);
113         g.drawString("F2:复活;F3:敌方复活(对多20)", 10, 550);
114         g.drawString("R:位置还原;Q:血量加满", 10, 530);
115     }
116     
117     @Override
118     /*repaint-〉update->paint*/
119     public void update(Graphics g) {
120         // TODO Auto-generated method stub
121         super.update(g);
122         if(OffScrennImage == null)
123             OffScrennImage = this.createImage(GAME_WIDTH, GAME_HEIGTH);
124         Graphics goffscrenn = OffScrennImage.getGraphics();    //设置一个内存画笔颜色为前景图片颜色
125         Color c = goffscrenn.getColor();    //还是先保存前景颜色
126         goffscrenn.setColor(Color.green);    //设置内存画笔颜色为绿色
127         goffscrenn.fillRect(0, 0, GAME_WIDTH, GAME_HEIGTH);    //画成图片,大小为游戏大小
128         goffscrenn.setColor(c);    //还原颜色
129         g.drawImage(OffScrennImage, 0, 0, null);    //在界面画出保存的图片
130         paint(goffscrenn);    //把内存画笔调用给paint
131     }
132 
133     private class PaintThread implements Runnable{
134 
135         @Override
136         public void run() {
137             // TODO Auto-generated method stub
138             while(true){
139                 repaint();    //运行顺序repaint->update->paint
140                 try{
141                     Thread.sleep(50);    //每隔50毫秒刷新画面一次
142                 }catch(Exception e){
143                     e.printStackTrace();
144                 }
145             }
146         }
147         
148     }
149     /*键盘响应*/
150     private class KeyMoniton extends KeyAdapter{
151 
152         /*摁下键盘响应*/
153         @Override
154         public void keyPressed(KeyEvent e) {
155             // TODO Auto-generated method stub
156             super.keyPressed(e);
157             myTank.KeyPressed(e);
158         }
159         /*抬起键盘响应*/
160         @Override
161         public void keyReleased(KeyEvent e) {
162             // TODO Auto-generated method stub
163             super.keyReleased(e);
164             myTank.keyReleased(e);
165         }
166         
167     }
168 }

Tank.java

  1 import java.awt.Color;
  2 import java.awt.Graphics;
  3 import java.awt.Image;
  4 import java.awt.Rectangle;
  5 import java.awt.event.KeyEvent;
  6 import java.util.List;
  7 import java.util.Random;
  8 
  9 import javax.swing.ImageIcon;
 10 
 11 
 12 public class Tank {
 13     /*坦克本身数据*/
 14     int x, y;//坦克坐标
 15     private int oldX, oldY;    //坦克上一步坐标
 16     public static final int Whith = 30;    //坦克宽
 17     public static final int Higth = 30;    //坦克高
 18     public static final int XSPEED = 5;    //横向移动速度
 19     public static final int YSPEED = 5;    //纵向移动速度
 20     private Color color;    //坦克颜色
 21     private boolean bL=false, bU=false, bR=false, bD=false;    //四个方向控制值
 22     enum Direction {L, LU, U, RU, R, RD, D, LD, STOP};    //由四个方向值合成八个方向的移动
 23     private Direction dir = Direction.STOP;    //出场方向
 24     private Direction ptDir = Direction.D;    //炮筒初始方向 
 25     private boolean good;    //判断坦克的阵营
 26     private boolean live = true;    //判断坦克是否存活
 27     private static Random r = new Random();//设置一个随机值变量
 28     private static int step = r.nextInt(12)+3;    //敌方坦克随机移动步骤3-14步
 29     private int Life = 100;    //血量
 30     private BloodBar bb = new BloodBar();    //血块类
 31     
 32 //    ImageIcon icon = new ImageIcon("res\myTank.jpg");
 33 //    ImageIcon icon2 = new ImageIcon("res\enemyTank.jpg");
 34 //    Image image = icon.getImage();
 35 //    Image image2 = icon2.getImage();
 36     
 37     
 38     private TankClient tc;    //主类权限
 39 
 40     public Tank(int x, int y, boolean good, Color color) {
 41         super();
 42         this.x = x;
 43         this.y = y;
 44         this.color = color;
 45         this.good = good;
 46     }
 47     public Tank(int x, int y, boolean good,Color color,Direction dir,TankClient tc){
 48         this(x,y,good,color);
 49         this.dir = dir;
 50         this.tc = tc;
 51     }
 52     /*获取坦克生命值*/
 53     public int getLife() {
 54         return Life;
 55     }
 56     /*设置坦克生命值*/
 57     public void setLife(int Life) {
 58         this.Life = Life;
 59     }
 60 
 61     /*获取坦克阵营*/
 62     public boolean isGood() {
 63         return good;
 64     }
 65     /*设置坦克阵营*/
 66     public void setGood(boolean good) {
 67         this.good = good;
 68     }
 69     /*获取坦克存活状态*/
 70     public boolean isLive() {
 71         return live;
 72     }
 73     /*设置坦克存活状态*/
 74     public void setLive(boolean live) {
 75         this.live = live;
 76     }
 77     /*画坦克*/
 78     public void draw(Graphics g){
 79         if(!live){    
 80             if(!good){
 81                 tc.tanks.remove(this);    //敌方坦克死亡时在集合中删除
 82                 //tc.tanks.add(new Tank(r.nextInt(700),r.nextInt(500),false,Color.blue,Direction.D,this.tc));
 83             }
 84             return;
 85         }
 86         /*先保存之前的画笔颜色,画完之后再还原画笔颜色*/
 87         Color c = g.getColor();    //获取当前画笔颜色
 88         g.setColor(color);    //设置画笔颜色为红色
 89         /*画坦克*/
 90         g.fillOval(x, y, Whith, Higth);
 91         /*两种方法绘制敌我坦克,运用之前加入的图片或者颜色区分*/
 92 //        if(good)
 93 //            g.drawImage(image, x, y,Whith,Higth,null);
 94 //        else
 95 //            g.drawImage(image2, x, y, Whith, Higth, null);
 96         if(good)    
 97             bb.draw(g);    //我方坦克画血条
 98         g.setColor(Color.black);
 99         /*通过炮筒方向画出炮筒*/
100         switch(ptDir){
101         case L:
102             g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x, y+Tank.Higth/2);
103             break;
104         case LU:
105             g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x, y);
106             break;
107         case U:
108             g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith/2, y);
109             break;
110         case RU:
111             g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith, y);
112             break;
113         case R:
114             g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith, y+Tank.Higth/2);
115             break;
116         case RD:
117             g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith, y+Tank.Higth);
118             break;
119         case D:
120             g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith/2, y+Tank.Higth);
121             break;
122         case LD:
123             g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x, y+Tank.Higth);
124             break;
125         }
126         g.setColor(c);    //还原画笔颜色
127         move();//移动
128     }
129     
130     /*键盘监听;摁键*/
131     public void KeyPressed(KeyEvent e){
132         int key = e.getKeyCode();    //将键盘监听到的摁键以整数保存
133         /*键盘移动坦克*/
134         switch(key){
135         /*移动摁键*/
136         case KeyEvent.VK_UP:
137             bU=true;
138             break;
139         case KeyEvent.VK_DOWN:
140             bD=true;
141             break;
142         case KeyEvent.VK_RIGHT:
143             bR=true;
144             break;
145         case KeyEvent.VK_LEFT:
146             bL=true;
147             break;
148         }
149         locateDirection();
150     }
151     
152     /*键盘监听;抬起键*/
153     public void keyReleased(KeyEvent e){
154         int key = e.getKeyCode();    //将键盘监听到的摁键以整数保存
155         /*键盘移动坦克*/
156         switch(key){
157         case KeyEvent.VK_UP:
158             bU=false;
159             break;
160         case KeyEvent.VK_DOWN:
161             bD=false;
162             break;
163         case KeyEvent.VK_RIGHT:
164             bR=false;
165             break;
166         case KeyEvent.VK_LEFT:
167             bL=false;
168             break;
169         case KeyEvent.VK_Z:    //单发子弹
170             if(live)
171                 fire();
172             break;
173         case KeyEvent.VK_F2:    //我方复活
174             if(!this.live){
175                 this.live=true;
176                 this.setLife(100);
177             }
178             break;
179         case KeyEvent.VK_F3:    //敌方复活
180             fuhuo();
181             break;
182         case KeyEvent.VK_A:        //无敌导弹
183             superFire();
184             break;
185         case KeyEvent.VK_Q:        //回血
186             if(this.live)
187                 this.Life = 100;
188             break;
189         case KeyEvent.VK_E:        //释放血块
190             tc.b.fh();
191             break;
192         /*还原位置键*/
193         case KeyEvent.VK_R:
194             x = 50;
195             y = 50;
196             break;
197         }
198         locateDirection();    //合成方向
199     }
200     /*合成移动方向*/
201     void locateDirection(){
202         if(bL&&!bU&&!bR&&!bD) dir=Direction.L;
203         else if(bL&&bU&&!bR&&!bD) dir=Direction.LU;
204         else if(!bL&&bU&&!bR&&!bD) dir=Direction.U;
205         else if(!bL&&bU&&bR&&!bD) dir=Direction.RU;
206         else if(!bL&&!bU&&bR&&!bD) dir=Direction.R;
207         else if(!bL&&!bU&&bR&&bD) dir=Direction.RD;
208         else if(!bL&&!bU&&!bR&&bD) dir=Direction.D;
209         else if(bL&&!bU&&!bR&&bD) dir=Direction.LD;
210         else if(!bL&&!bU&&!bR&&!bD) dir=Direction.STOP;
211     }
212     
213     void move(){ //移动
214         /*记录上一步的位置*/
215         oldX = x;
216         oldY = y;
217         switch(dir){
218         case L:
219             x-=XSPEED;
220             break;
221         case LU:
222             x-=XSPEED;
223             y-=YSPEED;
224             break;
225         case U:
226             y-=YSPEED;
227             break;
228         case RU:
229             x+=XSPEED;
230             y-=YSPEED;
231             break;
232         case R:
233             x+=XSPEED;
234             break;
235         case RD:
236             x+=XSPEED;
237             y+=YSPEED;
238             break;
239         case D:
240             y+=YSPEED;
241             break;
242         case LD:
243             x-=XSPEED;
244             y+=YSPEED;
245             break;
246         case STOP:
247             break;
248         }
249         /*判断坦克移动越界情况(游戏边界)*/
250         if(x < 5)    x = 5;
251         if(y < 25)    y = 25;
252         if(x+Whith > tc.GAME_WIDTH-5)    x = tc.GAME_WIDTH-Whith-5;
253         if(y+Higth > tc.GAME_HEIGTH-5) y = tc.GAME_HEIGTH-Higth-5;
254         
255         if(dir != Direction.STOP)    //如果坦克不静止就改变炮筒方向
256             ptDir = dir;
257         
258         /*敌方坦克自动移动*/
259         if(!good){
260             Direction[] dirs = Direction.values();    //将方向变量设为数组
261             if(step == 0){
262                 step = r.nextInt(12)+3;    //随机移动步骤
263                 int randomNumber = r.nextInt(dirs.length);    //随机移动方向
264                 dir = dirs[randomNumber];
265             }
266             step--;
267             if(r.nextInt(40)>30) this.fire();    //随机是否发射炮弹
268         }
269     }
270     /*敌方坦克复活*/
271     public void fuhuo(){
272         if(tc.tanks.size() < 20)
273             while(true){
274                 int x = r.nextInt(700);
275                 int y = r.nextInt(500);
276                 Tank t = new Tank(x,y,false,Color.blue,Direction.D,tc);
277                 /*如果坦克与墙重合则重新随机位置直到不重合为止才将新坦克加入集合*/
278                 if(t.getRect().intersects(tc.wall1.getRect())||t.getRect().intersects(tc.wall2.getRect())
279                         ||t.getRect().intersects(tc.wall3.getRect())
280                         ||t.getRect().intersects(tc.wall4.getRect())){
281                     continue;
282                 }
283                 else{
284                     tc.tanks.add(t);
285                     break;
286                 }
287         }
288     }
289     /*子弹发射*/
290     public void fire(){
291         int x = this.x + Whith/2 - Missile.Whith/2;    //控制子弹方向为坦克中间
292         int y = this.y + Higth/2 - Missile.Higth/2;
293         tc.missiles.add(new Missile(ptDir,color,x,y,good,tc)); //创建新的子弹类加入到子弹集合中
294     }
295     /*碰撞;获取坦克的范围*/
296     public Rectangle getRect(){
297         return new Rectangle(x,y,Whith,Higth);
298     }
299     /*回执上一步位置*/
300     private void stay(){
301         x = oldX;
302         y = oldY;
303     } 
304     /*如果撞墙,调用stay方法,返回上一步位置*/
305     public boolean hitWall(Wall w){ 
306         if(this.live&&this.getRect().intersects(w.getRect())){
307             this.stay();
308             return true;
309         }
310         return false;
311     }
312     /*坦克互相撞击事件*/
313     public boolean hitTanks(List<Tank> tanks){ 
314         for(int i=0;i<tanks.size();i++){
315             Tank t=tanks.get(i);
316             if(this!=t){//自己与自己不可相撞
317                 /*如果相撞返回上一步位置*/
318                 if(this.live&&t.isLive()&&this.getRect().intersects(t.getRect())){
319                     this.stay();
320                     t.stay();
321                     return true;
322                 }
323             }
324         }
325         return false;
326     }
327     /*带开火方向的发射函数*/
328     public Missile fire(Direction dir){
329         if(!live) return null;
330         int x=this.x+Whith/2-Missile.Whith/2;
331         int y=this.y+Higth/2-Missile.Higth/2;
332         Missile m=new Missile(dir,color,x, y,good, this.tc);
333         tc.missiles.add(m);
334         return m;
335     }
336     /*超级射击导弹*/
337     private void superFire(){
338         Direction[] dirs=Direction.values();
339         for(int i=0;i<8;i++){
340             fire(dirs[i]);//循环调用八个方向
341         }
342     }
343     /*新增血块类*/
344     private class BloodBar{
345         /*画血条*/
346         public void draw(Graphics g){
347             Color c=g.getColor();
348             g.setColor(Color.red);
349             g.drawRect(x, y-10, Whith, 10);
350             int w=Whith*Life/100;
351             g.fillRect(x, y-10, w, 10);
352             g.setColor(c);
353         }
354     }
355     /*吃血方法*/
356     public boolean eatBlood(Blood b){
357         if(this.live&&b.isLive()&&this.isGood()&&this.getRect().intersects(b.getRect())){
358             this.setLife(100);
359             b.setLive(false);
360             return true;
361         }
362         if(this.getRect().intersects(tc.wb.getRect()))
363             this.Life = 100;
364         return false;
365     }
366 }

Missile.java

  1 import java.awt.Color;
  2 import java.awt.Graphics;
  3 import java.awt.Rectangle;
  4 import java.util.List;
  5 
  6 public class Missile {
  7     /*子弹本身数据*/
  8     Tank.Direction dir;    //子弹方向
  9     Color c;    //子弹颜色
 10     int x,y;    //子弹位置
 11     public static final int XSPEED = 15;    //横向移动速度
 12     public static final int YSPEED = 15;    //纵向移动速度
 13     public static final int Whith = 10;        //子弹宽
 14     public static final int Higth = 10;        //子弹高
 15     private boolean live = true;    //判断子弹的存活
 16     private boolean good;    //判断子弹和阵营
 17     
 18     private TankClient tc;//主类权限
 19     
 20 
 21     public Missile(Tank.Direction dir,Color c, int x, int y) {
 22         super();
 23             this.dir = dir;
 24             this.x = x;
 25             this.y = y;
 26             this.c = c;
 27     }
 28     public Missile(Tank.Direction dir,Color c, int x, int y,boolean good,TankClient tc){
 29         this(dir,c,x,y);
 30         this.good = good;
 31         this.tc = tc;
 32     }
 33     
 34     /*获取子弹的存活*/
 35     public boolean isLive() {
 36         return live;
 37     }
 38     /*设置子弹的存活*/
 39     public void setLive(boolean live) {
 40         this.live = live;
 41     }
 42     public void draw(Graphics g){
 43         /*如果子弹死亡状态将这个子弹在子弹集合中删除*/
 44         if(!live){
 45             tc.missiles.remove(this);    //集合中删除
 46             return;
 47         }
 48         /*先保存之前的画笔颜色,画完之后再还原画笔颜色*/
 49         Color d = g.getColor();    //获取当前画笔颜色
 50         g.setColor(c);    //设置画笔颜色为红色
 51         /*画子弹*/
 52         g.fillOval(x, y, Whith, Higth);    
 53         
 54         g.setColor(d);    //还原画笔颜色
 55         move();    //移动
 56     }
 57     
 58     public void move(){
 59         /*判断移动方向移动坦克位置*/
 60         switch(dir){
 61         case L:
 62             x-=XSPEED;
 63             break;
 64         case LU:
 65             x-=XSPEED;
 66             y-=YSPEED;
 67             break;
 68         case U:
 69             y-=YSPEED;
 70             break;
 71         case RU:
 72             x+=XSPEED;
 73             y-=YSPEED;
 74             break;
 75         case R:
 76             x+=XSPEED;
 77             break;
 78         case RD:
 79             x+=XSPEED;
 80             y+=YSPEED;
 81             break;
 82         case D:
 83             y+=YSPEED;
 84             break;
 85         case LD:
 86             x-=XSPEED;
 87             y+=YSPEED;
 88             break;
 89         case STOP:
 90             break;
 91         }
 92         /*判断子弹的越界情况;出界则子弹死亡,在子弹集合中删去*/
 93         if(x<0||y<0||x>TankClient.GAME_WIDTH||y>TankClient.GAME_HEIGTH)
 94             live = false;
 95     }
 96     /*碰撞;获取子弹的范围*/
 97     public Rectangle getRect(){
 98         return new Rectangle(x,y,Whith,Higth);
 99     }
100     /*子弹与坦克碰撞过程*/
101     public boolean hitTank(Tank t){
102         /*如果子弹与坦克在同一范围则子弹和坦克同时死亡;且子弹只能杀死对方坦克*/
103         if(this.live&&this.getRect().intersects(t.getRect())&&t.isLive()&&this.good!=t.isGood()){
104             if(t.isGood()){ //好坦克
105                 /*我方坦克子弹射中会减少生命值,生命值0的时候会死亡*/
106                 t.setLife(t.getLife()-20);
107                 if(t.getLife()<=0) 
108                     t.setLive(false);
109             }else{ //坏坦克
110                 t.setLive(false);//死亡
111             }
112             this.live=false;//子弹死亡
113             tc.explode.add(new Explode(x, y, tc));//新建爆炸加入集合
114             return true;
115         }
116         return false;
117     }
118     /*循环坦克集合分别进行判断子弹碰撞*/
119     public boolean hitTanks(List<Tank> tanks){
120         for    (int i = 0; i < tanks.size(); i++){
121             if(hitTank(tanks.get(i)))
122                 return true;
123         }
124         return false;
125     }
126     /*子弹与墙的碰撞过程*/
127     public boolean hitWall(Wall w){
128         /*如果子弹与墙的范围重合子弹死亡*/
129         if(this.live&&this.getRect().intersects(w.getRect())){
130             this.live=false;    //子弹死亡
131             return true;
132         }
133         return false;
134     }
135 }

Wall.java

 1 import java.awt.Graphics;
 2 import java.awt.Rectangle;
 3 
 4 
 5 public class Wall {
 6     /*墙数据*/
 7     int x,y,w,h;    //位置和宽高
 8     private TankClient tc;    //主类权限
 9     
10     public Wall(int x, int y, int w, int h, TankClient tc) {
11         super();
12         this.x = x;
13         this.y = y;
14         this.w = w;
15         this.h = h;
16         this.tc = tc;
17     }
18     /*获取墙的范围*/
19     public Rectangle getRect(){
20         return new Rectangle(x,y,w,h);
21     }
22     /*画墙*/
23     public void draw(Graphics  g){
24         g.fillRect(x, y, w, h);
25     }
26 }

Explode.java

import java.awt.Color;
import java.awt.Graphics;


public class Explode {
    /*坦克爆炸属性*/
    int x,y;    //爆炸位置
    private boolean live = true;    //爆炸是否存在
    int step = 0;    //爆炸时间控制
    int [] diameter = new int[] {4, 7, 12, 18, 26, 32, 49, 56, 65, 77, 80, 50, 40, 30, 14, 6};//爆炸范围
    
    private TankClient tc;    //主类权限
    public Explode(int x, int y, TankClient tc) {    
        super();
        this.x = x;
        this.y = y;
        this.tc = tc;
    }
    
    /*画爆炸*/
    public void draw(Graphics g){
        if(!live) return;    //如果爆炸死亡状态不画结束
        /*如果爆炸时间结束爆炸不存在并在集合中删除*/
        if(step == diameter.length){
            live = false;    //爆炸死亡
            step = 0;    //步骤时间归0
            tc.explode.remove(this);    //集合中删除
            return;
        }
        /*画爆炸*/
        Color c = g.getColor();
        g.setColor(Color.orange);
        g.fillOval(x, y, diameter[step], diameter[step]);
        g.setColor(c);
        
        step++;
    }
    
}

Blood.java

 1 import java.awt.Color;
 2 import java.awt.Graphics;
 3 import java.awt.Rectangle;
 4 import java.util.Random;
 5 
 6 
 7 public class Blood {
 8     /*血块数据*/
 9     int x, y, w, h;//血块位置和大小
10     private TankClient tc;    //主类权限
11     private boolean live=true;//血块的存活
12     private static Random r = new Random();//设置一个随机值变量
13     /*获取血块的存活状态*/
14     public boolean isLive() {
15         return live;
16     }
17     /*设置血块的存活状态*/
18     public void setLive(boolean live) {
19         this.live = live;
20     }
21     /*血块位置初值随机一个数值*/
22     public Blood(){
23         x=r.nextInt(600)+100;
24         y=r.nextInt(400)+100;
25         w=h=15;
26     }
27     /*画血块*/
28     public void draw(Graphics g){
29         if(!live) return;
30         Color c=g.getColor();
31         g.setColor(Color.magenta);
32         g.fillRect(x, y, w, h);
33         g.setColor(c);
34     }
35     /*释放血块*/
36     public void fh(){
37         if(!live){
38             x = r.nextInt(600)+100;
39             y = r.nextInt(400)+100;
40             live = true;
41         }
42     }
43     /*获取血块范围*/
44     public Rectangle getRect(){
45         return new Rectangle(x, y, w, h);
46     }
47 }
原文地址:https://www.cnblogs.com/ABook/p/5657714.html