21世纪最大的一场坦克大战:T90居然能随心所欲干掉T80!

vns85978威尼斯城官网 6
军史

原标题:21世纪最大的一场坦克大战:T90居然能随心所欲干掉T80!

Java-坦克大战,坦克大战

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

 

利用Java语言中的集合、Swing、线程等知识点编写一个坦克大战游戏。
(1)画出敌我坦克的原理: 在坦克类里面有…

坦克大战升级版,超级坦克大战

相关游戏: 坦克大战 发布时间:2017-10-12

坦克大战可能是很多人儿时的回忆,经典的玩法,紧张刺激的操作体验。可能很多人都想重温这款非常经典好玩的坦克大战游戏,今天我们要来介绍的是这款坦克大战游戏的升级版,超级坦克大战。超级坦克大战作为这款非常经典的坦克大战游戏的升级版,到底会有哪里不同,又会有什么紧张刺激的玩法体验,下面就由小编带你走进这款非常好玩的游戏,超级坦克大战。

vns85978威尼斯城官网 1

超级坦克作为一款非常耐玩的游戏,可能是无数人儿时的经典回忆。接下来就由小编来介绍这款非常经典的游戏的升级版,超级坦克大战。超级坦克大战作为坦克大战的升级版,在玩法体验上保留了经典坦克大战的玩法,但是在很多细节上又有了不错的改良和提升。接下来就由小编介绍一下详细的改动和玩法。

超级坦克大战比起经典的坦克大战,首先改变的就是游戏的参与人数,在经典坦克大战中,游戏的参与人数就是只有一人独自的通关。作为一名孤胆英雄,可能通关的时候只有一个人,通关的难度尚且不谈,但是通关之后的喜悦却没人分享这确实是一个非常浪费的事情。所以在超级坦克大战中加入了双人的玩法。

当存在了双人的玩法时,那么超级坦克大战就有了不同的体验。双人坦克大战在游戏中加入了合作和对抗的玩法。在合作的模式中,两个人可以通力合作一起完成整个关卡。在对抗模式中可以相互对抗,相互炮击。

以上就是超级坦克大战的介绍。相对于经典坦克大战,希望大家能够更加喜欢这款经典版的升级款。超级坦克大战,好玩值得一试。

上一篇:水果连连看,经典的连连看小游戏
下一篇:一款神奇的飞行棋,卡通飞行棋

Java坦克大战(二),java坦克大战

本文紧接上一篇讲解坦克大战这个项目,因为当初在学习的时候,是以这个案例逐步学习Java基础的,过程是先讲知识点,再将知识点逐步的融入到项目中,即给坦克添加新的功能。之前的Demo练习,想都记录下来。这里不会具体讲解知识点的概念,下面开始啦~

Demo1:Flie的基本用法

package com.fanghua1;

import java.io.*;

public class Demo1_9 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // 创建一个文件对象(d:\\aa.txt是存在的)
        File f = new File("d:\\aa.txt");
        // 得到文件路径
        System.out.println("文件的路径:" + f.getAbsolutePath());
        // 得到文件的大小(字节大小)
        System.out.println("文件的字节:" + f.length());
        System.out.println("可读" + f.canRead());

        // 创建文件和创建文件夹
        File f2 = new File("d:\\222.txt");
        // 先判断文件是否存在
        if (!f2.exists()) {
            // 可以创建
            try {
                f2.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else {
            System.out.println("有文件,不能创建");
        }
        File f3 = new File("d:\\ff");
        if (f3.isDirectory()) {
            System.out.println("文件夹存在");
        } else {
            // 创建文件夹
            f3.mkdir();
        }

        // 列出文件夹下面的所有文件
        File f4 = new File("d:\\MyJavaDemo");
        if (f4.isDirectory()) {
            File lists[] = f4.listFiles();
            for (int i = 0; i < lists.length; i++) {
                System.out.println("文件名:" + lists[i].getName());
            }
        }

    }

}

Demo2:演示FileInputStream

