利用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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Image; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; public class TankClient extends JFrame{ /** * @param args */ /*游戲大小*/ public static final int GAME_WIDTH = 800; //界面寬 public static final int GAME_HEIGTH = 600; //界面高 Tank myTank = new Tank(500,400,true,Color.red,Tank.Direction.STOP, this);//我方坦克類 List<Missile> missiles = new ArrayList<Missile>();//子彈的集合 List<Explode> explode = new ArrayList<Explode>();//爆炸集合 List<Tank> tanks = new ArrayList<Tank>(); //坦克集合 Wall wall1 = new Wall(150,200,20,300,this); //墻1 Wall wall2 = new Wall(250,500,300,20,this); //墻2 Wall wall3 = new Wall(650,200,20,300,this); //墻2 Wall wall4 = new Wall(250,300,300,20,this); //墻2 Wall wb = new Wall(750,550,40,40,this); //墻2 Blood b = new Blood(); //血類 public static void main(String[] args) { // TODO Auto-generated method stub TankClient tc=new TankClient(); tc.lauchFrame(); } private void lauchFrame() { // TODO Auto-generated method stub for (int i = 0; i < 10; i++){ tanks.add(new Tank(50+40*(i+1), 50, false,Color.blue,Tank.Direction.D, this)); } this.setLocation(100, 100); //窗口初始坐標點 this.setSize(GAME_WIDTH, GAME_HEIGTH); //窗口初始大小 this.setTitle("TankWar"); //窗口名稱 /*窗口監聽*/ this.addWindowListener(new WindowAdapter() { @Override /*點退出叉之后運行*/ public void windowClosing(WindowEvent e) { // TODO Auto-generated method stub System.exit(0); //退出 } }); this.addKeyListener(new KeyMoniton()); //設置鍵盤監聽 this.setVisible(true); //設置窗口顯現 this.setResizable(false); //設置窗口不可改變大小 this.getContentPane().setBackground(Color.green); //設置窗口前景色為綠色 new Thread(new PaintThread()).start(); //開始運行PaintThread類run } @Override public void paint(Graphics g) { // TODO Auto-generated method stub //Graphics為畫筆類 super.paint(g); myTank.draw(g); wall1.draw(g); wall2.draw(g); wall3.draw(g); wall4.draw(g); wb.draw(g); b.draw(g); myTank.eatBlood(b); myTank.hitWall(wall1); myTank.hitWall(wall2); myTank.hitWall(wall3); myTank.hitWall(wall4); /*循環子彈集合*/ for (int i = 0; i < missiles.size(); i++){ Missile m = missiles.get(i); //獲取當前子彈 m.hitTanks(tanks); //自己子彈打死敵方坦克 m.hitWall(wall1); //子彈與墻 m.hitWall(wall2); m.hitWall(wall3); m.hitWall(wall4); m.hitTank(myTank);//敵人子彈打擊自己的坦克 m.draw(g); //畫子彈 } for (int i = 0; i < explode.size(); i++){ explode.get(i).draw(g); //畫爆炸 } for (int i = 0; i < tanks.size(); i++){ Tank t = tanks.get(i); t.draw(g); //畫敵方坦克 t.hitTanks(tanks); t.hitWall(wall1); //坦克與墻 t.hitWall(wall2); t.hitWall(wall3); t.hitWall(wall4); } //g.setFont(new Font("宋體",Font.BOLD,20)); g.drawString("missiles count:"+missiles.size(), 10, 50);//顯示 g.drawString("explode count:"+explode.size(), 10, 80);//顯示 g.drawString("tanks count:"+tanks.size(),10, 110); g.drawString("myTank Life:"+myTank.getLife(), 10, 130); g.drawString("回血:", 750, 540); g.drawString("方向鍵移動方向;E:釋放移動血快", 10, 590); g.drawString("z:發射東風-31;a:發射東風-41;", 10, 570); g.drawString("F2:復活;F3:敵方復活(對多20)", 10, 550); g.drawString("R:位置還原;Q:血量加滿", 10, 530); } @Override /*repaint-〉update->paint*/ public void update(Graphics g) { // TODO Auto-generated method stub super.update(g); if(OffScrennImage == null) OffScrennImage = this.createImage(GAME_WIDTH, GAME_HEIGTH); Graphics goffscrenn = OffScrennImage.getGraphics(); //設置一個內存畫筆顏色為前景圖片顏色 Color c = goffscrenn.getColor(); //還是先保存前景顏色 goffscrenn.setColor(Color.green); //設置內存畫筆顏色為綠色 goffscrenn.fillRect(0, 0, GAME_WIDTH, GAME_HEIGTH); //畫成圖片,大小為游戲大小 goffscrenn.setColor(c); //還原顏色 g.drawImage(OffScrennImage, 0, 0, null); //在界面畫出保存的圖片 paint(goffscrenn); //把內存畫筆調用給paint } private class PaintThread implements Runnable{ @Override public void run() { // TODO Auto-generated method stub while(true){ repaint(); //運行順序repaint->update->paint try{ Thread.sleep(50); //每隔50毫秒刷新畫面一次 }catch(Exception e){ e.printStackTrace(); } } } } /*鍵盤響應*/ private class KeyMoniton extends KeyAdapter{ /*摁下鍵盤響應*/ @Override public void keyPressed(KeyEvent e) { // TODO Auto-generated method stub super.keyPressed(e); myTank.KeyPressed(e); } /*抬起鍵盤響應*/ @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub super .keyReleased(e); myTank.keyReleased(e); } } } |
Tank.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
|
import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.util.List; import java.util.Random; import javax.swing.ImageIcon; public class Tank { /*坦克本身數據*/ int x, y;//坦克坐標 private int oldX, oldY; //坦克上一步坐標 public static final int Whith = 30; //坦克寬 public static final int Higth = 30; //坦克高 public static final int XSPEED = 5; //橫向移動速度 public static final int YSPEED = 5; //縱向移動速度 private Color color; //坦克顏色 private boolean bL=false, bU=false, bR=false, bD=false; //四個方向控制值 enum Direction {L, LU, U, RU, R, RD, D, LD, STOP}; //由四個方向值合成八個方向的移動 private Direction dir = Direction.STOP; //出場方向 private Direction ptDir = Direction.D; //炮筒初始方向 private boolean good; //判斷坦克的陣營 private boolean live = true; //判斷坦克是否存活 private static Random r = new Random();//設置一個隨機值變量 private static int step = r.nextInt(12)+3; //敵方坦克隨機移動步驟3-14步 private int Life = 100; //血量 private BloodBar bb = new BloodBar(); //血塊類 // ImageIcon icon = new ImageIcon("res\\myTank.jpg"); // ImageIcon icon2 = new ImageIcon("res\\enemyTank.jpg"); // Image image = icon.getImage(); // Image image2 = icon2.getImage(); private TankClient tc; //主類權限 public Tank(int x, int y, boolean good, Color color) { super(); this.x = x; this.y = y; this.color = color; this.good = good; } public Tank(int x, int y, boolean good,Color color,Direction dir,TankClient tc){ this(x,y,good,color); this.dir = dir; this.tc = tc; } /*獲取坦克生命值*/ public int getLife() { return Life; } /*設置坦克生命值*/ public void setLife(int Life) { this.Life = Life; } /*獲取坦克陣營*/ public boolean isGood() { return good; } /*設置坦克陣營*/ public void setGood(boolean good) { this.good = good; } /*獲取坦克存活狀態*/ public boolean isLive() { return live; } /*設置坦克存活狀態*/ public void setLive(boolean live) { this.live = live; } /*畫坦克*/ public void draw(Graphics g){ if(!live){ if(!good){ tc.tanks.remove(this); //敵方坦克死亡時在集合中刪除 //tc.tanks.add(new Tank(r.nextInt(700),r.nextInt(500),false,Color.blue,Direction.D,this.tc)); } return; } /*先保存之前的畫筆顏色,畫完之后再還原畫筆顏色*/ Color c = g.getColor(); //獲取當前畫筆顏色 g.setColor(color); //設置畫筆顏色為紅色 /*畫坦克*/ g.fillOval(x, y, Whith, Higth); /*兩種方法繪制敵我坦克,運用之前加入的圖片或者顏色區分*/ // if(good) // g.drawImage(image, x, y,Whith,Higth,null); // else // g.drawImage(image2, x, y, Whith, Higth, null); if(good) bb.draw(g); //我方坦克畫血條 g.setColor(Color.black); /*通過炮筒方向畫出炮筒*/ switch(ptDir){ case L: g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x, y+Tank.Higth/2); break; case LU: g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x, y); break; case U: g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith/2, y); break; case RU: g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith, y); break; case R: g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith, y+Tank.Higth/2); break; case RD: g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith, y+Tank.Higth); break; case D: g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x+Tank.Whith/2, y+Tank.Higth); break; case LD: g.drawLine(x+Tank.Whith/2, y+Tank.Higth/2, x, y+Tank.Higth); break; } g.setColor(c); //還原畫筆顏色 move();//移動 } /*鍵盤監聽;摁鍵*/ public void KeyPressed(KeyEvent e){ int key = e.getKeyCode(); //將鍵盤監聽到的摁鍵以整數保存 /*鍵盤移動坦克*/ switch(key){ /*移動摁鍵*/ case KeyEvent.VK_UP: bU=true; break; case KeyEvent.VK_DOWN: bD=true; break; case KeyEvent.VK_RIGHT: bR=true; break; case KeyEvent.VK_LEFT: bL=true; break; } locateDirection(); } /*鍵盤監聽;抬起鍵*/ public void keyReleased(KeyEvent e){ int key = e.getKeyCode(); //將鍵盤監聽到的摁鍵以整數保存 /*鍵盤移動坦克*/ switch(key){ case KeyEvent.VK_UP: bU=false; break; case KeyEvent.VK_DOWN: bD=false; break; case KeyEvent.VK_RIGHT: bR=false; break; case KeyEvent.VK_LEFT: bL=false; break; case KeyEvent.VK_Z: //單發子彈 if(live) fire(); break; case KeyEvent.VK_F2: //我方復活 if(!this.live){ this.live=true; this.setLife(100); } break; case KeyEvent.VK_F3: //敵方復活 fuhuo(); break; case KeyEvent.VK_A: //無敵導彈 superFire(); break; case KeyEvent.VK_Q: //回血 if(this.live) this.Life = 100; break; case KeyEvent.VK_E: //釋放血塊 tc.b.fh(); break; /*還原位置鍵*/ case KeyEvent.VK_R: x = 50; y = 50; break; } locateDirection(); //合成方向 } /*合成移動方向*/ void locateDirection(){ if(bL&&!bU&&!bR&&!bD) dir=Direction.L; else if(bL&&bU&&!bR&&!bD) dir=Direction.LU; else if(!bL&&bU&&!bR&&!bD) dir=Direction.U; else if(!bL&&bU&&bR&&!bD) dir=Direction.RU; else if(!bL&&!bU&&bR&&!bD) dir=Direction.R; else if(!bL&&!bU&&bR&&bD) dir=Direction.RD; else if(!bL&&!bU&&!bR&&bD) dir=Direction.D; else if(bL&&!bU&&!bR&&bD) dir=Direction.LD; else if(!bL&&!bU&&!bR&&!bD) dir=Direction.STOP; } void move(){ //移動 /*記錄上一步的位置*/ oldX = x; oldY = y; switch(dir){ case L: x-=XSPEED; break; case LU: x-=XSPEED; y-=YSPEED; break; case U: y-=YSPEED; break; case RU: x+=XSPEED; y-=YSPEED; break; case R: x+=XSPEED; break; case RD: x+=XSPEED; y+=YSPEED; break; case D: y+=YSPEED; break; case LD: x-=XSPEED; y+=YSPEED; break; case STOP: break; } /*判斷坦克移動越界情況(游戲邊界)*/ if(x < 5) x = 5; if(y < 25) y = 25; if(x+Whith > tc.GAME_WIDTH-5) x = tc.GAME_WIDTH-Whith-5; if(y+Higth > tc.GAME_HEIGTH-5) y = tc.GAME_HEIGTH-Higth-5; if(dir != Direction.STOP) //如果坦克不靜止就改變炮筒方向 ptDir = dir; /*敵方坦克自動移動*/ if(!good){ Direction[] dirs = Direction.values(); //將方向變量設為數組 if(step == 0){ step = r.nextInt(12)+3; //隨機移動步驟 int randomNumber = r.nextInt(dirs.length); //隨機移動方向 dir = dirs[randomNumber]; } step--; if(r.nextInt(40)>30) this.fire(); //隨機是否發射炮彈 } } /*敵方坦克復活*/ public void fuhuo(){ if(tc.tanks.size() < 20) while(true){ int x = r.nextInt(700); int y = r.nextInt(500); Tank t = new Tank(x,y,false,Color.blue,Direction.D,tc); /*如果坦克與墻重合則重新隨機位置直到不重合為止才將新坦克加入集合*/ if(t.getRect().intersects(tc.wall1.getRect())||t.getRect().intersects(tc.wall2.getRect()) ||t.getRect().intersects(tc.wall3.getRect()) ||t.getRect().intersects(tc.wall4.getRect())){ continue; } else{ tc.tanks.add(t); break; } } } /*子彈發射*/ public void fire(){ int x = this.x + Whith/2 - Missile.Whith/2; //控制子彈方向為坦克中間 int y = this.y + Higth/2 - Missile.Higth/2; tc.missiles.add(new Missile(ptDir,color,x,y,good,tc)); //創建新的子彈類加入到子彈集合中 } /*碰撞;獲取坦克的范圍*/ public Rectangle getRect(){ return new Rectangle(x,y,Whith,Higth); } /*回執上一步位置*/ private void stay(){ x = oldX; y = oldY; } /*如果撞墻,調用stay方法,返回上一步位置*/ public boolean hitWall(Wall w){ if(this.live&&this.getRect().intersects(w.getRect())){ this.stay(); return true; } return false; } /*坦克互相撞擊事件*/ public boolean hitTanks(List<Tank> tanks){ for(int i=0;i<tanks.size();i++){ Tank t=tanks.get(i); if(this!=t){//自己與自己不可相撞 /*如果相撞返回上一步位置*/ if(this.live&&t.isLive()&&this.getRect().intersects(t.getRect())){ this.stay(); t.stay(); return true; } } } return false; } /*帶開火方向的發射函數*/ public Missile fire(Direction dir){ if(!live) return null; int x=this.x+Whith/2-Missile.Whith/2; int y=this.y+Higth/2-Missile.Higth/2; Missile m=new Missile(dir,color,x, y,good, this.tc); tc.missiles.add(m); return m; } /*超級射擊導彈*/ private void superFire(){ Direction[] dirs=Direction.values(); for(int i=0;i<8;i++){ fire(dirs[i]);//循環調用八個方向 } } /*新增血塊類*/ private class BloodBar{ /*畫血條*/ public void draw(Graphics g){ Color c=g.getColor(); g.setColor(Color.red); g.drawRect(x, y-10, Whith, 10); int w=Whith*Life/100; g.fillRect(x, y-10, w, 10); g.setColor(c); } } /*吃血方法*/ public boolean eatBlood(Blood b){ if ( this .live&&b.isLive()&& this .isGood()&& this .getRect().intersects(b.getRect())){ this .setLife( 100 ); b.setLive( false ); return true ; } if ( this .getRect().intersects(tc.wb.getRect())) this .Life = 100 ; return false ; } } |
Missile.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.util.List; public class Missile { /*子彈本身數據*/ Tank.Direction dir; //子彈方向 Color c; //子彈顏色 int x,y; //子彈位置 public static final int XSPEED = 15; //橫向移動速度 public static final int YSPEED = 15; //縱向移動速度 public static final int Whith = 10; //子彈寬 public static final int Higth = 10; //子彈高 private boolean live = true; //判斷子彈的存活 private boolean good; //判斷子彈和陣營 private TankClient tc;//主類權限 public Missile(Tank.Direction dir,Color c, int x, int y) { super(); this.dir = dir; this.x = x; this.y = y; this.c = c; } public Missile(Tank.Direction dir,Color c, int x, int y,boolean good,TankClient tc){ this(dir,c,x,y); this.good = good; this.tc = tc; } /*獲取子彈的存活*/ public boolean isLive() { return live; } /*設置子彈的存活*/ public void setLive(boolean live) { this.live = live; } public void draw(Graphics g){ /*如果子彈死亡狀態將這個子彈在子彈集合中刪除*/ if(!live){ tc.missiles.remove(this); //集合中刪除 return; } /*先保存之前的畫筆顏色,畫完之后再還原畫筆顏色*/ Color d = g.getColor(); //獲取當前畫筆顏色 g.setColor(c); //設置畫筆顏色為紅色 /*畫子彈*/ g.fillOval(x, y, Whith, Higth); g.setColor(d); //還原畫筆顏色 move(); //移動 } public void move(){ /*判斷移動方向移動坦克位置*/ switch(dir){ case L: x-=XSPEED; break; case LU: x-=XSPEED; y-=YSPEED; break; case U: y-=YSPEED; break; case RU: x+=XSPEED; y-=YSPEED; break; case R: x+=XSPEED; break; case RD: x+=XSPEED; y+=YSPEED; break; case D: y+=YSPEED; break; case LD: x-=XSPEED; y+=YSPEED; break; case STOP: break; } /*判斷子彈的越界情況;出界則子彈死亡,在子彈集合中刪去*/ if(x<0||y<0||x>TankClient.GAME_WIDTH||y>TankClient.GAME_HEIGTH) live = false; } /*碰撞;獲取子彈的范圍*/ public Rectangle getRect(){ return new Rectangle(x,y,Whith,Higth); } /*子彈與坦克碰撞過程*/ public boolean hitTank(Tank t){ /*如果子彈與坦克在同一范圍則子彈和坦克同時死亡;且子彈只能殺死對方坦克*/ if(this.live&&this.getRect().intersects(t.getRect())&&t.isLive()&&this.good!=t.isGood()){ if(t.isGood()){ //好坦克 /*我方坦克子彈射中會減少生命值,生命值0的時候會死亡*/ t.setLife(t.getLife()-20); if(t.getLife()<=0) t.setLive(false); }else{ //壞坦克 t.setLive(false);//死亡 } this.live=false;//子彈死亡 tc.explode.add(new Explode(x, y, tc));//新建爆炸加入集合 return true; } return false; } /*循環坦克集合分別進行判斷子彈碰撞*/ public boolean hitTanks(List<Tank> tanks){ for (int i = 0; i < tanks.size(); i++){ if(hitTank(tanks.get(i))) return true; } return false; } /*子彈與墻的碰撞過程*/ public boolean hitWall(Wall w){ /*如果子彈與墻的范圍重合子彈死亡*/ if ( this .live&& this .getRect().intersects(w.getRect())){ this .live= false ; //子彈死亡 return true ; } return false ; } } |
Wall.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import java.awt.Graphics; import java.awt.Rectangle; public class Wall { /*墻數據*/ int x,y,w,h; //位置和寬高 private TankClient tc; //主類權限 public Wall(int x, int y, int w, int h, TankClient tc) { super(); this.x = x; this.y = y; this.w = w; this.h = h; this.tc = tc; } /*獲取墻的范圍*/ public Rectangle getRect(){ return new Rectangle(x,y,w,h); } /*畫墻*/ public void draw(Graphics g){ g.fillRect(x, y, w, h); } } |
Explode.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.util.Random; public class Blood { /*血塊數據*/ int x, y, w, h;//血塊位置和大小 private TankClient tc; //主類權限 private boolean live=true;//血塊的存活 private static Random r = new Random();//設置一個隨機值變量 /*獲取血塊的存活狀態*/ public boolean isLive() { return live; } /*設置血塊的存活狀態*/ public void setLive(boolean live) { this.live = live; } /*血塊位置初值隨機一個數值*/ public Blood(){ x=r.nextInt(600)+100; y=r.nextInt(400)+100; w=h=15; } /*畫血塊*/ public void draw(Graphics g){ if(!live) return; Color c=g.getColor(); g.setColor(Color.magenta); g.fillRect(x, y, w, h); g.setColor(c); } /*釋放血塊*/ public void fh(){ if(!live){ x = r.nextInt(600)+100; y = r.nextInt(400)+100; live = true; } } /*獲取血塊范圍*/ public Rectangle getRect(){ return new Rectangle(x, y, w, h); } } |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。