Documentation Python

Pythonでのゲーム開発に興味があるなら、Pygameライブラリは素晴らしいスタートポイントです。Pygameは2Dゲームの開発をシンプルにするための強力なライブラリで、Pythonを使ってグラフィックスや音声の処理、ユーザー入力の管理が簡単にできます。この記事では、Pygameを使ってシンプルな2Dゲームを作るための基礎を学びます。

Pygameの主要機能

機能説明主なモジュール
ウィンドウ管理ゲーム画面の作成・更新pygame.display
描画図形・画像の描画pygame.draw, pygame.image
イベント処理キーボード・マウス入力pygame.event, pygame.key
音声BGM・効果音の再生pygame.mixer
時間管理FPS制御・タイマーpygame.time
衝突判定オブジェクト間の当たり判定pygame.Rect

Pygameのインストール

まず、Pygameライブラリをインストールする必要があります。

pip install pygame

インストールの確認をします。

import pygame
print(pygame.version.ver)  # バージョン番号が表示されれば成功

Pygameの基本構造

Pygameでゲームを作る際の基本的な流れは、以下のステップに分かれます。

1. 初期化(pygame.init())

2. ウィンドウの作成(pygame.display.set_mode())

3. メインループ開始
    ├── イベント処理(キーボード・マウス)
    ├── ゲーム状態の更新
    ├── 画面の描画
    └── 画面の更新(pygame.display.flip())

4. 終了処理(pygame.quit())

基本的なウィンドウの作成

以下は、Pygameでゲームウィンドウを作成する最も基本的なコードです。

import pygame
import sys

# Pygameの初期化
pygame.init()

# 画面サイズの定数
WIDTH, HEIGHT = 800, 600

# ウィンドウの作成
screen = pygame.display.set_mode((WIDTH, HEIGHT))

# ウィンドウタイトルを設定
pygame.display.set_caption("Pygame入門")

# FPSを制御するためのClockオブジェクト
clock = pygame.time.Clock()

# メインループ
running = True
while running:
    # イベント処理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 背景色を設定(RGB: 白)
    screen.fill((255, 255, 255))

    # 画面の更新
    pygame.display.flip()

    # 60FPSに制限
    clock.tick(60)

# 終了処理
pygame.quit()
sys.exit()

FPS制御の重要性

pygame.time.Clock()を使うことで、ゲームの動作速度を一定に保てます。

clock = pygame.time.Clock()

while running:
    # ... ゲーム処理 ...

    # 60FPSに制限(1秒間に60回ループ)
    clock.tick(60)

    # 実際のFPSを取得
    actual_fps = clock.get_fps()

キャラクターの描画

次に、シンプルなキャラクターを描画してみましょう。

import pygame
import sys

pygame.init()

WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("キャラクター描画")
clock = pygame.time.Clock()

