【Pygame】卓球ゲーム(PONG風)を作成する方法とサンプルコード

Pygameを用いてPONG風の卓球ゲームを作る方法とソースコードを解説します。

卓球ゲーム(PONG)とは

PONGとは、1972年にATARI社から発売されたアーケードゲームです。
内容はバーをコントローラーで上下に操作しボールを打ち合う2人用のピンポンゲームです。
今回は、以下のようなPygameでPONG風の卓球ゲーム作成する方法を解説します。

動画解説版

サンプルコード

PONEのサンプルコードです。バーを上下に動かしてボールを打ち返し、相手のゴールにボールを入れるとスコアが加算されます。


コード解説

上記コードの各部分を順に詳しく解説します。

1. インポート

import pygame
import sys
from pygame.locals import *
  • pygame: Pygameライブラリ。
  • sys: システム関連。
  • pygame.locals: Pygameの定数。

2. バーのスプライトクラス

# バーのスプライトクラス
class Bar(pygame.sprite.Sprite):
    def __init__(self, x, y, alpha=0):
        super().__init__()
        self.image = pygame.Surface((10, 50 + 50*alpha))
        self.image.fill((255, 255, 255))
        self.rect = self.image.get_rect()
        self.rect.topleft = (x, y)

    def update(self, dy):
        self.rect.y += dy
        if self.rect.y < 10:
            self.rect.y = 10
        elif self.rect.y > 420:
            self.rect.y = 420
  • Barクラス: プレイヤーのバーを表すスプライトクラス。
  • initメソッド: バーの初期位置とサイズを設定。alphaはゲームレベルに応じて相手のバーサイズを大きくするための倍率。
  • updateメソッド: バーの位置を更新し、画面外に出ないように制限。

3. ボールのスプライトクラス

class Ball(pygame.sprite.Sprite):
    def __init__(self, x, y, vx, vy):
        super().__init__()
        self.image = pygame.Surface((20, 20), pygame.SRCALPHA)
        pygame.draw.circle(self.image, (255, 255, 255), (10, 10), 10)
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.vx = vx
        self.vy = vy

    def update(self):
        self.rect.x += self.vx
        self.rect.y += self.vy
        if self.rect.y <= 10 or self.rect.y >= 457.5:
            self.vy = -self.vy
  • Ballクラス: ボールを表すスプライトクラス。
  • initメソッド: ボールの初期位置と速度を設定。
  • updateメソッド: ボールの位置を更新し、上下の壁に当たった場合に反射。

4. 初期設定

def main():
    pygame.init()
    screen = pygame.display.set_mode((640, 480), 0, 32)
    pygame.display.set_caption("PONG")
    clock = pygame.time.Clock()
    font = pygame.font.SysFont(None, 40)

    # スコア
    score1, score2 = 0, 0

    # ゲームレベル(値が大きくなるほど、バーとボールが早く動き、敵のバーサイズが大きくなる)
    game_level = 2

    # ボールスピード
    ball_speed = 5
  • pygame.init(): Pygameを初期化。
  • screen: ゲーム画面の設定。
  • pygame.display.set_caption: ウィンドウのタイトルを設定。
  • clock: フレームレートを管理。
  • font: スコア表示用のフォントを設定。

5. スプライトの作成と管理

    # スプライト作成
    bar1 = Bar(10, 215)
    bar2 = Bar(620, 215, game_level*0.2)
    ball = Ball(320, 240, ball_speed + game_level, ball_speed + game_level)

    # スプライトグループに追加
    all_sprites = pygame.sprite.Group()
    all_sprites.add(bar1, bar2, ball)
  • bar1, bar2: プレイヤーと敵のバーを作成。
  • ball: ボールを作成。
  • all_sprites: 全てのスプライトを管理するグループ。

