概要
当たり判定はゲームのコア要素の一つです。
ここでは矩形(rect)判定、円やマスクによる精密判定、複数判定の効率的な処理方法を説明します。
用途に応じた手法を選ぶことが重要です。
矩形(Rect)ベースの当たり判定
最も簡単で高速なのが矩形(Rect)同士の衝突判定です。
スプライトが矩形領域を持っている場合、pygame.Rect.colliderect() を使って衝突を検出します。
多くのケースで十分に機能し、パフォーマンスも良好です。
# rect ベースの判定 if sprite1.rect.colliderect(sprite2.rect): handle_collision(sprite1, sprite2)
マスク(ピクセル単位)の判定
画像の透明部分を考慮した精密な当たり判定は pygame.mask を使います。
マスクはピクセル単位の衝突を検出できますが、計算コストが高くなるため必要な場合に限定して使います。
オフセット計算に注意してください。
# mask を使った判定の例 mask1 = pygame.mask.from_surface(sprite1.image) mask2 = pygame.mask.from_surface(sprite2.image) offset = (sprite2.rect.left - sprite1.rect.left, sprite2.rect.top - sprite1.rect.top) if mask1.overlap(mask2, offset): handle_precise_collision(sprite1, sprite2)
円や距離ベースの判定
キャラクターや弾丸などを中心点と半径で扱う場合は、距離の比較で判定できます。
平方根を使う計算は重いので、距離の二乗を比較する手法が一般的です。
# 円判定(距離の二乗を利用) dx = x1 - x2 dy = y1 - y2 r = r1 + r2 if dx*dx + dy*dy <= r*r: handle_collision()
多対多の衝突検出(最適化)
エネミー数や弾数が多い場合、全探索は O(n^2) になり負荷が高くなります。
空間分割(グリッド、クアッドツリー)やバウンディングボリューム階層(BVH)を使って候補を絞ると効率的です。
Pygame では近接判定用に簡易なグリッドを実装するのが現実的です。
スプライトグループでの衝突検出支援
pygame.sprite にはグループ間の当たり判定を支援する関数があります。
groupcollide や spritecollide を活用すると簡潔に実装できます。以下は使用例です。
# groupcollide の例(rect ベース) collisions = pygame.sprite.groupcollide(bullets, enemies, True, True) # spritecollide(マスク使用例) hits = pygame.sprite.spritecollide(player, enemies, False, pygame.sprite.collide_mask)
反発・ダメージ・衝突解決の考え方
衝突検出だけでなく、衝突解決(反発、位置補正、ダメージ処理など)も重要です。
物理演算を導入する場合は独自に運動方程式を扱うか、外部の物理エンジンを併用することを検討します。
単純なゲームでは位置補正や速度反転などで十分なケースが多いです。
手法 | 用途と特徴 |
---|---|
Rect.colliderect | 高速・簡易。矩形領域で十分な場合に有効。 |
Mask.overlap | ピクセル単位の精密判定。コスト高。 |
距離(円)判定 | 球状オブジェクトの近接検出に有効。軽量。 |