java学习之坦克大战游戏

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java学习之坦克大战游戏相关的知识,希望对你有一定的参考价值。

  总结:由于这几天快过年比较忙然后没怎么写,写代码途中一些经验总结现在给忘记了。这次的小项目感觉比上次写的思路清楚了点。没有之前第一次写那么逻辑混乱,结构也搞的比之前的要好,添加功能比较容易。学习了之前的经验,操作对象的方法由对象本身提供。不过这次小项目还有不足和不完善之处,有些可以做的功能没有实现,比如游戏存档,这里应该可以用下对象的序列化,还有游戏难度的设置也可以写个文件弄出来。要过年了,到处走亲戚没什么心思写了,这里只能留个尾巴了。

  前言:之前的及时通信项目完成后感觉线程方面和对java的运用还不是很熟悉,在另外一个学习视频中看到一个做坦克游戏的项目视频,便想自己试着做做看,先看视频把游戏规则什么的都搞清楚。然后开始一步一步实现。

主要功能步骤如下

* 1、画出坦克
* 2、我的坦克可以上下移动
* 3、可以发射子弹,子弹连发(或者最多5发)
* 4、当我的坦克击中敌人坦克时,敌人坦克消失(或者爆炸效果)
* 5、我被击中也显示爆炸效果。
* 6、游戏开始和游戏介绍选项

这次游戏界面没有进行设计,直接在一个frame上放个panel。

游戏设计仿mvc 这里不做详细介绍了直接上代码

model包

技术分享
package com.gh.model;
/**
 * 爆炸类
 * 考虑到同时爆炸定义个类
 * @author ganhang
 *
 */
public class Bomb {
    private int x;
    private int y;//坐标
    public boolean islive=true;
    private int time=9;//炸弹生命
    public Bomb() {
        super();
    }
    public Bomb(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }
    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 int getTime() {
        return time;
    }
    //生命递减
    public void livedown(){
        if(time>0){
            time--;
        }else{
            islive=false;
        }
    }
}
Bomb
技术分享
 1 package com.gh.model;
 2 /**
 3  * 子弹类,
 4  * 因为多个子弹同时运动所以需要个内部类做线程
 5  * @author ganhang
 6  *
 7  */
 8 public class Bullet {
 9     private int x;
10     private int y;
11     private int speed;
12     private int drect;
13     public boolean islive=true;
14     public Bullet(int x, int y, int speed, int drect) {
15         super();
16         this.x = x;
17         this.y = y;
18         this.speed = speed;
19         this.drect = drect;
20         new Thread(new BulletThread()).start();
21     }
22     public Bullet() {
23         super();
24     }
25 
26     public int getX() {
27         return x;
28     }
29 
30     public void setX(int x) {
31         this.x = x;
32     }
33 
34     public int getY() {
35         return y;
36     }
37 
38     public void setY(int y) {
39         this.y = y;
40     }
41 
42     class BulletThread implements Runnable {
43         @Override
44         public void run() {
45             while (true) {
46                 try {
47                     Thread.sleep(50);
48                 } catch (Exception e) {
49                     e.printStackTrace();
50                 }
51                 switch (drect) {//判断方向坐标移动
52                 case 0:
53                     y-=speed;
54                     break;
55                 case 1:
56                     x+=speed;
57                     break;
58                 case 2:
59                     y+=speed;
60                     break;
61                 case 3:
62                     x-=speed;
63                     break;
64                 }
65                 if (x < 0 || y < 0 || x > 500 || y > 500||!islive) {
66                     islive=false;
67                     break;
68                 }
69             }
70         }
71     }
72 }
Bullet
技术分享
package com.gh.model;

/**
 * 地图坐标标记
 * 防止敌方坦克重叠
 * @author ganhang
 *
 */
public class Map {
    public int[][] location=new int[500][500];
    public Map() {
        for (int i = 0; i < 500; i++) {
            for (int j = 0; j <500; j++) {
                location[i][j]=0;
            }
        }
    }
}
Map

