回答編集履歴

1

見直しキャンペーン中

2023/07/28 15:00

投稿

TN8001
TN8001

スコア9898

test CHANGED
@@ -1,487 +1,244 @@
1
1
  [Java - シューティングゲームで、当たり判定を実装したい|teratail](https://teratail.com/questions/351596)
2
-
3
2
  から1週間だいぶ試行錯誤しておられるようですね。
4
-
5
3
  しかし残念ながら方向が違うような気がします。
6
4
 
7
-
8
-
9
5
  Processingは仕組み上クラス内からグローバル変数にアクセスし放題なのですが、そのせいでスパゲッティコードにもなりやすいです(ありがたい時もあるんですが^^;
10
-
11
6
  例えば`ENEMY`の`x`・`y`が外に出てしまって(`ex`・`ey`)、前回より退化してしまっています。
12
7
 
13
-
14
-
15
8
  > 敵や弾の速度が不安定になってしまっています。
16
9
 
17
-
18
-
19
10
  ちゃんとは追っていませんが、おそらく`ex`・`ey`・`sx`・`sy`のせいです。
20
11
 
21
-
22
-
23
12
  > boolean でhitflagを立てて、衝突範囲内に入った時にtrueを返すような
24
13
 
25
-
26
-
27
14
  敵が複数いるのですから、フラグも複数あるべきでは?
28
-
29
15
  ひとつでもできないことはないでしょうが、ややこしくなるしすでにクラスがあるんですからそっちに定義すればいいと思います。
30
16
 
31
17
 
32
-
33
-
34
-
35
18
  個人的に気になった点を変更しました。
36
-
37
19
  * 命名規則を標準的なものに
38
-
39
20
  Javaではクラス名は通常パスカルケース(例:PascalCase)です。
40
-
41
21
  大文字だけ(例:UPPER_SNAKE_CASE)は定数に使用します。
42
-
43
22
  (まあ「個人で作っているものは好きにつけりゃいいじゃん」と思っていますが、標準のもの(`ArrayList`等)と混じると読みにくいので^^;
44
23
 
45
-
46
-
47
24
  * 同じような意味の`move`・`display`と、`update`・`draw`があるのは気持ち悪いので統一
48
-
49
25
  2つのプログラムを合体させた感じ?(いろいろ参考にされていると思いますが
50
26
 
51
-
52
-
53
27
  * つど`loadImage`してしまっているのは大変無駄
54
-
55
28
  せっかくクラスを作ったのだから、メンバ変数に入れときましょう。
56
29
 
57
-
58
-
59
30
  * `N`や`n`はわかりにくいので、`length`や拡張for文に置き換える
60
-
61
31
  特にグローバル変数は多いほど読みにくくなるので、使わずに済む場合は積極的に減らします。
62
32
 
63
33
 
64
-
65
-
66
-
67
34
  ```Processing
68
-
69
35
  Player player;
70
-
71
- Enemy[] enemys = new Enemy[5];
36
+ Enemy[] enemies = new Enemy[5];
72
-
73
37
  Star[] stars = new Star[100];
74
-
75
38
  ArrayList<Shot> shotList = new ArrayList<Shot>();
76
39
 
77
40
 
78
-
79
-
80
-
81
41
  void setup() {
82
-
83
42
  size(300, 600);
84
-
85
43
  frameRate(30);
86
-
87
44
  rectMode(CENTER);
88
-
89
45
  imageMode(CENTER);
90
-
91
46
  noCursor();
92
47
 
93
-
94
-
95
48
  player = new Player(loadImage("hikou.png"));
96
49
 
97
-
98
-
99
50
  PImage png = loadImage("enemy.png");
100
-
101
- for (int i = 0; i < enemys.length; i++) {
51
+ for (int i = 0; i < enemies.length; i++) {
102
-
103
- enemys[i] = new Enemy(png);
52
+ enemies[i] = new Enemy(png);
104
-
105
- }
53
+ }
106
-
107
-
108
54
 
109
55
  for (int i = 0; i < stars.length; i++) {
110
-
111
56
  stars[i] = new Star();
112
-
113
- }
57
+ }
114
-
115
- }
58
+ }
116
-
117
-
118
59
 
119
60
  void draw() {
120
-
121
61
  background(0);
122
62
 
123
-
124
-
125
63
  player.update();
126
64
 
127
-
128
-
129
65
  for (Star star : stars) {
130
-
131
66
  star.update();
132
-
133
67
  star.draw();
134
-
135
- }
68
+ }
136
-
137
-
138
69
 
139
70
  boolean gameOver = false;
140
-
141
- for (Enemy enemy : enemys) {
71
+ for (Enemy enemy : enemies) {
142
-
143
72
  enemy.update();
144
73
 
145
-
146
-
147
74
  // 弾に当たっているか確認のため全弾ループ
148
-
149
75
  for (int i = shotList.size () - 1; i >= 0; i--) {
150
-
151
76
  Shot shot = shotList.get(i);
152
-
153
77
  if (enemy.isHit(shot.x, shot.y)) { // shotの座標と接触していれば...
154
-
155
78
  enemy.isDead = true; // フラグで管理するならこう
156
-
157
79
  //enemy.init(); // でも敵がいなくなってしまうので単に初期化でいい気が^^;
158
-
159
80
  shotList.remove(i);
160
-
161
81
  println("hit");
162
-
163
82
  }
164
-
165
- }
83
+ }
166
-
167
-
168
84
 
169
85
  // ついでに自機との接触も
170
-
171
86
  if (enemy.isHit(player.x, player.y)) { // playerの座標と接触していれば...
172
-
173
87
  gameOver = true;
174
-
175
- }
88
+ }
176
-
177
-
178
89
 
179
90
  enemy.draw();
180
-
181
- }
91
+ }
182
-
183
-
184
92
 
185
93
  for (int i = shotList.size () - 1; i >= 0; i--) {
186
-
187
94
  Shot shot = shotList.get(i);
188
-
189
95
  shot.update();
190
-
191
96
  if (shot.isAlive()) {
192
-
193
97
  shot.draw();
194
-
195
98
  } else {
196
-
197
99
  shotList.remove(i);
198
-
199
- }
100
+ }
200
-
201
- }
101
+ }
202
-
203
-
204
102
 
205
103
  player.draw();
206
104
 
207
-
208
-
209
105
  if (gameOver) {
210
-
211
106
  fill(255);
212
-
213
107
  textSize(40);
214
-
215
108
  textAlign(CENTER, CENTER);
216
-
217
109
  text("GAME OVER", width / 2, height / 2);
218
-
219
110
  noLoop();
220
-
221
- }
111
+ }
222
-
223
- }
112
+ }
224
-
225
-
226
113
 
227
114
  void mousePressed() {
228
-
229
115
  shotList.add(new Shot(player.x, player.y));
230
-
231
- }
116
+ }
232
-
233
-
234
-
235
117
 
236
118
 
237
119
  class Player {
238
-
239
120
  PImage image;
240
-
241
- float x;
121
+ float x;
242
-
243
- float y;
122
+ float y;
244
-
245
-
246
123
 
247
124
  Player(PImage _image) {
248
-
249
125
  image = _image;
250
-
251
- }
126
+ }
252
-
253
-
254
-
127
+
255
- void update() {
128
+ void update() {
256
-
257
129
  x = mouseX;
258
-
259
130
  y = mouseY;
260
-
261
- }
131
+ }
262
-
263
-
264
-
132
+
265
- void draw() {
133
+ void draw() {
266
-
267
134
  image(image, x, y);
268
-
269
- }
135
+ }
270
-
271
- }
136
+ }
272
-
273
-
274
137
 
275
138
  class Enemy {
276
-
277
139
  PImage image;
278
-
279
- float x;
140
+ float x;
280
-
281
- float y;
141
+ float y;
282
-
283
142
  float vy = 5;
284
-
285
143
  float size = 40;
286
-
287
144
  boolean isDead; // フラグを作るならココ
288
145
 
289
-
290
-
291
146
  Enemy(PImage _image) {
292
-
293
147
  image = _image;
294
-
295
148
  init();
296
-
297
149
  y = random(-2 * height, -height);
298
-
299
- }
150
+ }
300
-
301
-
302
151
 
303
152
  void init() {
304
-
305
153
  isDead = false;
306
-
307
154
  y = random(-20);
308
-
309
155
  x = random(20, width - 20);
310
-
311
- }
156
+ }
312
-
313
-
314
-
157
+
315
- void draw() {
158
+ void draw() {
316
-
317
159
  if (isDead) return;
318
160
 
319
-
320
-
321
161
  image(image, x, y);
322
-
323
- }
162
+ }
324
-
325
-
326
-
163
+
327
- void update() {
164
+ void update() {
328
-
329
165
  if (isDead) return;
330
166
 
331
-
332
-
333
167
  y += vy;
334
-
335
168
  if (height + size < y) {
336
-
337
169
  init();
338
-
339
- }
170
+ }
340
-
341
- }
171
+ }
342
-
343
-
344
172
 
345
173
  // Shot#isAliveと同じような感じで指定座標(_x・_y)との接触判定
346
-
347
174
  boolean isHit(float _x, float _y) {
348
-
349
175
  if (isDead) return false;
350
176
 
351
-
352
-
353
177
  float r = size / 2;
354
-
355
178
  return x - r < _x && _x < x + r && y - r < _y && _y < y + r;
356
-
357
- }
179
+ }
358
-
359
- }
180
+ }
360
-
361
-
362
181
 
363
182
  class Star {
364
-
365
- float x;
183
+ float x;
366
-
367
- float y;
184
+ float y;
368
-
369
185
  float vy;
370
-
371
186
  float len;
372
187
 
373
-
374
-
375
188
  Star() {
376
-
377
189
  init();
378
-
379
190
  y = random(-height, height);
380
-
381
- }
191
+ }
382
-
383
-
384
192
 
385
193
  void init() {
386
-
387
194
  y = random(-2 * height, -1);
388
-
389
195
  x = random(0, width);
390
-
391
196
  vy = random(10, 18);
392
-
393
197
  len = random(15, 25);
394
-
395
- }
198
+ }
396
-
397
-
398
-
199
+
399
- void update() {
200
+ void update() {
400
-
401
201
  y += vy;
402
-
403
202
  if (height < y + len) {
404
-
405
203
  init();
406
-
407
- }
204
+ }
408
-
409
- }
205
+ }
410
-
411
-
412
-
206
+
413
- void draw() {
207
+ void draw() {
414
-
415
208
  stroke(200);
416
-
417
209
  line(x, y, x, y + len);
418
-
419
- }
210
+ }
420
-
421
- }
211
+ }
422
-
423
-
424
212
 
425
213
  class Shot {
426
-
427
- float x;
214
+ float x;
428
-
429
- float y;
215
+ float y;
430
-
431
216
  float vy = -15;
432
-
433
217
  float size = 6;
434
218
 
435
-
436
-
437
219
  Shot(float _x, float _y) {
438
-
439
220
  x = _x;
440
-
441
221
  y = _y;
442
-
443
- }
222
+ }
444
-
445
-
446
-
223
+
447
- void update() {
224
+ void update() {
448
-
449
225
  y += vy;
450
-
451
- }
226
+ }
452
-
453
-
454
-
227
+
455
- void draw() {
228
+ void draw() {
456
-
457
229
  stroke(0);
458
-
459
230
  fill(255, 0, 0);
460
-
461
231
  rect(x, y, size, size);
462
-
463
- }
232
+ }
464
-
465
-
466
233
 
467
234
  boolean isAlive() {
468
-
469
235
  float r = size / 2;
470
-
471
236
  return 0 <= x + r && x - r <= width && 0 <= y + r && y - r <= height;
472
-
473
- }
237
+ }
474
-
475
- }
238
+ }
476
-
477
239
  ```
478
240
 
479
-
480
-
481
241
  ---
482
242
 
483
-
484
-
485
243
  別にこれが正解というわけではありません。
486
-
487
244
  10人いたら10通りのコードになるでしょうし、あまりいじらないようにしたので「ちょっとどうかな?」という部分もあります。