質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

5351閲覧

pygameでスペースを押すと、上に動く四角を表示させたい。

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/03/03 04:11

前提・実現したいこと

pygameでシューティングゲームを作っています。

発生している問題・エラーメッセージ

スペースキーを押すと自機から弾が発射されるようにしたいのですが、スペースを押しても反応がありません。
スペースを押すと、任意の自機の位置から白い四角が表示され、x方向に-5ずつ動くようにするにはどうすればいいでしょうか?

該当のソースコード

python3

1# -*- coding: utf-8 -*- 2import pygame 3from pygame.locals import * 4import sys 5 6SCREEN = Rect(0, 0, 700, 500) 7 8pygame.init() 9screen = pygame.display.set_mode((700, 500)) 10pygame.display.set_caption("Shooting") 11 12 13#自機と敵機 14class Flyer(pygame.sprite.Sprite): 15 def __init__(self, filename, x, y, vx, vy): 16 pygame.sprite.Sprite.__init__(self) 17 self.x = x 18 self.y = y 19 self.image = pygame.image.load(filename).convert_alpha() 20 w = self.image.get_width() 21 h = self.image.get_height() 22 self.rect = Rect(x, y, w, h) 23 self.vx = vx 24 self.vy = vy 25 def draw(self, screen): 26 screen.blit(self.image, self.rect) 27 28class Player(Flyer): 29 def __init__(self, filename, x, y, vx, vy): 30 super().__init__(filename, x, y, vx, vy) 31 def move(self): 32 pressed_key = pygame.key.get_pressed() 33 if pressed_key[K_LEFT]: 34 self.rect.move_ip(-self.vx, 0) 35 if pressed_key[K_RIGHT]: 36 self.rect.move_ip(self.vx, 0) 37 if pressed_key[K_UP]: 38 self.rect.move_ip(0, -self.vy) 39 if pressed_key[K_DOWN]: 40 self.rect.move_ip(0, self.vy) 41 if self.y < -30 or self.y > 500 or self.x < -30 or self.x > 700: 42 pygame.sprite.Sprite.remove(self) 43 def shoot(self, screen): #弾発射 44 bullet = pygame.draw.rect(screen, (255, 255, 255), (self.x, self.y, 20, 20), 0) 45 bullet.move_ip(-5, 0) 46 47class Enemy(Flyer): 48 def __init__(self, filename, x, y, vx, vy): 49 super().__init__(filename, x, y, vx, vy) 50 def move(self): 51 self.rect.move_ip(self.vx, self.vy) 52 self.rect = self.rect.clamp(SCREEN) 53 54#メイン 55def main(): 56 player = Player("player.jpg", 350, 400, 5, 5) 57 enemy1 = Enemy("enemy.jpg", 100, 100, 5, 0) 58 clock = pygame.time.Clock() 59 60 while 1: 61 clock.tick(30) 62 screen.fill((0, 0, 0)) 63 64 player.move() 65 enemy1.move() 66 player.draw(screen) 67 enemy1.draw(screen) 68 69 pygame.display.update() 70 71 for event in pygame.event.get(): 72 if event.type == QUIT: 73 pygame.quit() 74 sys.exit() 75 if event.type == KEYDOWN: 76 if event.key == K_SPACE: 77 player.shoot(screen) 78 if event.key == K_ESCAPE: 79 pygame.quit() 80 sys.exit() 81 82if __name__ == "__main__": 83 main()

試したこと

whileの中にplayer.shoot(screen)を入れてみましたが最初から、playerと同じ位置に動かない白い四角が表示されるだけでした。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

原因は主に2点
0. 移動処理であるbullet.move_ipをショットキー押下時の一度しか行っていないため、一度しか移動されないからです。そのため質問文のような状態になります。
0. move_ipのパラメータは上に移動したいなら、x軸ではなくy軸の値を変更する必要があります。

それ以外に発射したbulletがスクリーンの描画範囲外かの生存管理を行う必要があります。

  1. class Bulletを新規追加
  2. 変数:bullet_list にてBulletの生存管理をする。

2018/03/05 コメント欄の質問を受けて追記

bullet = Bullet()

としていないのに
bullet.move()
bullet.draw()
が動くのはなぜですか?

これはしてますよ。処理の流れをコメント1~5で説明します。
動きが分かりづらい時は図でプログラムの動作を書いてみるといいかもです。

自機を左上に移動してるときだけ弾が発射されないのですが、これはなぜでしょうか?

■条件
・自機を左上方向に移動中
・ショットキーを押下

この時にショットキーを押下しても弾が発射されないという点ですね。
不具合ではないでしょうか、以下のprint文で各処理で正しい値が取れているのかdebugしてみてはどうでしょうか。
少し調査してみた限りでは、event.key == K_SPACE:のスペース押下イベントが発生してませんでした。
キーボードの同時押しの制限(Nキーロールオーバー)に引っかかった可能性もあります

あとはがんばってくださいな。

Python

1import time 2print('Done' + str(time.perf_counter()))

以下はサンプルコードです。


Python

