こんにちは。
グローバルウェイの川嶌です。
Python初学者用の学習教材を探す機会があり、その中でPyGameに触れてみました。
PyGameを使うと100step程度のコードで簡単なゲームが作れます。
今回はPythonでゲームを作成できるPyGame紹介します。
この記事は以下の方を対象としています
★4 Python開発経験が3年以上。
★3 Python開発経験が1年以上。
★2 Python 初級者。簡単なプログラムコードが書けます。
★1 プログラミング未経験。
PyGameとは
PyGameは、初心者でも簡単に扱える、2Dゲーム開発に特化したシンプルで使いやすいライブラリです。2000年には登場しており、他のゲーム開発用ライブラリと比べて歴史が長いこともあり、ドキュメント類も充実しています。
開発環境を構築する
Pythonのインストールについては既に完了しているものとして説明します。
また、実行する環境はWindows環境を想定しています。 ターミナルを開き、下記コマンドを実行しましょう。
pip install pygame |
以上で、PyGameが使えるようになります。
サンプルコードを実行
まずは実際のコードを実行してみましょう。
下記のコードをファイルに保存します。
〔dodge_enemy.py〕
import pygame import random # ↓↓↓クラス定義はココから # 色を定義するためのクラス class Color: BLACK = (0, 0, 0) WHITE = (255, 255, 255) RED = (255, 0, 0) # 画面を管理するクラス class Screen: def __init__(self, width, height, font): self._width = width self._height = height self._font = font self._pg_display = pygame.display.set_mode( (width, height) # 2-1 ) @property def width(self): return self._width @property def height(self): return self._height # ゲームオブジェクトを描画するメソッド def draw(self, game_object_list): self._pg_display.fill(Color.BLACK) for gm in game_object_list: gm.draw(self._pg_display) pygame.display.flip() # 2-2 # ゲームオーバー画面を表示するメソッド def display_game_over(self): text = self._font.render(“ゲームオーバー!”, True, Color.WHITE) # 4-3 text_rect = text.get_rect(center=(self.width // 2, self.height // 2)) self._pg_display.blit(text, text_rect) # 4-4 pygame.display.flip() # 2-2 # ゲームオブジェクトの基本クラス class GameObject: def __init__(self, screen, x, y, width, height, color): self._screen = screen self._color = color self._pg_rect = pygame.Rect(x, y, width, height) # 3-1 @property def pg_rect(self): return self._pg_rect # 他のオブジェクトと衝突しているかを判定するメソッド def colliderect(self, game_object): return self._pg_rect.colliderect(game_object.pg_rect) # 3-2 # オブジェクトを描画するメソッド def draw(self, pg_display): pass # プレイヤーを表すクラス class Player(GameObject): def __init__(self, screen, x, y, radius, color): super().__init__( screen, x – radius, y – radius, radius * 2, radius * 2, color ) self._radius = radius # プレイヤーを移動させるメソッド def move(self, dx, dy): new_left = self._pg_rect.left + dx new_right = self._pg_rect.right + dx new_top = self._pg_rect.top + dy new_bottom = self._pg_rect.bottom + dy move_x = 0 move_y = 0 if self._screen.width > new_right and new_left > 0: move_x = dx if self._screen.height > new_bottom and new_top > 0: move_y = dy self._pg_rect.move_ip(move_x, move_y) # プレイヤーを描画するメソッド def draw(self, pg_display): pygame.draw.circle( pg_display, self._color, self._pg_rect.center, self._radius ) # 4-1 # 敵を表すクラス class Enemy(GameObject): def __init__(self, screen, x, y, width, height, color, speed): super().__init__(screen, x, y, width, height, color) self._speed = speed # 敵を移動させるメソッド def move(self): self._pg_rect.move_ip(0, self._speed) if self._pg_rect.top > self._screen.height: self._pg_rect.y = -self._pg_rect.height self._pg_rect.x = random.randint( 0, self._screen.width – self._pg_rect.width ) # 敵を描画するメソッド def draw(self, pg_display): pygame.draw.rect(pg_display, self._color, self._pg_rect) # 4-2 # ↑↑↑クラス定義はココまで # プログラムを実行すると、以降のコードが順次実行されます pygame.init() # 1-1 pygame.font.init() # 1-2 font = pygame.font.SysFont(“MS Gothic”, 74) screen = Screen(600, 400, font) player_radius = 15 player = Player(screen, 300, 350, player_radius, Color.WHITE) enemy_list = [] # 敵を生成するループ for i in range(8): enemy_list.append( Enemy( screen, random.randint(0, screen.width – 30), -30, 30, 30, Color.RED, random.randint(5, 10), ) ) running = True game_over = False # メインループ 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.move(-5, 0) if keys[pygame.K_RIGHT]: player.move(5, 0) if keys[pygame.K_UP]: player.move(0, -5) if keys[pygame.K_DOWN]: player.move(0, 5) # 敵の移動と衝突判定 for enemy in enemy_list: enemy.move() if player.colliderect(enemy): game_over = True # 画面の描画 screen.draw([player, *enemy_list]) # ゲームオーバー時の処理 if game_over: screen.display_game_over() pygame.time.delay(2000) running = False pygame.time.Clock().tick(60) # 5-1 pygame.quit() print(“ゲーム終了”) |
下記コマンドで実行してみましょう
python dodge_enemy.py |
コマンドを実行すると、新しいウインドウが起動し、ゲームが開始されます。
赤い四角(Enemy)が落ちてくるので、白い丸(Player)をキーボードの矢印キーで操作して避けましょう。ぶつかってしまうとゲームオーバーです。
ゲームオーバー後、または右上の✕ボタンのクリックでゲームウインドウを閉じます。
サンプルコード解説
■実行順
コードは上から順番に実行されます。実行の流れとしては下記となります。
①import文により、メモリ内に外部ライブラリの内容が展開されます。
②class文により、メモリ内にクラス定義内容が展開されます。
③「pygame.init() # 1-1」の行で、最初の実行コードが実行されます。
ここでは、メモリに展開された外部ライブラリpygameのinit関数を引数なしで実行します。
実行が完了したら、次の行が順次実行されます。(同期実行)
④「while running:」の行は、runningという変数がTrueである限り無限にループして処理を繰り返します。runningがFalseになるタイミングは、ゲーム画面右上の×ボタンが押されるなどしてQUITイベントが発生した場合か、ゲームオーバーになって2秒経過した場合としています。
⑤ファイルの末端まで実行し、次に実行する処理がなくなったらプログラムは終了します。
■クラス定義
Color …ゲーム中に登場する色を定義しています
Screen …ゲーム画面のサイズや後述のGameObjectの描画を行う
GameObject …ゲーム画面上に登場するオブジェクトの基底クラス
┣Player …キーボード操作できるプレイヤー
┗Enemy …上から落ちてくる敵
■ 使用しているPyGame関数
呼び出しているPyGame関数の一覧と説明(ソース上のインラインコメントと本一覧の項番が対応します)
1. 初期化関連 | 1-1. pygame.init() | PyGameライブラリの初期化を行い、使用するモジュールを準備します。 |
1-2. pygame.font.init() | フォントモジュールを初期化し、フォントを使用できるようにします。 | |
2. 画面関連 | 2-1. pygame.display.set_mode(size) | 指定したサイズのウィンドウを作成し、そのウィンドウを表すpygame.Surfaceオブジェクトを返します。 |
2-2. pygame.display.flip() | 描画した内容を画面に反映させます。これにより、更新された画面がユーザーに表示されます。 | |
3. 矩形関連 | 3-1. pygame.Rect(left, top, width, height) | 矩形を定義するためのオブジェクトを作成します。このオブジェクトを使って、位置やサイズを管理します。 |
3-2. pygame.Rect.colliderect(self, other_rect) | 他の矩形と衝突しているかどうかを判定するメソッドです。このメソッドを使用して、オブジェクト同士の衝突を確認します。 | |
4. 描画関連 | 4-1. pygame.draw.circle(surface, color, center, radius) | 指定された色と位置で円を描画します。プレイヤーオブジェクトの形を表現するために使用します。 |
4-2. pygame.draw.rect(surface, color, rect) | 指定された色で矩形を描画します。敵やブロックの形を表現するために使用します。 | |
4-3. pygame.font.Font.render(self, text, antialias, color) | 指定したフォント、アンチエイリアス設定、色を使ってテキストを描画するための画像を生成します。 | |
4-4. pygame.Surface.blit(self, source, dest) | あるSurfaceオブジェクト(source)を別のSurfaceオブジェクト(dest)の指定位置に描画します。これにより、テキストや画像を画面に表示できます。 | |
5. 時間関連 | 5-1. pygame.time.Clock.tick(self, fps) | 指定したフレームレート(60fps)でループするように動的に計算し待機します。これにより、ゲームの描画速度を一定に保ち、動作を滑らかにします。 |
まとめ
PyGameを使うと、手軽にゲームのゲーム開発が可能です。
オブジェクト間の衝突判定や、フレームレート指定等、便利な機能が備わっており、
ゲームを完成させるまでのハードルはかなり軽減されているのではないかと感じました。
ゲーム開発用のPythonライブラリやフレームワークは世の中にいくつかあり、PyGameは多機能ではないようですが、反面、手軽に使用できるため、Python初学者向けの学習教材としても使用できるライブラリと感じました。