6. ゲームの初期状態

    bar1_dy = 0
    score1, score2 = 0, 0
  • bar1_dy: プレイヤーのバーの移動量(初期値0)。
  • score1, score2: プレイヤーと敵のスコア。

7. メインループとイベント処理

    running = True  # ループ処理の実行を継続するフラグ

    while running:
        # キーイベント処理
        for event in pygame.event.get():
            # 閉じるボタンが押されたらループ終了(ゲーム終了)
            if event.type == QUIT:
                running = False
            # ↑もしくは↓矢印キーが押されたらバーを10px動かす
            if event.type == KEYDOWN:
                if event.key == K_UP:
                    bar1_dy = -10
                elif event.key == K_DOWN:
                    bar1_dy = 10
            if event.type == KEYUP:
                if event.key in (K_UP, K_DOWN):
                    bar1_dy = 0
  • QUITイベント: ゲームを終了。
  • KEYDOWNイベント: キーが押されたときの処理。
  • KEYUPイベント: キーが離されたときの処理。

8. スプライトの更新

        # バーとボールの更新
        bar1.update(bar1_dy)
        bar2.update((ball.rect.y - bar2.rect.y) * 0.1 * game_level)
        ball.update()
  • bar1.update: プレイヤーのバーを更新。
  • bar2.update: 敵のバーをボールに追従させる。ゲームレベル(game_level)が高いほど速く追従する。
  • ball.update: ボールを更新。

9. 衝突判定

        if pygame.sprite.collide_rect(ball, bar1) or pygame.sprite.collide_rect(ball, bar2):
            ball.vx = -ball.vx
  • collide_rect: ボールがバーに当たった場合、ボールの方向を反転。

10. スコアの更新

        if ball.rect.x < 5:
            score2 += 1
            ball.rect.center = (320, 240)
            ball.vx = 2
            ball.vy = 2
        elif ball.rect.x > 620:
            score1 += 1
            ball.rect.center = (320, 240)
            ball.vx = -2
            ball.vy = -2
  • ボールが左端または右端に到達: スコアを更新し、ボールを中央にリセット。

11. 画面の描画

        screen.fill((0, 50, 0))
        pygame.draw.aaline(screen, (255, 255, 255), (330, 5), (330, 475))
        all_sprites.draw(screen)
        screen.blit(font.render(str(score1), True, (255, 255, 255)), (250, 10))
        screen.blit(font.render(str(score2), True, (255, 255, 255)), (400, 10))
        pygame.display.update()
        clock.tick(30)
  • 画面のクリア: 画面を黒で塗りつぶす。
  • 中央線の描画: 中央に線を描画。
  • スプライトの描画: 全てのスプライトを描画。
  • スコアの描画: スコアを画面に表示。
  • 画面の更新: 画面を更新。
  • フレームレートの設定: ゲームのフレームレートを設定。

12. main関数の呼び出し

if __name__ == "__main__":
    main()
  • main関数の呼び出し: ゲームを開始。

関連ページ

Pygameの使い方については以下ページで解説しています。

【Pygame超入門】使い方とサンプルゲームを解説
Pygameで2Dゲームを簡単に制作する方法を入門者向けに解説します。

Python全般については以下ページで解説しています。

【Python超入門】使い方とサンプル集
Pythonの使い方について、基礎文法から応用例まで入門者向けに解説します。

コメント

  1. renk より:

    ブログを楽しく拝見させて頂いております。ありがとうございます。
    さて、PONGサンプルを動作させようと思いますが、バーだけ動いて動作しません。
    何か問題ありますでしょうか?
    因みに/→//の対応はしました。

    <開発環境>
    Windows
    Python 3.6

    • 管理人 より:

      ※renk様
      コメントありがとうございます。
      私の環境(Windows10+Python3.6)でもエラーが出ましたので
      ソースコードを修正致しました。
      ご確認いただけますと幸いです。

  2. renk より:

    ご対応頂きありがとうございます。
    私の環境でも動作確認できました。