package com.fanghua1;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Demo1_11 {
    public static void main(String[] args) {
        File f = new File("d:\\aa.txt");
        FileInputStream fis = null;
        byte bytes[] = new byte[1024];
        int n = 0;
        try {
            fis = new FileInputStream(f);
            try {
                while ((n = fis.read(bytes)) != -1) {
                    String s = new String(bytes, 0, n);
                    System.out.println(s);
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Demo3:演示FileOutputStream

package com.fanghua1;

import java.io.*;
public class Demo2_1 {
    public static void main(String[] args) {
        // 这里:File f=new File("d:\\ss.text");
        // 如果d:\\ss.text不存在,它会直接创建这个文件
        // 如果存在,会进行覆盖。所以一定一定要进行判断
        File f = new File("d:\\ss.text");
        // 字节输出流
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(f);
            // \r\n:表示换行
            String s = "我的第一个字节输出流文件,文本内容\r\n";
            String s1 = "我是上一句的下一行";

            fos.write(s.getBytes());
            fos.write(s1.getBytes());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

Demo4:演示图片的拷贝

package com.fanghua1;

import java.io.*;

public class Demo2_2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        // 思路:先把图片读入到内存--->写入到某个文件
        // 因为是二进制文件,因策只能用字节流完成
        //可以不用File f=new File("c:\\a.jpg");下面直接把c:\\a.jpg给FileInoutStream即可
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("c:\\a.jpg");
            fos = new FileOutputStream("d:\\a.jpg");// 这里a.jpg,你写什么就命名为什么

            byte buf[] = new byte[512]; // 512 是1024的一半
            int n = 0;// 记录实际读取到的字节数
            // 循环读取
            while ((n= fis.read(buf)) != -1) {
                //输出到指定文件,验证:没有这句话在d盘会创建0字节的a.jpg文件
                fos.write(buf);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                fos.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

Demo5:演示BufferedReader

package com.fanghua1;

import java.io.*;

public class Demo2_3 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // 不是这里:FileReader f=new FileReader("d:\\MyJavaDemo\\Demo6.java");
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            FileReader f = new FileReader("d:\\MyJavaDemo\\Demo6.java");
            br = new BufferedReader(f);
            // 创建FileWriter对象
            FileWriter fw = new FileWriter("e:\\赵云.txt");
            bw = new BufferedWriter(fw);
            // 循环读取
            String s = "";
            while ((s = br.readLine()) != null) {
                // 输出到磁盘(+"\r\n"换行)
                bw.write(s + "\r\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
                bw.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

坦克大战(1.2版本)(#^.^#)

1.Menbers类

package com.fanghua2;
/**
 * 从Menbers.java里分离出来,代表坦克的功能类(同包访问机制)
 * 目的:减少Menbers.java文件的长度,整洁、规范
 */

//坦克类
class Tank1_2 {

    int x = 0;
    int y = 0;

    // 坦克方向:0表示上,1表示右,2表示下,3表示左
    int direct = 0;
    int speed = 1;
    //坦克的颜色
    int color;

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getDirect() {
        return direct;
    }

    public void setDirect(int direct) {
        this.direct = direct;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    // 构造函数
    public Tank1_2(int x, int y) {
        this.x = x;
        this.y = y;

    }

}
//敌人的坦克
class EnemyTank extends Tank1_2{

    public EnemyTank(int x, int y) {
        super(x, y);
        // TODO Auto-generated constructor stub
    }
}

//我的坦克
class Hero1_2 extends Tank1_2 {
    public Hero1_2(int x, int y) {
        super(x, y);
    }

    public void moveUp() {
        y -= speed;
    }
    public void moveRight() {
        x += speed;
    }
    public void moveDown() {
        y += speed;
    }
    public void moveLeft() {
        x -= speed;
    }
}

2.MyTankGame1_3类

/*
 * 删掉很多之前的注释
 * 功能:画出坦克1.2版本
 * 坦克移动的时候,头尾相应进行更正
 * 学习:文件(类)剥离、线程
 */
package com.fanghua2;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.Vector;

import javax.swing.*;

public class MyTankGame1_3 extends JFrame {

    Mypanel1_2 mp = null;

    public static void main(String[] args) {
        new MyTankGame1_3();
    }

    // 构造函数
    public MyTankGame1_3() {
        mp = new Mypanel1_2();
        this.add(mp);
        // 注册监听
        this.addKeyListener(mp);

        this.setSize(600, 500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);

    }
}

// 我的面板
class Mypanel1_2 extends JPanel implements java.awt.event.KeyListener {

    // 定义我的坦克
    Hero1_2 hero = null;
    // 定义敌人的坦克(不止一辆,线程安全,集合)
    Vector<EnemyTank> ets = new Vector<EnemyTank>();
    int enSize = 3;// 敌人坦克保持三个

    // 构造函数
    public Mypanel1_2() {
        hero = new Hero1_2(10, 10);
        for (int i = 0; i < enSize; i++) {

            // 创建一辆敌人的坦克
            EnemyTank et = new EnemyTank((i + 1) * 50, 0);
            et.setColor(0);
            //坦克默认反向是0(向上),这里改一下
            et.setDirect(2);
            // 加入
            ets.add(et);

        }
    }

    // 重写paint函数
    public void paint(Graphics g) {
        // 一定要调用
        super.paint(g);
        g.fillRect(0, 0, 600, 500);
        // 画出自己的坦克(将方向填进去)
        this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);
        // 画出敌人的坦克(这里不用 i<enSize,而用ets.size,敌人坦克会被打死)
        for (int i = 0; i < enSize; i++) {
            this.drawTank(ets.get(i).getX(), ets.get(i).getY(), g, ets.get(i)
                    .getDirect(), 0);

        }

    }

    // 画出坦克的函数
    public void drawTank(int x, int y, Graphics g, int direct, int type) {
        // 坦克类型
        switch (type) {
        case 0:
            g.setColor(Color.green);
            break;
        case 1:
            g.setColor(Color.yellow);
            break;
        }
        // 方向设置
        switch (direct) {
        // 向上
        case 0:
            g.fill3DRect(x, y, 5, 30, false);
            g.fill3DRect(x + 15, y, 5, 30, false);
            g.fill3DRect(x + 5, y + 5, 10, 20, false);
            g.fillOval(x + 5, y + 10, 10, 10);
            g.drawLine(x + 10, y + 15, x + 10, y);
            break;
        // 向右
        case 1:
            g.fill3DRect(x, y, 30, 5, false);
            g.fill3DRect(x, y + 15, 30, 5, false);
            g.fill3DRect(x + 5, y + 5, 20, 10, false);
            g.fillOval(x + 10, y + 5, 10, 10);
            g.drawLine(x + 15, y + 10, x + 30, y + 10);
            break;
        // 向下
        case 2:
            g.fill3DRect(x, y, 5, 30, false);
            g.fill3DRect(x + 15, y, 5, 30, false);
            g.fill3DRect(x + 5, y + 5, 10, 20, false);
            g.fillOval(x + 5, y + 10, 10, 10);
            g.drawLine(x + 10, y + 15, x + 10, y + 30);
            break;
        // 向左
        case 3:
            g.fill3DRect(x, y, 30, 5, false);
            g.fill3DRect(x, y + 15, 30, 5, false);
            g.fill3DRect(x + 5, y + 5, 20, 10, false);
            g.fillOval(x + 10, y + 5, 10, 10);
            g.drawLine(x + 15, y + 10, x, y + 10);
            break;
        }

    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        // 已更正为顺时针
        if (e.getKeyCode() == KeyEvent.VK_UP 
                || e.getKeyCode() == KeyEvent.VK_W) {
            this.hero.moveUp();
            this.hero.setDirect(0);
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT
                || e.getKeyCode() == KeyEvent.VK_D) {
            this.hero.setDirect(1);
            this.hero.moveRight();
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN
                || e.getKeyCode() == KeyEvent.VK_S) {
            this.hero.moveDown();
            this.hero.setDirect(2);
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT
                || e.getKeyCode() == KeyEvent.VK_A) {
            this.hero.moveLeft();
            this.hero.setDirect(3);
        }
        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }
}

此时,我的坦克已经可以用键盘来操控:

vns85978威尼斯城官网 2

 

本文紧接上一篇讲解坦克大战这个项目,因为当初在学习的时候,是以这个案例逐步学习Java基础的,过程…

早在1973年的第四次中东战争中,世界就已经领教到了反坦克导弹在现代装甲战争中的巨大作用,其射程远其精度高,基本可以做到对坦克一发入魂,这也迫使坦克本身为了应对未来战争做出改变。到了上世纪80年代,俄罗斯开始在坦克上大量安装爆炸反应装甲,其目的就是为了抵抗包括反坦克导弹在内的一切装药武器,当时基本所有苏俄主力坦克都安装了ERA,而作为苏联一部分的乌克兰同样不例外,这些ERA可以有效对抗RPG-7,9M113等反坦克武器,不过容易被破甲弹所破坏。

vns85978威尼斯城官网 3

理论上来说,2014年开始的顿巴斯战争可能会像1973年第四次中东战争一样,坦克的防护不足以对抗新锐反坦克武器的攻击,然而无论是俄军还是乌军,其拥有的反坦克导弹数量都严重不足,因此主力依然是坦克炮或者反坦克炮。乌军最初由于缺乏反坦克武器,对付俄军装甲部队时采用了集中火炮近距离射击的战术,不过在给俄军带来巨大损失的时候己方同样损失巨大,打不起消耗战的乌军没过多久便不再使用这种战术。

vns85978威尼斯城官网 4

更加令乌军绝望的是,在2015年签署的《第二次明斯克协议》中,规定双方炮兵均后撤50公里,这更让俄军装甲部队变得肆无忌惮。事实上在顿巴斯战争刚刚开打时,双方使用的坦克型号大同小异(因为东乌民兵手中的坦克基本上是从乌军火库中抢过来的),以T-64,T-72和少量T-80为主,但到了2014年9月,俄军的T-72B3坦克开赴前线,再加上后来出现的少量T-90A坦克,整个装甲战争形势瞬间逆转。

vns85978威尼斯城官网 5

虽说T-90A的数量相对较少,而且在运用上基本上是被当做预备队来使用,但面对乌军的老旧坦克基本上处于所向无敌的状态,战争已经进行了四年多,没有任何证据表明乌军在战场上击毁了一辆T-90A。

vns85978威尼斯城官网 6

2014年9月两军对决卢甘斯克,同一个月双方激战新亚速斯克,2015年1月双方激战顿涅茨克机场,2月激战杰巴利采沃,T-90A的出现极大地改变了战役走向,其装备的125毫米主炮可以在正常交战距离上随心所欲地干掉T-64BV甚至是T-80BV,而乌军对此毫无办法。原本双方交换比在1.5比1左右,如今乌军平均损失三辆坦克才能换取对方一辆坦克的损失!距离交战区最近的哈尔科夫机械制造厂在2014年示威运动中遭受了很大影响,至今产能也没有恢复。(利刃/陶波列夫)

尊重内容,从尊重作者开始,转载、合作请私信联系我们。返回搜狐,查看更多

责任编辑:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图