1# -*- coding: utf-8 -*- 2import pygame 3from pygame.locals import * 4import sys 5 6SCREEN = Rect(0, 0, 700, 500) 7 8pygame.init() 9screen = pygame.display.set_mode((700, 500)) 10pygame.display.set_caption("Shooting") 11 12 13#自機と敵機 14class Flyer(pygame.sprite.Sprite): 15 def __init__(self, filename, x, y, vx, vy): 16 pygame.sprite.Sprite.__init__(self) 17 self.x = x 18 self.y = y 19 self.image = pygame.image.load(filename).convert_alpha() 20 w = self.image.get_width() 21 h = self.image.get_height() 22 self.rect = Rect(x, y, w, h) 23 self.vx = vx 24 self.vy = vy 25 26 def draw(self, screen): 27 screen.blit(self.image, self.rect) 28 29 30class Player(Flyer): 31 def __init__(self, filename, x, y, vx, vy): 32 super().__init__(filename, x, y, vx, vy) 33 34 def move(self): 35 pressed_key = pygame.key.get_pressed() 36 if pressed_key[K_LEFT]: 37 self.rect.move_ip(-self.vx, 0) 38 if pressed_key[K_RIGHT]: 39 self.rect.move_ip(self.vx, 0) 40 if pressed_key[K_UP]: 41 self.rect.move_ip(0, -self.vy) 42 if pressed_key[K_DOWN]: 43 self.rect.move_ip(0, self.vy) 44 if self.y < -30 or self.y > 500 or self.x < -30 or self.x > 700: 45 pygame.sprite.Sprite.remove(self) 46 47 def shoot(self, screen): #弾発射 48 class Bullet(object): 49 def __init__(self, x: int, y: int): 50 self.bullet = Rect(x, y, 20, 20) 51 52 def draw(self): 53 pygame.draw.rect(screen, (255, 255, 255), self.bullet) 54 55 def move(self, x: int=0, y: int=-5): 56 self.bullet.move_ip(x, y) 57 58 @property 59 def is_destroy(self) -> bool: 60 if self.bullet.x < -30 or self.bullet.y < - 30: 61 return True 62 return False 63 64 # 自機の位置が移動しても発射位置が追従するようにself.x/self.y ではなく self.rectを使用 65 # 3,Bulletクラスのインスタンス変数を生成してshoot関数の戻り値として返す 66 return Bullet(self.rect.x, self.rect.y) 67 68 69class Enemy(Flyer): 70 def __init__(self, filename, x, y, vx, vy): 71 super().__init__(filename, x, y, vx, vy) 72 73 def move(self): 74 self.rect.move_ip(self.vx, self.vy) 75 self.rect = self.rect.clamp(SCREEN) 76 77#メイン 78def main(): 79 player = Player("player.jpg", 350, 400, 5, 5) 80 enemy1 = Enemy("enemy.jpg", 100, 100, 5, 0) 81 clock = pygame.time.Clock() 82 # 1,リストでbulletの生存管理 83 bullet_list = [] 84 85 while 1: 86 clock.tick(30) 87 screen.fill((0, 0, 0)) 88 89 player.move() 90 enemy1.move() 91 player.draw(screen) 92 enemy1.draw(screen) 93 # 5,bullet_listの内容をfor in ループで回す。 94 for bullet in bullet_list: 95 bullet.move() 96 bullet.draw() 97 #リストからスクリーン範囲外のbulletをクリーンアップ 98 bullet_list = list(filter(lambda x: not x.is_destroy, bullet_list)) 99 100 pygame.display.update() 101 102 for event in pygame.event.get(): 103 if event.type == QUIT: 104 pygame.quit() 105 sys.exit() 106 if event.type == KEYDOWN: 107 # 2,ショット:スペースキーを押下時に弾を発射 108 if event.key == K_SPACE: 109 # 発射時にbullet_listに追加 110 bullet = player.shoot(screen) 111 # 4,リストにplayer.shootの戻り値である変数:bulletを追加 112 bullet_list.append(bullet) 113 if event.key == K_ESCAPE: 114 pygame.quit() 115 sys.exit() 116 117 118if __name__ == "__main__": 119 main() 120

投稿2018/03/03 08:56

編集2018/03/05 09:44
umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/03/05 02:11

ありがとうございます。弾を発射することができました。 質問があります。 player = Player("player.jpg", 350, 400, 5, 5) のように bullet = Bullet() としていないのに bullet.move() bullet.draw() が動くのはなぜですか?
退会済みユーザー

退会済みユーザー

2018/03/05 05:48

もう一つ質問があります。 自機を左上に移動してるときだけ弾が発射されないのですが、これはなぜでしょうか?
退会済みユーザー

退会済みユーザー

2018/03/05 10:04

ご回答ありがとうございます。分からないところが何点かありましたが、自分で調べてみようと思います。
umyu

2018/03/05 10:08

もしも友達にコンピュータでの対戦ゲームが好きな人がいれば、 Nキーロールオーバーについては知っているかもしれません、聞いてみてはどうでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問