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

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

新規登録して質問してみよう
ただいま回答率
85.31%
Pygame

Pygameは、ビデオゲームの製作用に設計されたクロスプラットフォームのPythonモジュールセットです。Pythonでコンピューターグラフィックスと音声を扱うためのライブラリが含まれています。

Python

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

Q&A

解決済

1回答

305閲覧

ブロック崩しにおける、ブロックの消え方

Yuto_0125

総合スコア2

Pygame

Pygameは、ビデオゲームの製作用に設計されたクロスプラットフォームのPythonモジュールセットです。Pythonでコンピューターグラフィックスと音声を扱うためのライブラリが含まれています。

Python

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

0グッド

0クリップ

投稿2023/09/20 04:29

実現したいこと

ボールと衝突したブロックが消えるようにしたい

前提

初心者なので、必要なものと不必要なものがハッキリしないため、載せるコードが長くなってしまいます。ご了承ください。
Pygameにて、基本的なブロック崩しを作成しています。

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

ゲーム開始直後、ボールが一番下の行のブロックのどれかに当たります。当たったブロックと同じy座標にある、x座標が一番小さい(一番奥のブロック)が消えてしまいます。当然、ボールに当たったブロックが消えるようにしたい

該当のソースコード

Python

1import pygame 2import setting as s 3import random 4from block import Block 5 6class Ball(pygame.sprite.Sprite): 7 def __init__(self, groups, x, y, racket_group, block_group): 8 super().__init__(groups) 9 self.screen = pygame.display.get_surface() 10 11 # グループ 12 self.racket_group = racket_group 13 self.block_group = block_group 14 15 # ラケット 16 self.image = pygame.Surface((10, 10)) 17 self.image.fill(s.RED) 18 self.rect = self.image.get_rect(center = (x, y)) 19 20 # 移動 21 move_list = [-1, 1] 22 self.direction = pygame.math.Vector2((random.choice(move_list), -1)) 23 self.speed = 4 24 25 def move(self): 26 if self.rect.right >= s.screen_width or self.rect.left <= 0: 27 self.direction.x *= -1 28 self.rect.x += self.speed * self.direction.x 29 if self.rect.top <= 0: 30 self.direction.y *= -1 31 self.rect.y += self.speed * self.direction.y 32 33 def check_off_screen(self): 34 if self.rect.top >= s.screen_height: 35 self.kill() 36 37 def reflection_racket(self): # ラケット反射 38 for racket in self.racket_group: 39 if self.rect.bottom >= racket.rect.top: 40 if self.rect.top <= racket.rect.bottom: 41 if self.rect.right <= racket.rect.right and self.rect.left >= racket.rect.left: 42 self.direction.y *= -1 43 44 def reflection_block(self): # ブロック反射 45 for block in self.block_group: 46 if self.rect.right >= block.rect.left and self.rect.left <= block.rect.right: # ブロックのx範囲内にボール 47 if self.rect.top <= block.rect.bottom <= self.rect.bottom:# # ブロックの下側衝突 48 self.direction.y *= -1 49 if self.rect.top <= block.rect.top <= self.rect.bottom: # ブロックの上側衝突 50 self.direction.y *= -1 51 52 53 if self.rect.top <= block.rect.bottom and self.rect.bottom >= block.rect.top: # ブロックのy範囲内にボール 54 if self.rect.left <= block.rect.left <= self.rect.right: 55 self.direction.x *= -1 56 if self.rect.left <= block.rect.right <= self.rect.right: 57 self.direction.x *= -1 58 59 def getCoords(self): # 左上と右下の座標取得 60 return (self.rect.x, self.rect.y, self.rect.x + s.block_width - 5, self.rect.y + s.block_height - 5) 61 62 63 64 def getCollisionCoords(self, object): 65 # ボールとオブジェクトの座標取得 66 ball_x1, ball_y1, ball_x2, ball_y2 = self.getCoords() 67 object_x1, object_y1, object_x2, object_y2 = object.getCoords() 68 69 # 短形の座標取得 70 x1 = max(ball_x1, object_x1) 71 y1 = max(ball_y1, object_y1) 72 x2 = min(ball_x2, object_x2) 73 y2 = min(ball_y2, object_y2) 74 75 if x1 < x2 and y1 < y2: 76 return (x1, y1, x2, y2) 77 else: 78 return None 79 80 def collision(self): 81 max_area = 0 82 x = None 83 y = None 84 for block in self.block_group: 85 collision_rect = self.getCollisionCoords(block) 86 if collision_rect != None: # 当たった場合 87 x1, y1, x2, y2 = collision_rect 88 area = (x2 - x1) * (y2 - y1) 89 if max_area < area: 90 max_area = area 91 x = x1 // s.block_width 92 y = y1 // s.block_height 93 return x, y 94 95 96 97 def update(self): 98 self.move() 99 self.check_off_screen() 100 self.reflection_racket() 101 self.reflection_block() 102 self.collision() 103 104class Block(pygame.sprite.Sprite): 105 def __init__(self, groups, position, ball_group): 106 super().__init__(groups) 107 self.screen = pygame.display.get_surface() 108 109 # グループ 110 self.ball_group = ball_group 111 112 # ブロック 113 self.position = position 114 self.image = pygame.Surface((s.block_width - 5, s.block_height - 5)) 115 self.image.fill(s.GREEN) 116 self.rect = self.image.get_rect(topleft = (self.position)) 117 118 # 体力 119 self.health = 1 120 self.alive = True 121 122 def getCoords(self): # 左上と右下の座標取得 123 return (self.rect.x, self.rect.y, self.rect.x + s.block_width - 5, self.rect.y + s.block_height - 5) 124 125 def update(self): 126 self.getCoords() 127 128class Game: 129 def __init__(self): 130 self.screen = pygame.display.get_surface() 131 132 # グループの作成 133 self.create_group() 134 135 # ラケット 136 racket = Racket(self.racket_group, s.screen_width / 2, s.screen_height - 10) 137 138 # ボール 139 self.ball = Ball(self.ball_group, s.screen_width / 2, s.screen_height / 2, self.racket_group, self.block_group) 140 141 142 143 def create_group(self): 144 self.racket_group = pygame.sprite.GroupSingle() 145 self.ball_group = pygame.sprite.Group() 146 self.block_group = pygame.sprite.Group() 147 148 149 def set_up(self): # ブロック生成 150 self.field = [] 151 for row in range(s.row_num): 152 block_list = [] 153 for col in range(s.col_num): 154 self.block = Block(self.block_group, (col * s.block_width + 2.5, row * s.block_height), self.ball_group) 155 block_list.append(self.block) 156 self.field.append(block_list) 157 158 159 def delete(self): # ブロック削除 160 collided_block = None 161 x, y = self.ball.collision() 162 if x != None and y != None: 163 collided_block = self.field[x][y] 164 165 if collided_block != None: 166 collided_block.kill() 167 168 169 170 171 172 def run(self): 173 self.racket_group.draw(self.screen) 174 self.racket_group.update() 175 self.ball_group.draw(self.screen) 176 self.ball_group.update() 177 self.block_group.draw(self.screen) 178 self.block_group.update() 179 self.delete()

試したこと

ボールと衝突したブロックの座標を取得しようとGameクラス内のdelete()においてprint(x, y)を実行したところ、表示された座標の値自体は想定通りのものが出力された

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

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

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

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

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

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

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

guest

回答1

0

ベストアンサー

set_upの中でfieldに必要以上にたくさんblock_listを追加しているようにみえます
おそらくですがそれが原因ではないでしょうか。


「deleteがおかしい → collisionの結果(x,y)を表示確認してみたら想定通りだった」
というとこまでたどり着けたのなら、次のcollided_blockの中身は想定通りか?もしくはself.fieldは? それらを表示確認してみたら?……とやっていけば自力で原因に辿り着けていたのではという気がします。たいへん惜しい

投稿2023/09/20 18:18

pecmm

総合スコア760

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

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

Yuto_0125

2023/09/21 00:29

回答ありがとうございます。set_upのfieldをfor文から出したら解決しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問