坦克类,刚才上传发现点问题暂时没改

技术分享
  1 package com.gh.model;
  2 
  3 import java.util.Vector;
  4 /**
  5  * 坦克类
  6  * 每个坦克就是一个线程,
  7  * 这里自己坦克并没有启动线程
  8  * @author ganhang
  9  *
 10  */
 11 public class Tank implements Runnable {
 12     private int x = 0;
 13     private int y = 0;// 坐标
 14     private int drect = 0;// 方向 0向上,1向右,2向下,3向左;
 15     private int type = 0;// 坦克类型 0表示自己
 16     private int speed = 3;// 速度
 17     public Vector<Bullet> mybs = new Vector<Bullet>();// 子弹集
 18     private Bullet myBullet;// 子弹
 19     public boolean islive = true;
 20     private Map map;
 21     public boolean start = true;
 22     public Map getMap() {
 23         return map;
 24     }
 25 
 26     public void setMap(Map map) {
 27         this.map = map;
 28     }
 29 
 30     public Tank(int x, int y, int drect, int type) {
 31         super();
 32         this.x = x;
 33         this.y = y;
 34         this.drect = drect;
 35         this.type = type;
 36     }
 37 
 38     public Tank() {
 39         super();
 40     }
 41 
 42     public Bullet getMyBullet() {
 43         return myBullet;
 44     }
 45 
 46     public int getSpeed() {
 47         return speed;
 48     }
 49 
 50     public void setSpeed(int speed) {
 51         this.speed = speed;
 52     }
 53 
 54     public int getX() {
 55         return x;
 56     }
 57 
 58     public int getDrect() {
 59         return drect;
 60     }
 61 
 62     public void setDrect(int drect) {
 63         this.drect = drect;
 64     }
 65 
 66     public int getType() {
 67         return type;
 68     }
 69 
 70     public void setType(int type) {
 71         this.type = type;
 72     }
 73 
 74     public void setX(int x) {
 75         this.x = x;
 76     }
 77 
 78     public int getY() {
 79         return y;
 80     }
 81 
 82     public void setY(int y) {
 83         this.y = y;
 84     }
 85 
 86     public void moveUp() {
 87         if (y - speed < 0)
 88             y = 0;
 89         else {
 90             y -= speed;
 91              map.location[x][y]=1;//标记此坦克坐标在地图上防止其他坦克过来占用导致重叠
 92 //             这里只标记了坦克坐标那一个点,会有bug,部分坦克还是有重叠现象,
 93 //             这里可以遍历整个坦克坐标(x到x+20,y到y+30)设置标记。
 94 //             for(int i=x;i<x+20;i++){
 95 //                 for (int j = y; j < y+30; j++) {
 96 //                     map.location[x][y]=1;
 97 //                }
 98 //             }
 99         }
100     }
101 
102     public void moveDown() {
103         if (y + speed > 470)
104             y = 470;
105         else {
106             y += speed;
107              map.location[x][y]=1;
108         }
109     }
110 
111     public void moveRight() {
112         if (x + speed > 470)
113             x = 470;
114         else {
115             x += speed;
116              map.location[x][y]=1;
117         }
118     }
119 
120     public void moveLeft() {
121         if (x - speed < 0)
122             x = 0;
123         else {
124             x -= speed;
125              map.location[x][y]=1;
126         }
127     }
128 
129     public void shot() {
130         switch (drect) {
131         case 0:
132             myBullet = new Bullet(x + 10, y, 5, 0);
133             mybs.add(myBullet);
134             break;
135         case 1:
136             myBullet = new Bullet(x + 30, y + 10, 5, 1);
137             mybs.add(myBullet);
138             break;
139         case 2:
140             myBullet = new Bullet(x + 10, y + 30, 5, 2);
141             mybs.add(myBullet);
142             break;
143         case 3:
144             myBullet = new Bullet(x, y + 10, 5, 3);
145             mybs.add(myBullet);
146             break;
147         }
148     }
149 
150     @Override
151     public void run() {
152         while (islive) {
153             if (start) {
154                 int step;
155                 int s;
156                 try {
157                     switch (drect) {
158                     case 0:
159                         step = (int) (Math.random() * 30);
160                         for (int i = 0; i < step; i++) {
161                             moveUp();
162                             if (y <= 0)
163                                 break;// 撞墙跳出循环
164                             if (y >= 30)// 仿数组越界
165                                 if (map.location[x][y - 30] == 1 || map.location[x][y - 20] == 1) {
166                                     map.location[x][y - 30] = 0;//这里没分开判断
167                                     map.location[x][y - 20] = 0;
168                                     break;
169                                 }
170                             Thread.sleep(80);
171                         }
172                         break;
173                     case 1:
174                         step = (int) (Math.random() * 30);
175                         for (int i = 0; i < step; i++) {
176                             moveRight();
177                             if (x >= 500)
178                                 break;
179                             if (x < 470)
180                                 if (map.location[x + 20][y] == 1 || map.location[x + 30][y] == 1) {
181                                     map.location[x + 20][y] = 0;
182                                     map.location[x + 30][y] = 0;
183                                     break;
184                                 }
185                             Thread.sleep(80);
186                         }
187                         break;
188                     case 2:
189                         step = (int) (Math.random() * 30);
190                         for (int i = 0; i < step; i++) {
191                             moveDown();
192                             if (y >= 500)
193                                 break;
194                             if (y < 470)
195                                 if (map.location[x][y + 30] == 1 || map.location[x][y + 20] == 1) {
196                                     map.location[x][y + 30] = 0;
197                                     map.location[x][y + 20] = 0;
198                                     break;
199                                 }
200                             Thread.sleep(80);
201                         }
202                         break;
203                     case 3:
204                         step = (int) (Math.random() * 30);
205                         for (int i = 0; i < step; i++) {
206                             moveLeft();
207                             if (x <= 0)
208                                 break;
209                             if (x >= 30)
210                                 if (map.location[x - 20][y] == 1 || map.location[x - 30][y] == 1) {
211                                     map.location[x - 20][y] = 0;
212                                     map.location[x - 30][y] = 0;
213                                     break;
214                                 }
215                             Thread.sleep(80);
216                         }
217                         break;
218                     }
219                 } catch (InterruptedException e) {
220                     e.printStackTrace();
221                 }
222                 drect = (int) (Math.random() * 4);// 随机方向
223                 s = (int) (Math.random() * 10);
224                 if (s > 8) {
225                     shot();
226                 }
227             }
228         }
229     }
230 }
Tank

