坦克大战学习笔记-TankWar

最近学习了马士兵老师直播的单机版坦克大战,模仿的做了一个,整理一下思路记录下来,项目git地址:https://github.com/zhuchangli/TankWar/tree/master

视频地址https://www.bilibili.com/video/av5949029 

TankClient类:管理其他类,作为主程序的接口,

  1 package cc.openhome;
  2 
  3 import java.awt.*;
  4 import java.awt.event.KeyAdapter;
  5 import java.awt.event.KeyEvent;
  6 import java.awt.event.WindowAdapter;
  7 import java.awt.event.WindowEvent;
  8 import java.util.ArrayList;
  9 import java.util.List;
 10 
 11 
 12     /**
 13      * @Description: 坦克大战主界面
 14      * @author zili_zl
 15      */
 16 public class TankClient extends Frame{
 17 
 18     /**
 19     * 整个游戏宽度
 20     */
 21     public static final int GAME_WIDTH = 800;
 22     public static final int GAME_HEIGHT = 600;
 23     public final int bknum = 5;
 24 
 25     // 解决画面加载卡顿问题
 26     Image offScreenImage = null;
 27 
 28     Tank mytank = new Tank(500,500,true, Tank.Direction.STOP,this);
 29 
 30     Wall wall = new Wall(300,300,this);
 31 
 32     Blood b = new Blood();
 33     // 存储多发炮弹
 34     List<Missile> missiles = new ArrayList<Missile>();
 35     // 存储爆炸
 36     List<Explode> explodes = new ArrayList<Explode>();
 37     // 存储tank
 38     List<Tank> tanks = new ArrayList<Tank>();
 39 
 40 
 41     /**
 42      * Description
 43      * date: 3:57 PM 1/6/19
 44      * @param  g 画笔显示在屏幕上画出一些对象
 45      * @return void
 46      *
 47      **/
 48 
 49     public void paint(Graphics g){
 50 
 51         // 在屏幕上显示一些文字,有提示的文字
 52         g.drawString("missiles count: "+missiles.size(),10,60);
 53         g.drawString("explodes count: "+explodes.size(),10,80);
 54         g.drawString("tanks count: "+tanks.size(),10,100);
 55         g.drawString("mytank life: "+mytank.getLife(),10,120);
 56 
 57         // 敌方所有坦克报废后重新生成一批坦克
 58         if(tanks.size()<= 0){
 59             for(int i = 0;i < bknum;i++){
 60                 Tank tk = new Tank(50 + (i + 1) * 50,100,false, Tank.Direction.D,this);
 61                 tanks.add(tk);
 62             }
 63         }
 64 
 65         // 拿出所有的子弹
 66         for(int i = 0;i < missiles.size();i++){
 67             Missile m = missiles.get(i);
 68             // 子弹击打敌方
 69             m.hitTanks(tanks);
 70             // 子弹攻击自己
 71             m.hitTank(mytank);
 72 
 73             // 判断子弹是否撞墙
 74             m.collidesWithWall(wall);
 75             // 第一种解决用bool值解决
 76             /*
 77             if(!m.isLive()){
 78                 missiles.remove(m);
 79             }else {
 80                 m.draw(g);
 81             }
 82             */
 83             // 画出子弹
 84             m.draw(g);
 85         }
 86 
 87         // 产生爆炸逐个画出来
 88         for(int i = 0;i < explodes.size();i++){
 89             Explode ex = explodes.get(i);
 90             ex.draw(g);
 91         }
 92         // 拿出生成的tank
 93         for(int i = 0; i < tanks.size();i++){
 94             Tank t = tanks.get(i);
 95             // 坦克撞墙
 96             t.collidesWithWall(wall);
 97             // 同一个tank相遇
 98             t.collidesWithTanks(tanks);
 99             t.draw(g);
100         }
101         // 画出墙来
102         wall.draw(g);
103         // tank吃血补充生命值
104         mytank.eatBlood(b);
105         mytank.draw(g);
106         b.draw(g);
107     }
108     
109     /**
110      * @Description: 使用update方法 实现双缓冲
111      * @param: [g]
112      * @return: void
113      */
114 
115     public void update(Graphics g){
116         // 保证只生成背景色一次
117         if(offScreenImage == null){
118             offScreenImage = this.createImage(GAME_WIDTH,GAME_HEIGHT);
119 
120         }
121         // 幕后图片,调用paint在画布上作画
122         Graphics gOffScreen = offScreenImage.getGraphics();
123 
124         // 背景重刷, 重擦
125         Color c = gOffScreen.getColor();   // 获取当前颜色
126         gOffScreen.setColor(Color.GREEN);  // 设置颜色为颜色绿色
127         gOffScreen.fillRect(0,0,GAME_WIDTH,GAME_HEIGHT);  // 画一个 800×600的方块,颜色黑色
128         gOffScreen.setColor(c);          // 刷完之后把颜色改回去
129         paint(gOffScreen);
130         //一次把图片画的前面去
131         g.drawImage(offScreenImage,0,0,null);
132 
133     }
134     
135     /**
136      * @Description: 做一些初始化工作,只调用一次
137      * @param: []
138      * @return: void
139      */
140     public void lauchFram(){
141 
142         // 在未画之前开始生成tank
143         for(int i = 0;i < 10;i++){
144             Tank tk = new Tank(50 + (i + 1) * 50,100,false, Tank.Direction.D,this);
145             tanks.add(tk);
146         }
147 
148         this.setLocation(400,300);           // 打开画面相对屏幕的坐标位置和屏幕的大小
149         this.setSize(GAME_WIDTH,GAME_HEIGHT);     // 设置游戏画面的长度和高度
150         this.setTitle("TankWar");                 // 游戏界面标题值
151 
152         // 关闭点击叉号起作用的
153         this.addWindowListener(new WindowAdapter() {
154             @Override
155             public void windowClosing(WindowEvent e) {
156                 System.exit(0);
157             }
158         });
159 
160         this.setResizable(false);            // 固定画面大小,不可以改变大小
161         this.setBackground(Color.GREEN);     // 设置草地颜色
162         setVisible(true);                    // 设置可见性
163 
164         // 添加键盘监听
165         this.addKeyListener(new TankClient.KeyMonitor());
166 
167         // 开启一个线程去画一些对象
168         new Thread(new TankClient.PaintThread()).start();
169     }
170 
171     public static void main(String [] args){
172         TankClient tc = new TankClient();
173         tc.lauchFram();
174     }
175 
176     /**
177      * @Description: 重画方法,让线程工作
178      * @param: 
179      * @return: 
180      */
181     private class PaintThread implements Runnable{
182 
183         @Override
184         public void run() {
185             while (true){
186                 repaint();
187                 try{
188                     Thread.sleep(100);
189                 }catch (InterruptedException e){
190                     e.printStackTrace();
191                 }
192             }
193         }
194     }
195     
196     /**
197      * @Description: 监听键盘事件
198      * @param: 
199      * @return: 
200      */
201     private class KeyMonitor extends KeyAdapter {
202         public void keyPressed(KeyEvent e) {
203             mytank.keyPressed(e);
204         }
205 
206         public void keyReleased(KeyEvent e) {
207             mytank.keyReleased(e);
208         }
209     }
210 }
TankClient

