Pygame入門 — ミニプロジェクト(簡易シューティング)

概要

この章では、学んだ内容をまとめて簡単なシューティングゲームを作ります。
プレイヤー移動、弾発射、敵生成、当たり判定、スコア管理を実装することで、実践的な開発の流れを学びます。

プロジェクト構成(例)

下記のようなフォルダ構成で始めるのが分かりやすいです。

simple_shooter/
├─ main.py
├─ game/
│  ├─ __init__.py
│  ├─ player.py
│  ├─ enemy.py
│  ├─ bullet.py
│  └─ utils.py
├─ assets/
│  ├─ player.png
│  ├─ enemy.png
│  ├─ bullet.png
│  └─ sound/
│     ├─ shoot.wav
│     └─ bgm.mp3
└─ requirements.txt

 

最小実装(サンプル)

以下は main.py における簡易な実装例です。
クラスは別ファイルに分けることを推奨します。

# main.py - 簡易シューティングの最小例(説明用)
import pygame
import sys
import random
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()

# プレイヤー
player_surf = pygame.Surface((40, 30))
player_surf.fill((0, 200, 0))
player_rect = player_surf.get_rect(center=(320, 430))

bullets = []
enemies = []
score = 0

def spawn_enemy():
    x = random.randint(20, 620)
    rect = pygame.Rect(x, -30, 30, 30)
    enemies.append(rect)

SPAWN_EVENT = USEREVENT + 1
pygame.time.set_timer(SPAWN_EVENT, 800)  # 800ms ごとに敵出現

running = True
while running:
    dt = clock.tick(60) / 1000.0

    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        elif event.type == SPAWN_EVENT:
            spawn_enemy()
        elif event.type == KEYDOWN:
            if event.key == K_SPACE:
                bullet_rect = pygame.Rect(player_rect.centerx - 4, player_rect.top - 10, 8, 10)
                bullets.append(bullet_rect)

    # 入力(移動)
    keys = pygame.key.get_pressed()
    if keys[K_LEFT]:
        player_rect.x -= int(300 * dt)
    if keys[K_RIGHT]:
        player_rect.x += int(300 * dt)
    player_rect.clamp_ip(screen.get_rect())

    # 弾の更新
    for b in bullets[:]:
        b.y -= int(500 * dt)
        if b.bottom < 0: bullets.remove(b) # 敵の更新 for e in enemies[:]: e.y += int(120 * dt) if e.top > 480:
            enemies.remove(e)

    # 衝突判定(弾と敵)
    for e in enemies[:]:
        for b in bullets[:]:
            if e.colliderect(b):
                try:
                    enemies.remove(e)
                    bullets.remove(b)
                except ValueError:
                    pass
                score += 100

    # 描画
    screen.fill((30, 30, 30))
    screen.blit(player_surf, player_rect)
    for b in bullets:
        pygame.draw.rect(screen, (255, 255, 0), b)
    for e in enemies:
        pygame.draw.rect(screen, (200, 0, 0), e)

    # スコア表示
    font = pygame.font.SysFont(None, 24)
    text = font.render(f"Score: {score}", True, (255,255,255))
    screen.blit(text, (10, 10))

    pygame.display.flip()

pygame.quit()
sys.exit()

 

拡張案(学習ポイント)

以下を段階的に追加して完成度を高めてください。

  • 画像(player.png, enemy.png, bullet.png)に差し替え、Sprite クラスに分割する
  • 当たり判定を mask ベースに変更して精度を上げる
  • 敵種類や弾パターンを増やす(アルゴリズム実装)
  • スコア表示やライフ、ゲームオーバー画面を実装する
  • SE(shoot.wav)やBGM(bgm.mp3)を追加して雰囲気を向上させ

 

注意点とデバッグ

– リソース(画像・音声)は事前に読み込み、毎フレームで再読み込みしないでください
– 衝突処理でリストをループ中に変更する際はコピーを使うか、安全に削除する工夫をしてください
– パフォーマンス測定のために clock.get_fps() やプロファイラを利用してください

項目 補足
敵出現 タイマーイベントやウェーブ制御で管理
弾管理 弾は再利用(プール)を検討すると効率的