pygame チートシート
最終更新
セットアップとゲームループ
pygame のプログラムはまずウィンドウを開き、プレイヤーが終了するまで一つのループを繰り返します。
| 操作 | コード |
|---|---|
| pygame-ce をインストール | python3 -m pip install pygame-ce |
| pygame を読み込んで初期化 | import pygame
pygame.init() |
| ウィンドウを開く | screen = pygame.display.set_mode((640, 480)) |
| ウィンドウのタイトルを設定 | pygame.display.set_caption("My Game") |
| Clock を作る | clock = pygame.time.Clock() |
| ゲームループ | running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill("black")
pygame.display.flip()
clock.tick(60) |
| ループの後で終了する | pygame.quit() |
画面
画面は Surface です。flip するまで何も表示されません。
| 操作 | コード |
|---|---|
| 描き終えたフレームを表示 | pygame.display.flip() |
| 一部の領域だけ更新 | pygame.display.update([rect1, rect2]) |
| 画面を塗りつぶす | screen.fill((30, 30, 46)) |
| ウィンドウのサイズ | screen.get_size(), screen.get_width() |
| 画面を Rect として取得 | screen.get_rect() |
| サイズを変えられるウィンドウ | pygame.display.set_mode((640, 480), pygame.RESIZABLE) |
| デスクトップと同じサイズで全画面表示 | pygame.display.set_mode((0, 0), pygame.FULLSCREEN) |
色と描画
pygame.draw の関数は Surface、色、位置を受け取ります。width=0 で内側を塗りつぶします。
| 操作 | コード |
|---|---|
| RGB で色を指定 | (255, 140, 0) |
| 名前や16進数で色を指定 | "tomato", "#ff8c00", pygame.Color("gold") |
| 四角形 | pygame.draw.rect(screen, "red", (x, y, w, h)) |
| 枠線と角丸 | pygame.draw.rect(screen, "red", rect, width=2, border_radius=8) |
| 円 (中心で指定) | pygame.draw.circle(screen, "blue", (cx, cy), radius) |
| 線 | pygame.draw.line(screen, "white", (x1, y1), (x2, y2), 3) |
| 多角形 | pygame.draw.polygon(screen, "green", [(0, 0), (40, 0), (20, 30)]) |
| 枠に収まる楕円 | pygame.draw.ellipse(screen, "purple", (x, y, w, h)) |
Rect
Rect は位置とサイズを整数で持ちます。
| 操作 | コード |
|---|---|
| Rect を作る | player = pygame.Rect(x, y, width, height) |
| 好きな点を基準に位置を決める | player.center = (320, 240), player.bottom = 400 |
| 辺と角 | left, right, top, bottom, topleft, midbottom |
| その場で移動 | player.move_ip(dx, dy) |
| 移動したコピー | moved = player.move(dx, dy) |
| 画面の中に収める | player.clamp_ip(screen.get_rect()) |
| 中心を基準に広げる | bigger = player.inflate(20, 20) |
| 小数の位置 (pygame-ce) | pygame.FRect(10.5, 20.25, 40, 40) |
画像、Surface、blit
画像はループの前に一度だけ読み込み、毎フレーム blit します。
| 操作 | コード |
|---|---|
| 透明度付きで画像を読み込む | img = pygame.image.load("player.png").convert_alpha() |
| 透明部分のない画像を読み込む | bg = pygame.image.load("sky.png").convert() |
| 画像を描く | screen.blit(img, (x, y)) |
| 中央に描く | screen.blit(img, img.get_rect(center=(320, 240))) |
| 空の Surface を作る | panel = pygame.Surface((200, 100)) |
| 透明な Surface | layer = pygame.Surface((200, 100), pygame.SRCALPHA) |
| Surface 全体を半透明にする | img.set_alpha(128) |
| スプライトシートから1コマ切り出す | frame = sheet.subsurface((0, 0, 32, 32)) |
| スクリーンショットを保存 | pygame.image.save(screen, "shot.png") |
変形
どの関数も新しい Surface を返します。直前の結果ではなく、元の画像を変形しましょう。
| 操作 | コード |
|---|---|
| サイズを変える | pygame.transform.scale(img, (64, 64)) |
| 倍率で拡大縮小 | pygame.transform.scale_by(img, 2) |
| なめらかにサイズを変える | pygame.transform.smoothscale(img, (64, 64)) |
| 回転 (反時計回り、度) | pygame.transform.rotate(img, 45) |
| 中心を軸に回転 | rotated = pygame.transform.rotate(original, angle)
rect = rotated.get_rect(center=rect.center) |
| 左右反転 | pygame.transform.flip(img, True, False) |
イベントとキーボード
1回だけの押下にはイベントを、押しっぱなしのキーには get_pressed() を使います。
| 操作 | コード |
|---|---|
| このフレームのイベントを読む | for event in pygame.event.get(): |
| ウィンドウが閉じられた | event.type == pygame.QUIT |
| キーが押された | event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE |
| キーが離された | event.type == pygame.KEYUP |
| 入力された文字 | event.unicode |
| 今押されているキー | keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= 5 |
| 2つのキーから向きを求める | dx = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT] |
| このフレームで押されたキー (pygame-ce) | pygame.key.get_just_pressed()[pygame.K_SPACE] |
| キー定数 | K_a...K_z, K_0...K_9, K_UP, K_RETURN, K_ESCAPE, K_LSHIFT |
| キーの名前 | pygame.key.name(event.key) |
| 独自のイベント | HIT = pygame.event.custom_type()
pygame.event.post(pygame.event.Event(HIT)) |
マウス
ボタン: 1 は左、2 は中央、3 は右。
| 操作 | コード |
|---|---|
| ボタンが押された | event.type == pygame.MOUSEBUTTONDOWN and event.button == 1 |
| 押された位置 | event.pos |
| 現在のポインター位置 | x, y = pygame.mouse.get_pos() |
| 今押されているボタン | left, middle, right = pygame.mouse.get_pressed() |
| マウスが動いた | event.type == pygame.MOUSEMOTION, event.rel |
| ホイールが回された | event.type == pygame.MOUSEWHEEL, event.y |
| ボタンの中をクリックした | button_rect.collidepoint(event.pos) |
| ポインターを隠す | pygame.mouse.set_visible(False) |
スプライトとグループ
スプライトは image と rect を持ち、グループはたくさんのスプライトをまとめて更新し、描画します。
| 操作 | コード |
|---|---|
| スプライトのクラス | class Coin(pygame.sprite.Sprite):
def __init__(self, pos):
super().__init__()
self.image = coin_img
self.rect = self.image.get_rect(center=pos) |
| グループを作る | coins = pygame.sprite.Group() |
| グループに追加 | coins.add(Coin((100, 50))) |
| すべてのスプライトを更新 | coins.update() |
| すべてのスプライトを描く | coins.draw(screen) |
| すべてのグループからスプライトを外す | coin.kill() |
| スプライトを1つだけ持つグループ | player = pygame.sprite.GroupSingle(Player()) |
当たり判定
Rect は重なったときに衝突します。辺が接しているだけでは衝突になりません。
| 操作 | コード |
|---|---|
| 2つの四角形 | a.colliderect(b) |
| 点が中にあるか | rect.collidepoint(x, y) |
| 複数のうち最初の1つ | rect.collidelist(walls) # index or -1 |
| スプライトとグループ | hits = pygame.sprite.spritecollide(player, coins, True) |
| どれかに当たったか | pygame.sprite.spritecollideany(player, enemies) |
| グループ同士 | pygame.sprite.groupcollide(bullets, enemies, True, True) |
| ピクセル単位 | pygame.sprite.spritecollide(a, group, False, pygame.sprite.collide_mask) |
| 円 | pygame.Vector2(a).distance_to(b) < r1 + r2 |
テキストとフォント
テキストを Surface に描画してから blit します。
| 操作 | コード |
|---|---|
| デフォルトのフォント | font = pygame.font.Font(None, 36) |
| システムフォント | font = pygame.font.SysFont("arial", 24) |
| フォントファイル | font = pygame.font.Font("pixel.ttf", 32) |
| テキストを描画 | text = font.render("Score: 10", True, "white") |
| 中央に描く | screen.blit(text, text.get_rect(center=(320, 40))) |
| 長いテキストを折り返す (pygame-ce) | font.render(story, True, "white", None, 400) |
| 描画せずにサイズを求める | font.size("Hello") |
| インストール済みのフォント | pygame.font.get_fonts() |
効果音と音楽
効果音は一度だけ読み込みます。音楽はファイルから1曲をストリーミング再生します。
| 操作 | コード |
|---|---|
| 効果音を読み込む | jump = pygame.mixer.Sound("jump.ogg") |
| 再生する | jump.play() |
| 効果音の音量 | jump.set_volume(0.5) |
| 音楽を読み込む | pygame.mixer.music.load("theme.ogg") |
| 音楽をずっとループ再生 | pygame.mixer.music.play(-1) |
| 一時停止と再開 | pygame.mixer.music.pause(), pygame.mixer.music.unpause() |
| 音楽を止める | pygame.mixer.music.stop() |
時間とタイマー
ティックの単位はミリ秒です。
| 操作 | コード |
|---|---|
| フレームレートを制限 | clock.tick(60) |
| デルタタイム (秒) | dt = clock.tick(60) / 1000 |
| 現在のフレームレート | clock.get_fps() |
| init からの経過ミリ秒 | pygame.time.get_ticks() |
| 繰り返すタイマーイベント | SPAWN = pygame.event.custom_type()
pygame.time.set_timer(SPAWN, 1000) |
| 1回だけのタイマー | pygame.time.set_timer(SPAWN, 2000, loops=1) |
| タイマーを止める | pygame.time.set_timer(SPAWN, 0) |
Vector2
位置や速度を小数で扱います。
| 操作 | コード |
|---|---|
| ベクトルを作る | pos = pygame.Vector2(100, 200) |
| 速度で動かす | pos += velocity * dt |
| 長さ | velocity.length() |
| 斜めでも同じ速さにする | if direction.length() > 0:
direction = direction.normalize() |
| 2点間の距離 | pos.distance_to(target) |
| 回転 | velocity.rotate(90) |
| 目標の点へ近づける (pygame-ce) | pos.move_towards_ip(target, 5) |
Python で 2D ゲームを作るときによく使う pygame のコードを、用途別にまとめました。ゲームループ、画面、色と描画、Rect、画像と blit、拡大縮小と回転、キーボードとマウスの入力、スプライトとグループ、当たり判定、テキスト、音、タイマー、Vector2 を扱います。各行には、そのまま貼り付けられる短いコードと、その働きを並べています。
ここに載せたコードはすべて pygame-ce 2.5 向けです。pygame-ce は pygame のコミュニティ版で、今も import pygame で読み込みます。pygame-ce と書かれた行はその追加機能を使っており、それ以外の行は元の pygame でも動きます。どのコードも pygame プレイグラウンド で試せます。ブラウザで pygame が動くので、インストールは不要です。Python そのものが初めてなら、まず Python チートシート から始めましょう。
pygame チートシートのよくある質問
この pygame チートシートは無料ですか?
はい。無料で、登録も不要です。ブックマークするか、ブラウザから PDF に印刷しておけば、スプライトグループ、効果音、当たり判定の正確な書き方が必要なときにいつでも見返せます。
このチートシートは pygame と pygame-ce の両方で使えますか?
import pygame で読み込み、API のほとんどが共通です。pygame-ce と書かれた行 (FRect、scale_by、get_just_pressed、テキストの折り返し、move_towards_ip) には pygame-ce が必要で、それ以外はどちらでも動きます。pygame のウィンドウが応答しないのはなぜですか?
pygame.event.get() を呼び、各フレームの最後に pygame.display.flip() と clock.tick(60) を呼んでください。入力にはイベントと key.get_pressed() のどちらを使えばよいですか?
KEYDOWN イベントを使います。歩くなど、キーを押している間ずっと続く動作には pygame.key.get_pressed() を使います。