Tank类:

  1 package cc.openhome;
  2 
  3 import java.awt.*;
  4 import java.awt.event.KeyEvent;
  5 import java.util.List;
  6 import java.util.Random;
  7 
  8 /**
  9  *
 10  * @Description 坦克类
 11  * @Author zizl_zq
 12  * @Date 1/6/19 3:51 PM
 13  */
 14 public class Tank {
 15 
 16     // tank 生命值
 17     public static final int LIFETIME = 100;
 18     // 移动的速度
 19     public static final int xSpeed = 5;
 20     public static final int ySpeed = 5;
 21 
 22     // tank 的宽度
 23     public static final int WIDTH = 30;
 24     public static final int HEIGHT = 30;
 25 
 26     int x ,y;
 27     private boolean bL = false;
 28     private boolean bR = false;
 29     private boolean bU = false;
 30     private boolean bD = false;
 31     enum Direction {L,LU,U,RU,R,RD,D,LD,STOP};  // 有八个移动方向和停止
 32 
 33     private Direction dir = Direction.STOP;   // tank的方向
 34     private Direction ptdir = Direction.D;    // 炮筒的方向
 35 
 36     private TankClient tkc;
 37 
 38     private int oldx,oldy;
 39 
 40     private boolean good;
 41 
 42     private BloodBar bb = new BloodBar();  // 显示声明值进度条
 43     
 44     /**
 45      * @Description: tank 分敌方和我方tank
 46      * @param: []
 47      * @return: boolean
 48      */
 49     public boolean isGood() {
 50         return good;
 51     }
 52     // 产生随机数 static 只产生一份,是共享变量
 53     private static Random r = new Random();
 54 
 55     public void setLive(boolean live) {
 56         this.live = live;
 57     }
 58     
 59     /**
 60      * @Description: 当tank撞在墙上是需要停下来的,在撞见墙的上一步开始停下来改变方向
 61      * @param: []
 62      * @return: void
 63      */
 64     public void stay(){
 65         x = oldx;
 66         y = oldy;
 67     }
 68 
 69     public boolean isLive() {
 70         return live;
 71     }
 72 
 73     private boolean live = true;
 74     // 产生移动的步长
 75     private int step = r.nextInt(12) + 3;
 76 
 77     // 生命值
 78     private int life = 100;
 79 
 80     public int getLife() {
 81         return life;
 82     }
 83 
 84     public void setLife(int life) {
 85         this.life = life;
 86     }
 87 
 88     public Tank(int x,int y,boolean good){
 89         this.x = x;
 90         this.y = y;
 91         this.good = good;
 92     }
 93     public Tank(int x, int y, boolean good, Direction dir, TankClient tkc){
 94         this(x,y,good);
 95         this.dir = dir;
 96         this.tkc = tkc;
 97     }
 98     
 99     /**
100      * @Description: 画tank
101      * @param: [g]
102      * @return: void
103      */
104     public void draw(Graphics g){
105         if(!live) {
106             if(!good){
107                 tkc.tanks.remove(this);
108             }
109             return;
110         }
111         Color c = g.getColor();         // 保存以前颜色
112         if(good) g.setColor(Color.red); // 玩家tank画成红色
113         else g.setColor(Color.blue);    // 敌方tank画成蓝色
114 
115         // 坐标四个参数,确定图案大小
116         g.fillOval(x,y,WIDTH,HEIGHT);
117         g.setColor(c);
118 
119         if(good) bb.draw(g);
120         // 画炮筒
121         switch (ptdir ){
122             case L:
123                 g.drawLine(x+Tank.WIDTH / 2,y + Tank.HEIGHT / 2,x,y + Tank.HEIGHT / 2);
124                 break;
125             case LU:
126                 g.drawLine(x+Tank.WIDTH / 2,y + Tank.HEIGHT / 2,x,y );
127                 break;
128             case U:
129                 g.drawLine(x+Tank.WIDTH / 2,y + Tank.HEIGHT / 2,x + Tank.WIDTH / 2,y);
130                 break;
131             case RU:
132                 g.drawLine(x+Tank.WIDTH / 2,y + Tank.HEIGHT / 2,x + Tank.WIDTH,y);
133                 break;
134             case R:
135                 g.drawLine(x+Tank.WIDTH / 2,y + Tank.HEIGHT / 2,x + Tank.WIDTH ,y + Tank.HEIGHT /2);
136                 break;
137             case RD:
138                 g.drawLine(x+Tank.WIDTH / 2,y + Tank.HEIGHT / 2,x + Tank.WIDTH,y + Tank.HEIGHT );
139                 break;
140             case D:
141                 g.drawLine(x+Tank.WIDTH / 2,y + Tank.HEIGHT / 2,x + Tank.WIDTH /2,y + Tank.HEIGHT);
142                 break;
143             case LD:
144                 g.drawLine(x+Tank.WIDTH / 2,y + Tank.HEIGHT / 2,x,y + Tank.HEIGHT);
145                 break;
146         }
147         // 移动
148         move();
149     }
150     
151     /**
152      * @Description: 根据方向来确定行进方向
153      * @param: []
154      * @return: void
155      */
156     void move(){
157         this.oldx = x;
158         this.oldy = y;
159         switch (dir ){
160             case L:
161                 x -= xSpeed;
162                 break;
163             case LU:
164                 x -= xSpeed;
165                 y -= ySpeed;
166                 break;
167             case U:
168                 y -= ySpeed;
169                 break;
170             case RU:
171                 x += xSpeed;
172                 y -= ySpeed;
173                 break;
174             case R:
175                 x += xSpeed;
176                 break;
177             case RD:
178                 x += xSpeed;
179                 y += ySpeed;
180                 break;
181             case D:
182                 y += ySpeed;
183                 break;
184             case LD:
185                 x -= xSpeed;
186                 y += ySpeed;
187                 break;
188             case STOP:
189                 break;
190         }
191         // 炮筒方向,解决静止也能发炮
192         if(dir != Direction.STOP){
193             ptdir = dir;
194         }
195 
196         // 限制tank 不能越界
197         if(x < 0) x = 0;
198         if(y < 30) y = 30;
199         if(x + Tank.WIDTH > TankClient.GAME_WIDTH) x = TankClient.GAME_WIDTH - Tank.WIDTH;
200         if(y + Tank.HEIGHT > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT - Tank.HEIGHT;
201 
202         // 敌方tank在八个方向里面随机选择方向,找出下一步移动方向
203         if(!good){
204             // enum 转换为数组
205             Direction [] dirs = Direction.values();
206             if(step == 0){
207                 step = r.nextInt(12) + 3;
208                 int rn = r.nextInt(dirs.length);
209                 dir = dirs[rn];
210             }
211             step--;
212             // 解决子弹发射太快问题 这个条件下发射一枚炮弹
213             if(r.nextInt(40) > 38) fire();
214 
215         }
216 
217     }
218   
219     /**
220      * @Description: 键盘按下事件
221      * @param: [e]
222      * @return: void
223      */
224     public void keyPressed(KeyEvent e) {
225         int key = e.getKeyCode();
226         switch (key){
227             case KeyEvent.VK_LEFT:
228                 bL = true;
229                 break;
230             case KeyEvent.VK_RIGHT:
231                 bR = true;
232                 break;
233             case KeyEvent.VK_UP:
234                 bU = true;
235                 break;
236             case KeyEvent.VK_DOWN:
237                 bD = true;
238                 break;
239         }
240         locateDirection();
241     }
242     
243     /**
244      * @Description: 处理松开按键事件
245      * @param: [e]
246      * @return: void
247      */
248     public void keyReleased(KeyEvent e){
249         int key = e.getKeyCode();
250         switch (key){
251             case KeyEvent.VK_F2:
252                 if(good){
253                     this.live = true;
254                     this.life = LIFETIME;
255                 }
256             case KeyEvent.VK_CONTROL:     // control键发射炮弹 释放按键时发射炮弹控制 发射频率
257                 fire();
258                 break;
259             case KeyEvent.VK_LEFT:
260                 bL = false;
261                 break;
262             case KeyEvent.VK_RIGHT:
263                 bR = false;
264                 break;
265             case KeyEvent.VK_UP:
266                 bU = false;
267                 break;
268             case KeyEvent.VK_DOWN:
269                 bD = false;
270                 break;
271             case KeyEvent.VK_SPACE:
272                 superFire();
273                 break;
274         }
275         locateDirection();
276     }
277     
278     /**
279      * @Description: 根据按下的键盘确定移动方向
280      * @param: []
281      * @return: void
282      */
283     void locateDirection(){
284         if(bL && !bR && !bU && !bD) dir = Direction.L;
285         else if(bL && !bR && bU && !bD) dir = Direction.LU;
286         else if(!bL && !bR && bU && !bD) dir = Direction.U;
287         else if(!bL && bR && bU && !bD) dir = Direction.RU;
288         else if(!bL && bR && !bU && !bD) dir = Direction.R;
289         else if(!bL && bR && !bU && bD) dir = Direction.RD;
290         else if(!bL && !bR && !bU && bD) dir = Direction.D;
291         else if(bL && !bR && !bU && bD) dir = Direction.LD;
292         else if(!bL && !bR && !bU && !bD) dir = Direction.STOP;
293     }
294     
295     /**
296      * @Description: 开火打出一发子弹
297      * @param: []
298      * @return: cc.openhome.Missile
299      */
300     public Missile fire(){
301         int x = this.x + (Tank.WIDTH - Missile.WIDTH) / 2;
302         int y = this.y + (Tank.HEIGHT - Missile.HEIGHT) / 2;
303         Missile m = new Missile(x,y,good,ptdir,this.tkc);
304         tkc.missiles.add(m);
305         return m;
306     }
307     
308     /**
309      * @Description: 朝固定方向打出一颗子弹
310      * @param: [dir]
311      * @return: cc.openhome.Missile
312      */
313     public Missile fire(Direction dir){
314         int x = this.x + (Tank.WIDTH - Missile.WIDTH) / 2;
315         int y = this.y + (Tank.HEIGHT - Missile.HEIGHT) / 2;
316         Missile m = new Missile(x,y,good,dir,this.tkc);
317         tkc.missiles.add(m);
318         return m;
319     }
320     
321     /**
322      * @Description: 获取子弹的方块
323      * @param: []
324      * @return: java.awt.Rectangle
325      */
326     public Rectangle getRect(){
327         return new Rectangle(x,y,WIDTH,HEIGHT);
328     }
329     
330     /**
331      * @Description: tank 撞见墙了作处理
332      * @param: [w]
333      * @return: boolean
334      */
335     public boolean collidesWithWall(Wall w){
336         // 撞见墙 让坦克掉头,或停下来
337         if(this.getRect().intersects(w.getRect())){
338             this.stay();
339             return true;
340         }
341         return false;
342     }
343     
344     /**
345      * @Description: 处理tank遇见tank时
346      * @param: [tanks]
347      * @return: boolean
348      */
349     public boolean collidesWithTanks(List<Tank> tanks){
350         for(int i = 0;i < tanks.size();i++){
351             Tank t = tanks.get(i);
352             if(this != t){
353                 if(this.live && t.isLive() && this.getRect().intersects(t.getRect())){
354                     this.stay();
355                     t.stay();
356                     return true;
357                 }
358             }
359 
360         }
361         return false;
362     }
363     
364     /**
365      * @Description: 超级子弹 一次可以朝多个方向打出子弹
366      * @param: []
367      * @return: void
368      */
369     public void superFire(){
370         Direction [] dirs = Direction.values();
371         for(int i = 0;i < 8;i++){
372             fire(dirs[i]);
373         }
374     }
375     
376     /**
377      * @Description: 成tank的生命值
378      * @param: 
379      * @return: 
380      */
381     private class BloodBar{
382         public void draw(Graphics g){
383             Color c = g.getColor();
384             g.setColor(Color.red);
385             g.drawRect(x,y - 15,WIDTH,10);
386             int w = WIDTH * life / 100;
387             g.fillRect(x,y - 15,w,10);
388             g.setColor(c);
389         }
390     }
391     
392     /**
393      * @Description: 给tank补充生命值
394      * @param: [b]
395      * @return: boolean
396      */
397     public boolean eatBlood(Blood b){
398         // 当前tank活着,还有血,子弹和血块相撞
399         if(this.live && b.isLive() && this.getRect().intersects(b.getRect())){
400             if(life < LIFETIME){
401                 life += 20;
402             }
403             b.setLive(false);
404             return true;
405         }
406         return false;
407     }
408 }
Tank

Missile类:

  1 package cc.openhome;
  2 
  3 import cc.openhome.Explode;
  4 import cc.openhome.Wall;
  5 
  6 import java.awt.*;
  7 import java.util.List;
  8 /**
  9  * @descpition 子弹类
 10  * @author zizl_zq
 11  * @date 1/6/19 3:51 PM
 12  */
 13 public class Missile {
 14 
 15     // 子弹的移动速度
 16     public static final int xSpeed = 10;
 17     public static final int ySpeed = 10;
 18 
 19     // 子弹的宽度,高度
 20     public static final int WIDTH = 10;
 21     public static final int HEIGHT = 10;
 22     private int x,y;
 23     private Tank.Direction dir;
 24 
 25     private boolean good;
 26     private TankClient tc;
 27 
 28 
 29     private boolean live = true;
 30 
 31     public Missile(int x, int y, Tank.Direction dir) {
 32         this.x = x;
 33         this.y = y;
 34         this.dir = dir;
 35     }
 36 
 37     public Missile(int x, int y, Boolean good, Tank.Direction dir, TankClient tc){
 38         this(x,y,dir);
 39         this.good = good;
 40         this.tc = tc;
 41     }
 42 
 43     public boolean isLive() {
 44         return live;
 45     }
 46     public void setLive(boolean live) {
 47         this.live = live;
 48     }
 49 
 50 
 51     public void draw(Graphics g){
 52         if(!live)
 53         {
 54             tc.missiles.remove(this);
 55             return;
 56         }
 57         Color c = g.getColor();
 58         if(!good){
 59             g.setColor(Color.blue);
 60         }
 61         if(good){
 62             g.setColor(Color.black);
 63         }
 64         // 坐标四个参数,确定图案大小
 65         g.fillOval(x,y,WIDTH,HEIGHT);
 66         g.setColor(c);
 67 
 68         // 移动
 69         move();
 70     }
 71 
 72     /**
 73      * @Description 子弹移动方法
 74      * @Param []
 75      * @return void
 76      */
 77     void move(){
 78         switch (dir ){
 79             case L:
 80                 x -= xSpeed;
 81                 break;
 82             case LU:
 83                 x -= xSpeed;
 84                 y -= ySpeed;
 85                 break;
 86             case U:
 87                 y -= ySpeed;
 88                 break;
 89             case RU:
 90                 x += xSpeed;
 91                 y -= ySpeed;
 92                 break;
 93             case R:
 94                 x += xSpeed;
 95                 break;
 96             case RD:
 97                 x += xSpeed;
 98                 y += ySpeed;
 99                 break;
100             case D:
101                 y += ySpeed;
102                 break;
103             case LD:
104                 x -= xSpeed;
105                 y += ySpeed;
106                 break;
107         }
108         // 判断炮弹出界
109         if(x < 0 || y < 0 || x > TankClient.GAME_WIDTH || y > TankClient.GAME_HEIGHT){
110             live = false;
111         }
112     }
113 
114     // 获取子弹的方块
115     public Rectangle getRect(){
116         return new Rectangle(x,y,WIDTH,HEIGHT);
117 
118     }
119     /**
120      * @Description 子弹打击tank
121      * @Param [tk]
122      * @return boolean
123      */
124     public boolean hitTank(Tank tk){
125         // 1,判断子弹是否活着 2,判断是否击中,3,判断坦克是否活着,4,判断是否是一伙的
126         if(this.live && this.getRect().intersects(tk.getRect()) && tk.isLive() && this.good != tk.isGood()){
127             if(tk.isGood()){
128                 tk.setLife(tk.getLife() - 20);
129                 if(tk.getLife() <= 0){
130                     tk.setLive(false);
131                 }
132 
133             }else {
134                 tk.setLive(false);
135             }
136             this.setLive(false);
137             Explode e = new Explode(x,y,tc);
138             tc.explodes.add(e);
139             return true;
140         }
141         return false;
142     }
143 
144     /**
145      * @Description 击打所有的tank
146      * @Param [tanks]
147      * @return boolean
148      */
149     public boolean hitTanks(List<Tank> tanks){
150         for(int i = 0;i < tanks.size();i++){
151             if(hitTank(tanks.get(i))){
152               return true;
153             }
154         }
155         return false;
156     }
157 
158     /**
159      * @Description 子弹撞在墙上
160      * @Param [w]
161      * @return boolean
162      */
163     public boolean collidesWithWall(Wall w){
164         // 子弹撞到墙上,让它消失
165         if(this.getRect().intersects(w.getRect())){
166             setLive(false);
167             return true;
168         }
169         return false;
170     }
171 }
Missile

Blood类:

 1 package cc.openhome;
 2 
 3 import java.awt.*;
 4 
 5 /**
 6  *@ClassName cc.openhome.Blood
 7  *@Description 血块类
 8  *@Author zizl_zq
 9  *@Date 1/6/19 3:51 PM
10  */
11 public class Blood {
12 
13     int x,y,w,h;  // 血块出现的位置,长和宽
14     private int step = 0;
15     TankClient tc;
16     // 血块按照指定的这几个点移动
17     int [][] positions = {
18             {430,440},{430,450},{440,460},{460,470},{470,450},{450,440},{440,430}
19     };
20 
21     /**
22      * @Description 判断血块是否活着,如果被坦克吃掉了就消失
23      * @Param []
24      * @return boolean
25      */
26     public boolean isLive() {
27         return live;
28     }
29 
30     /**
31      * @Description 设置血块的生命
32      * @Param [live]
33      * @return void
34      */
35     public void setLive(boolean live) {
36         this.live = live;
37     }
38 
39     private boolean live = true;
40 
41     public Blood(){
42         x = positions[0][0];
43         y = positions[0][1];
44         w = 10;
45         h = 10;
46     }
47 
48     /**
49      * @Description 按着这个步子在移动的
50      * @Param []
51      * @return void
52      */
53     public void move(){
54 
55         if(step == positions.length){
56             step = 0;
57         }
58         x = positions[step][0];
59         y = positions[step][1];
60         step++;
61     }
62 
63     /**
64      * @Description 画出血块
65      * @Param [g]
66      * @return void
67      */
68     public void draw(Graphics g){
69         if(!live){
70             return;
71         }
72         Color c = g.getColor();
73         g.setColor(Color.magenta);
74         g.fillRect(x,y,w,h);
75         g.setColor(c);
76         move();
77     }
78 
79     /**
80      * @Description 获取自身位置,为碰撞做准备
81      * @Param []
82      * @return java.awt.Rectangle
83      */
84     public Rectangle getRect(){
85         return new Rectangle(x,y,w,h);
86     }
87 }
Blood

Wall 类:

 1 package cc.openhome;
 2 
 3 import java.awt.*;
 4 /**
 5  *@Description 增加游戏好玩度,增加一堵墙
 6  *@Author zizl_zq
 7  *@Date 1/6/19 3:51 PM
 8  */
 9 public class Wall {
10     public static final int WIDTH = 200;
11     public static final int HEIGHT = 10;
12 
13     int x,y;
14     private TankClient tc;
15     public Wall(int x, int y, TankClient tc) {
16         this.x = x;
17         this.y = y;
18         this.tc = tc;
19     }
20 
21     /**
22      * @Description 画出一个tank
23      * @Param [g]
24      * @return void
25      **/
26     public void draw(Graphics g){
27         Color c = g.getColor();
28         g.setColor(Color.black);
29         g.fillRect(x,y,WIDTH,HEIGHT);
30         g.setColor(c);
31     }
32 
33     /**
34      * @Description 获取墙的位置
35      * @Param []
36      * @return java.awt.Rectangle
37      **/
38     public Rectangle getRect(){
39         return new Rectangle(x,y,WIDTH,HEIGHT);
40     }
41 
42 }
Wall

Explode类:

 1 package cc.openhome;
 2 
 3 import java.awt.*;
 4 
 5 /**
 6  *@ClassName cc.openhome.Explode
 7  *@Description 爆炸类
 8  *@Author zizl_zq
 9  *@Date 1/6/19 3:51 PM
10  */
11 public class Explode {
12     int x,y;
13     private boolean live = true;
14     private TankClient tc;
15 
16     int [] diameter = {4,7,12,18,26,32,49,60,30,14,6};
17     int step = 0;
18 
19     public Explode(int x, int y, TankClient tc){
20         this.x = x;
21         this.y = y;
22         this.tc = tc;
23     }
24 
25     public void draw(Graphics g){
26 
27         if(!live) {
28             tc.explodes.remove(this);
29             return;
30         }
31 
32         if(step == diameter.length){
33             live = false;
34             step = 0;
35             return;
36         }
37         Color c = g.getColor();
38         g.setColor(Color.yellow);
39         g.fillOval(x,y,diameter[step],diameter[step]);
40         g.setColor(c);
41 
42         step++;
43     }
44 }
Explode

运行结果:

总结 :

进一步理解了面向对象的思想,处理问题是,首要考虑解决这个问题需要什么对象,这些对象需要有那些属性,用这些属性来解决什么问题。

使用IDEA生成api文档。生成jar包。

新学到的知识点:继承Fram类,paint,lauchFram,uptate方法,里面用于图像处理的几个方法。键盘监听事件,继承KeyAdapter类,keyPressed,KeyReleased方法。键盘可以控制画面上的图像运动。 

不足之处:页面很简陋,没运用多态方法,功能还很单一,可以使用一个标志值来控制重画线程的结束,线程的使用不够熟练。

猜你喜欢

转载自www.cnblogs.com/changlili/p/10230799.html
今日推荐