# 色の定義(RGB)
WHITE = (255, 255, 255)
BLUE = (0, 128, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

# プレイヤーの設定
player_pos = [100, 100]
player_size = 50

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 背景を白で塗りつぶし
    screen.fill(WHITE)

    # 四角形を描画(プレイヤー)
    pygame.draw.rect(screen, BLUE, (*player_pos, player_size, player_size))

    # 円を描画
    pygame.draw.circle(screen, RED, (300, 200), 30)

    # 線を描画
    pygame.draw.line(screen, GREEN, (400, 100), (500, 200), 3)

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()

主な描画関数

関数説明引数
pygame.draw.rect()四角形surface, color, rect
pygame.draw.circle()surface, color, center, radius
pygame.draw.line()surface, color, start, end, width
pygame.draw.polygon()多角形surface, color, points

キャラクターの移動

キーボード入力に応じてキャラクターを移動させます。

import pygame
import sys

pygame.init()

WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("キャラクター移動")
clock = pygame.time.Clock()

WHITE = (255, 255, 255)
BLUE = (0, 128, 255)

# プレイヤーの設定
player_x = WIDTH // 2
player_y = HEIGHT // 2
player_size = 50
player_speed = 5

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        # ESCキーで終了
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False

    # キーの状態を取得
    keys = pygame.key.get_pressed()

    # 矢印キーまたはWASDキーで移動
    if keys[pygame.K_LEFT] or keys[pygame.K_a]:
        player_x -= player_speed
    if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
        player_x += player_speed
    if keys[pygame.K_UP] or keys[pygame.K_w]:
        player_y -= player_speed
    if keys[pygame.K_DOWN] or keys[pygame.K_s]:
        player_y += player_speed

    # 画面外に出ないように制限(境界チェック)
    player_x = max(0, min(player_x, WIDTH - player_size))
    player_y = max(0, min(player_y, HEIGHT - player_size))

    # 描画
    screen.fill(WHITE)
    pygame.draw.rect(screen, BLUE, (player_x, player_y, player_size, player_size))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()

キーボード入力の2つの方法

# 方法1: pygame.key.get_pressed() - 押しっぱなしを検出
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
    print("スペースキーが押されている")

# 方法2: イベントで検出 - 押した瞬間・離した瞬間を検出
for event in pygame.event.get():
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_SPACE:
            print("スペースキーが押された")
    if event.type == pygame.KEYUP:
        if event.key == pygame.K_SPACE:
            print("スペースキーが離された")

衝突判定(コリジョン検出)

ゲームでは、オブジェクト同士が接触したかどうかを判定する必要があります。

import pygame
import sys
import random

pygame.init()

WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("衝突判定")
clock = pygame.time.Clock()

WHITE = (255, 255, 255)
BLUE = (0, 128, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

# プレイヤー(Rectオブジェクトを使用)
player = pygame.Rect(100, 100, 50, 50)
player_speed = 5

# アイテム
item = pygame.Rect(
    random.randint(0, WIDTH - 30),
    random.randint(0, HEIGHT - 30),
    30, 30
)

# スコア
score = 0
font = pygame.font.Font(None, 36)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 移動
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player.x -= player_speed
    if keys[pygame.K_RIGHT]:
        player.x += player_speed
    if keys[pygame.K_UP]:
        player.y -= player_speed
    if keys[pygame.K_DOWN]:
        player.y += player_speed

    # 境界チェック
    player.clamp_ip(screen.get_rect())

    # 衝突判定
    if player.colliderect(item):
        score += 1
        # アイテムを新しい位置に移動
        item.x = random.randint(0, WIDTH - item.width)
        item.y = random.randint(0, HEIGHT - item.height)

    # 描画
    screen.fill(WHITE)
    pygame.draw.rect(screen, BLUE, player)
    pygame.draw.rect(screen, RED, item)

    # スコア表示
    score_text = font.render(f"Score: {score}", True, (0, 0, 0))
    screen.blit(score_text, (10, 10))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()

Rectの便利なメソッド

rect = pygame.Rect(x, y, width, height)

# 衝突判定
rect.colliderect(other_rect)  # 矩形同士の衝突
rect.collidepoint(x, y)       # 点との衝突

# 位置の取得・設定
rect.center     # 中心座標
rect.topleft    # 左上座標
rect.bottomright  # 右下座標

# 境界内に収める
rect.clamp_ip(screen.get_rect())

画像の読み込みと表示

実際のゲームでは、画像ファイルを使用します。

import pygame
import sys

pygame.init()

WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()

# 画像の読み込み
try:
    player_image = pygame.image.load("player.png").convert_alpha()
    # 画像のサイズ変更
    player_image = pygame.transform.scale(player_image, (64, 64))
except pygame.error:
    # 画像がない場合はサーフェスを作成
    player_image = pygame.Surface((64, 64))
    player_image.fill((0, 128, 255))

player_rect = player_image.get_rect()
player_rect.center = (WIDTH // 2, HEIGHT // 2)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        player_rect.x -= 5
    if keys[pygame.K_RIGHT]:
        player_rect.x += 5

    screen.fill((255, 255, 255))
    screen.blit(player_image, player_rect)  # 画像を描画

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()

サウンドの再生

BGMや効果音を追加すると、ゲームの雰囲気が向上します。

import pygame
import sys

pygame.init()
pygame.mixer.init()  # サウンドシステムの初期化

WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()

# サウンドの読み込み
try:
    # 効果音
    jump_sound = pygame.mixer.Sound("jump.wav")
    jump_sound.set_volume(0.5)  # 音量を50%に設定

    # BGM
    pygame.mixer.music.load("bgm.mp3")
    pygame.mixer.music.set_volume(0.3)
    pygame.mixer.music.play(-1)  # -1でループ再生
except pygame.error as e:
    print(f"サウンドファイルの読み込みに失敗: {e}")
    jump_sound = None

player_y = 400
is_jumping = False
velocity_y = 0

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE and not is_jumping:
                is_jumping = True
                velocity_y = -15
                if jump_sound:
                    jump_sound.play()

    # ジャンプ処理
    if is_jumping:
        player_y += velocity_y
        velocity_y += 0.8  # 重力
        if player_y >= 400:
            player_y = 400
            is_jumping = False
            velocity_y = 0

    screen.fill((135, 206, 235))  # 空色
    pygame.draw.rect(screen, (0, 128, 255), (100, player_y, 50, 50))
    pygame.draw.rect(screen, (100, 200, 100), (0, 450, WIDTH, 150))  # 地面

    pygame.display.flip()
    clock.tick(60)

pygame.mixer.music.stop()
pygame.quit()
sys.exit()

ゲームの拡張アイデア

基本的なPygameの使い方が理解できたら、次のような機能を追加してみましょう。

機能説明
敵キャラクタープレイヤーを追いかける敵を実装
スコアシステムハイスコアの保存・読み込み
ゲームオーバー残機システム、ゲームオーバー画面
メニュー画面タイトル画面、ポーズ機能
アニメーションスプライトシートを使った歩行アニメーション

完成版:シンプルなゲーム

これまでの要素を組み合わせた完成版のコードです。

import pygame
import sys
import random

# 初期化
pygame.init()

# 定数
WIDTH, HEIGHT = 800, 600
FPS = 60

# 色
WHITE = (255, 255, 255)
BLUE = (0, 128, 255)
RED = (255, 0, 0)
BLACK = (0, 0, 0)

# ゲームクラス
class Game:
    def __init__(self):
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        pygame.display.set_caption("Pygameサンプルゲーム")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(None, 36)
        self.reset()

    def reset(self):
        self.player = pygame.Rect(WIDTH // 2, HEIGHT // 2, 50, 50)
        self.items = [self.spawn_item() for _ in range(5)]
        self.score = 0
        self.running = True

    def spawn_item(self):
        return pygame.Rect(
            random.randint(0, WIDTH - 20),
            random.randint(0, HEIGHT - 20),
            20, 20
        )

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    self.running = False
                if event.key == pygame.K_r:
                    self.reset()

    def update(self):
        keys = pygame.key.get_pressed()
        speed = 5

        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.player.x -= speed
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.player.x += speed
        if keys[pygame.K_UP] or keys[pygame.K_w]:
            self.player.y -= speed
        if keys[pygame.K_DOWN] or keys[pygame.K_s]:
            self.player.y += speed

        self.player.clamp_ip(self.screen.get_rect())

        # アイテム収集
        for item in self.items[:]:
            if self.player.colliderect(item):
                self.items.remove(item)
                self.items.append(self.spawn_item())
                self.score += 10

    def draw(self):
        self.screen.fill(WHITE)
        pygame.draw.rect(self.screen, BLUE, self.player)
        for item in self.items:
            pygame.draw.rect(self.screen, RED, item)

        score_text = self.font.render(f"Score: {self.score}", True, BLACK)
        self.screen.blit(score_text, (10, 10))

        pygame.display.flip()

    def run(self):
        while self.running:
            self.handle_events()
            self.update()
            self.draw()
            self.clock.tick(FPS)

        pygame.quit()
        sys.exit()

# ゲーム実行
if __name__ == "__main__":
    game = Game()
    game.run()

まとめ

Pygameは Pythonで簡単に2Dゲームを作るための素晴らしいツールです。今回学んだ内容をまとめます。

項目内容
初期化pygame.init()
ウィンドウpygame.display.set_mode()
描画pygame.draw.rect(), screen.blit()
入力pygame.key.get_pressed()
衝突判定rect.colliderect()
FPS制御pygame.time.Clock().tick(60)

まずは基本を押さえ、徐々に機能を追加して、自分だけのゲームを作ってみましょう!

参考文献

円