view包

技术分享
  1 package com.gh.view;
  2 
  3 import java.awt.Color;
  4 import java.awt.Graphics;
  5 import java.awt.Image;
  6 import java.awt.Toolkit;
  7 import java.util.Vector;
  8 
  9 import javax.swing.JOptionPane;
 10 import javax.swing.JPanel;
 11 
 12 import com.gh.model.Bomb;
 13 import com.gh.model.Bullet;
 14 import com.gh.model.Map;
 15 import com.gh.model.Tank;
 16 
 17 /**
 18  * 游戏显示面板
 19  * 
 20  * @author ganhang
 21  *
 22  */
 23 
 24 public class Mypanel extends JPanel implements Runnable {
 25     public Tank mytank = null;// 我的坦克
 26     Tank ek = null;
 27     Image img;
 28     Vector<Tank> eks = new Vector<Tank>();//地方坦克集
 29     Vector<Bomb> bs = new Vector<Bomb>();//爆炸集合
 30     Map map = new Map();
 31 
 32     public Mypanel() {
 33         mytank = new Tank(200, 200, 0, 0);
 34         mytank.setMap(map);
 35         // 创建敌人坦克
 36         for (int i = 0; i < 17; i++) {
 37             ek = new Tank(i * 30, 10, 2, 1);
 38             eks.add(ek);
 39             ek.setMap(map);
 40             new Thread(ek).start();
 41         }
 42         img = Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("/1.png"));
 43     }
 44 
 45     @Override
 46     public void paint(Graphics g) {
 47         super.paint(g);
 48         // 画背景
 49         g.fillRect(0, 0, 500, 500);
 50         // 画自己的坦克
 51         if (mytank.islive)
 52             drawTank(mytank.getX(), mytank.getY(), g, mytank.getDrect(), mytank.getType());
 53         // 画自己的子弹
 54         for (int i = 0; i < mytank.mybs.size(); i++) {// 循环时删除集合时,不要用foreach,用for
 55             Bullet b = new Bullet();
 56             b = mytank.mybs.get(i);
 57             if (b.islive) {
 58                 g.setColor(Color.white);
 59                 g.fill3DRect(b.getX(), b.getY(), 2, 2, false);
 60             } else
 61                 mytank.mybs.remove(b);
 62         }
 63         // 画敌人坦克
 64         for (int i = 0; i < eks.size(); i++) {
 65             Tank ek = new Tank();
 66             ek = eks.get(i);
 67             if (ek.islive)
 68                 drawEnemyTank(ek.getX(), ek.getY(), ek.getDrect(), g);
 69             // 画敌人子弹
 70             for (int j = 0; j < ek.mybs.size(); j++) {
 71                 Bullet eb = new Bullet();
 72                 eb = ek.mybs.get(j);
 73                 if (eb.islive) {
 74                     g.setColor(Color.green);
 75                     g.fill3DRect(eb.getX(), eb.getY(), 2, 2, false);
 76                 } else
 77                     ek.mybs.remove(eb);
 78             }
 79         }
 80         // 画爆炸,这里有个bug第一次爆炸没有爆炸效果图出来,检查原因是只一闪而过
 81         // 添加休眠好了点,不过影响后面爆炸效果,不明白为什么第一次画得快些
 82         for (int i = 0; i < bs.size(); i++) {
 83             // System.out.println(bs.size());
 84             Bomb bb = bs.get(i);
 85             if (bb.islive) {
 86                 if (bb.getTime() > 6) {
 87                     try {
 88                         Thread.sleep(50);
 89                     } catch (Exception e) {
 90                         e.printStackTrace();
 91                     }
 92                     g.drawImage(img, bb.getX(), bb.getY(), 30, 30, this);
 93                 } else if (bb.getTime() > 3) {
 94                     g.drawImage(img, bb.getX(), bb.getY(), 15, 15, this);
 95                 } else if (bb.getTime() > 0) {
 96                     g.drawImage(img, bb.getX(), bb.getY(), 1, 1, this);
 97                 }
 98             }
 99             bb.livedown();
100             if (bb.getTime() == 0)
101                 bs.remove(bb);
102         }
103     }
104 
105     public boolean isHitEnemy(Bullet b, Tank ek) {
106         if (ek.getDrect() == 0 || ek.getDrect() == 2) {
107             // 坦克竖着时宽20,高30
108             if (b.getX() >= ek.getX() && b.getX() <= ek.getX() + 20 && b.getY() >= ek.getY()
109                     && b.getY() <= ek.getY() + 30) {
110                 b.islive = false;
111                 ek.islive = false;
112 

以上是关于java学习之坦克大战游戏的主要内容,如果未能解决你的问题,请参考以下文章

第16章 坦克大战1

韩顺平循序渐进学Java零基础 项目篇(09161820222628)

韩顺平循序渐进学Java零基础 项目篇(09161820222628)

《Java小游戏实现》:坦克大战(续三)

坦克大战第一节——画出自己的坦克(新手篇)

《Java小游戏实现》:坦克大战(续2)