teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

6

Nキーロールオーバーについて追記

2018/03/05 09:44

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -21,9 +21,15 @@
21
21
 
22
22
  > 自機を左上に移動してるときだけ弾が発射されないのですが、これはなぜでしょうか?
23
23
 
24
+ ■条件
25
+ ・自機を左上方向に移動中
26
+ ・ショットキーを押下
27
+
24
- キーボード左上キーを押下して移動時に弾が発射されないという点でしたね。
28
+ 時にショットキーを押下して弾が発射されないという点でね。
25
- 不具合ではないでしょうか、以下のprint文で正しい値が取れているのかdebugしてみてはどうでしょうか。
29
+ 不具合ではないでしょうか、以下のprint文で各処理で正しい値が取れているのかdebugしてみてはどうでしょうか。
26
30
  少し調査してみた限りでは、event.key == K_SPACE:のスペース押下イベントが発生してませんでした。
31
+ [キーボードの同時押しの制限(Nキーロールオーバー)に引っかかった可能性もあります](http://wikiwiki.jp/fpag/?%A5%AD%A1%BC%A5%DC%A1%BC%A5%C9%A4%CE%C6%B1%BB%FE%B2%A1%A4%B7%A4%CB%A4%C4%A4%A4%A4%C6)
32
+
27
33
  あとはがんばってくださいな。
28
34
 
29
35
  ```Python

5

質問を読み違えていたので訂正。

2018/03/05 09:44

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -21,18 +21,16 @@
21
21
 
22
22
  > 自機を左上に移動してるときだけ弾が発射されないのですが、これはなぜでしょうか?
23
23
 
24
- こちらはバグですねご指摘ありがとうございます。
25
- Bullet#is_destroyで弾生存判定をしているのすが、
24
+ キーボード左上キー押下して移動時に弾が発射されなという点したね。
26
- 自機サイズを計算するのを忘れそのため、すぐに弾が削除対象になります。
25
+ 不具合ではないでしょうか、以下print文で正しい値が取れているのかdebugしみてはどうでょうか
26
+ 少し調査してみた限りでは、event.key == K_SPACE:のスペース押下イベントが発生してませんでした。
27
+ あとはがんばってくださいな。
27
28
 
29
+ ```Python
28
- 対応方法は2案あって、
30
+ import time
29
- 0. Player#moveにて自機の移動範囲を制限する。
30
- 0. Bullet#is_destroyで自機のサイズを計算に含める。
31
+ print('Done' + str(time.perf_counter()))
32
+ ```
31
33
 
32
- 案2で実装します。
33
- 質問文に自機の画像が無いため正確な自機のサイズはわかりませんが、
34
- Player#moveを参考に30*30としておきます。
35
-
36
34
  以下はサンプルコードです。
37
35
 
38
36
  ---

4

空白行を削除!

2018/03/05 09:26

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -132,7 +132,6 @@
132
132
  enemy1.draw(screen)
133
133
  # 5,bullet_listの内容をfor in ループで回す。
134
134
  for bullet in bullet_list:
135
-
136
135
  bullet.move()
137
136
  bullet.draw()
138
137
  #リストからスクリーン範囲外のbulletをクリーンアップ

3

Bullet#is_destroyを自機のサイズを計算するように変更、bullet説明変数を追加

2018/03/05 06:57

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -7,8 +7,36 @@
7
7
  0. `class Bullet`を新規追加
8
8
  0. 変数:`bullet_list` にて`Bullet`の生存管理をする。
9
9
 
10
+ ---
10
- 上記対応をしたサンプルード記載しおきます。ご参考まで。
11
+ 2018/03/05 メント欄の質問受け追記
11
12
 
13
+ > bullet = Bullet()
14
+ としていないのに
15
+ bullet.move()
16
+ bullet.draw()
17
+ が動くのはなぜですか?
18
+
19
+ これはしてますよ。処理の流れをコメント1~5で説明します。
20
+ 動きが分かりづらい時は図でプログラムの動作を書いてみるといいかもです。
21
+
22
+ > 自機を左上に移動してるときだけ弾が発射されないのですが、これはなぜでしょうか?
23
+
24
+ こちらはバグですねご指摘ありがとうございます。
25
+ Bullet#is_destroyで弾の生存判定をしているのですが、
26
+ 自機のサイズを計算するのを忘れてました。そのため、すぐに弾が削除対象になります。
27
+
28
+ 対応方法は2案あって、
29
+ 0. Player#moveにて自機の移動範囲を制限する。
30
+ 0. Bullet#is_destroyで自機のサイズを計算に含める。
31
+
32
+ 案2で実装します。
33
+ 質問文に自機の画像が無いため正確な自機のサイズはわかりませんが、
34
+ Player#moveを参考に30*30としておきます。
35
+
36
+ 以下はサンプルコードです。
37
+
38
+ ---
39
+
12
40
  ```Python
13
41
  # -*- coding: utf-8 -*-
14
42
  import pygame
@@ -69,11 +97,12 @@
69
97
 
70
98
  @property
71
99
  def is_destroy(self) -> bool:
72
- if self.bullet.x < 0 or self.bullet.y < 0:
100
+ if self.bullet.x < -30 or self.bullet.y < - 30:
73
101
  return True
74
102
  return False
75
103
 
76
104
  # 自機の位置が移動しても発射位置が追従するようにself.x/self.y ではなく self.rectを使用
105
+ # 3,Bulletクラスのインスタンス変数を生成してshoot関数の戻り値として返す
77
106
  return Bullet(self.rect.x, self.rect.y)
78
107
 
79
108
 
@@ -90,6 +119,7 @@
90
119
  player = Player("player.jpg", 350, 400, 5, 5)
91
120
  enemy1 = Enemy("enemy.jpg", 100, 100, 5, 0)
92
121
  clock = pygame.time.Clock()
122
+ # 1,リストでbulletの生存管理
93
123
  bullet_list = []
94
124
 
95
125
  while 1:
@@ -100,7 +130,9 @@
100
130
  enemy1.move()
101
131
  player.draw(screen)
102
132
  enemy1.draw(screen)
133
+ # 5,bullet_listの内容をfor in ループで回す。
103
134
  for bullet in bullet_list:
135
+
104
136
  bullet.move()
105
137
  bullet.draw()
106
138
  #リストからスクリーン範囲外のbulletをクリーンアップ
@@ -113,9 +145,12 @@
113
145
  pygame.quit()
114
146
  sys.exit()
115
147
  if event.type == KEYDOWN:
148
+ # 2,ショット:スペースキーを押下時に弾を発射
116
149
  if event.key == K_SPACE:
117
150
  # 発射時にbullet_listに追加
118
- bullet_list.append(player.shoot(screen))
151
+ bullet = player.shoot(screen)
152
+ # 4,リストにplayer.shootの戻り値である変数:bulletを追加
153
+ bullet_list.append(bullet)
119
154
  if event.key == K_ESCAPE:
120
155
  pygame.quit()
121
156
  sys.exit()

2

is_destroyをプロパティ化

2018/03/05 06:56

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -34,12 +34,15 @@
34
34
  self.rect = Rect(x, y, w, h)
35
35
  self.vx = vx
36
36
  self.vy = vy
37
+
37
38
  def draw(self, screen):
38
39
  screen.blit(self.image, self.rect)
39
40
 
41
+
40
42
  class Player(Flyer):
41
43
  def __init__(self, filename, x, y, vx, vy):
42
44
  super().__init__(filename, x, y, vx, vy)
45
+
43
46
  def move(self):
44
47
  pressed_key = pygame.key.get_pressed()
45
48
  if pressed_key[K_LEFT]:
@@ -55,15 +58,16 @@
55
58
 
56
59
  def shoot(self, screen): #弾発射
57
60
  class Bullet(object):
58
- def __init__(self, x:int, y:int):
61
+ def __init__(self, x: int, y: int):
59
62
  self.bullet = Rect(x, y, 20, 20)
60
63
 
61
64
  def draw(self):
62
65
  pygame.draw.rect(screen, (255, 255, 255), self.bullet)
63
66
 
64
- def move(self, x:int=0, y:int=-5):
67
+ def move(self, x: int=0, y: int=-5):
65
68
  self.bullet.move_ip(x, y)
66
69
 
70
+ @property
67
71
  def is_destroy(self) -> bool:
68
72
  if self.bullet.x < 0 or self.bullet.y < 0:
69
73
  return True
@@ -72,9 +76,11 @@
72
76
  # 自機の位置が移動しても発射位置が追従するようにself.x/self.y ではなく self.rectを使用
73
77
  return Bullet(self.rect.x, self.rect.y)
74
78
 
79
+
75
80
  class Enemy(Flyer):
76
81
  def __init__(self, filename, x, y, vx, vy):
77
82
  super().__init__(filename, x, y, vx, vy)
83
+
78
84
  def move(self):
79
85
  self.rect.move_ip(self.vx, self.vy)
80
86
  self.rect = self.rect.clamp(SCREEN)
@@ -97,8 +103,8 @@
97
103
  for bullet in bullet_list:
98
104
  bullet.move()
99
105
  bullet.draw()
100
- #リストからスクリーン範囲外のbulletを削除
106
+ #リストからスクリーン範囲外のbulletをクリーンアップ
101
- bullet_list = list(filter(lambda x: not x.is_destroy(), bullet_list))
107
+ bullet_list = list(filter(lambda x: not x.is_destroy, bullet_list))
102
108
 
103
109
  pygame.display.update()
104
110
 
@@ -117,4 +123,5 @@
117
123
 
118
124
  if __name__ == "__main__":
119
125
  main()
126
+
120
127
  ```

1

追記

2018/03/03 11:21

投稿

umyu
umyu

スコア5846

answer CHANGED
@@ -2,10 +2,8 @@
2
2
  0. 移動処理である`bullet.move_ip`をショットキー押下時の一度しか行っていないため、一度しか移動されないからです。そのため質問文のような状態になります。
3
3
  0. move_ipのパラメータは上に移動したいなら、x軸ではなくy軸の値を変更する必要があります。
4
4
 
5
-
6
5
  それ以外に発射したbulletがスクリーンの描画範囲外かの`生存管理`を行う必要があります。
7
6
 
8
-
9
7
  0. `class Bullet`を新規追加
10
8
  0. 変数:`bullet_list` にて`Bullet`の生存管理をする。
11
9
 
@@ -110,7 +108,7 @@
110
108
  sys.exit()
111
109
  if event.type == KEYDOWN:
112
110
  if event.key == K_SPACE:
113
- #player.shoot(screen)
111
+ # 発射時にbullet_listに追加
114
112
  bullet_list.append(player.shoot(screen))
115
113
  if event.key == K_ESCAPE:
116
114
  pygame.quit()