皆さん、こんにちは!
上越市を拠点にし、「FA設備・装置開発」と「画像処理」に強い会社、NSIです!
私達は豊富な経験と専門知識で、各種業界の自動化・システム化のお手伝いをしています。
先日、ブログに掲載できそうなネタを探していたところ…
ちょっと面白そうなPythonライブラリを発見したので、調査してみました。
というわけで、今回は Pythonでゲームが作れるライブラリ についてご紹介。
興味がある方、今後使ってみたい方の参考になれば嬉しいです。
Pygameとは?
Pygameは、Pythonでゲーム開発を行うためのライブラリです。
主な機能として、GUIの作成, 音声の利用, キーボードやマウスイベントの取得といった機能があります。
これらの機能を利用して、ゲーム開発はもちろん、GUIアプリケーションやデジタルアート作品の制作などにも活用されています。
Pygame
https://www.pygame.org/news

オープンソースなので情報が多く、初心者でも学びやすいのが特徴だよ。
Pygameを使ってみる
それでは、Pygameを使用してアプリを作成してみましょう!
今回は実装が比較的簡単なピンポンゲームを作成します。
なお、ここからはPythonがインストールされていることを前提に説明していきます。
1. Pygameのインストール
コマンドプロンプトを起動し、以下のコマンドを実行します。
※ 以下はPythonがインストールされている場合のコマンドです。別の開発環境(Anaconda)等を使っている場合は、それに合わせて変更してください。
pip install pygame
補足:Anacondaとは?
簡単に言うと、Pythonでの開発に必要な「ライブラリ」や「ツール」などをセットにした実行環境。
Pythonでは、必要なライブラリを「pip install ~」で1つずつインストールする必要があるが、Anacondaはインストール時にある程度のライブラリも含まれているため、わざわざインストールする手間がないのがメリット。
多様な機能が含まれている分、Pythonよりも容量を必要とするのがデメリット。
2. 処理を作成する
処理がやや長いため、何段階かに分けて説明していきます。
ソースコードの全文は最後に記載してあるため、まずコピペして実行したい!という方はそちらをご参照ください。
まず、画面やパドル, ボールのサイズなどを定義します。
事前にまとめて定義しておくことで、後々調整が楽に行えるようになります。
import pygame
import sys
# ゲーム画面のサイズ
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# パドルのサイズ,速度
PADDLE_WIDTH = 10
PADDLE_HEIGHT = 100
PADDLE_SPEED = 10
# ボールのサイズ,速度
BALL_SIZE = 15
BALL_SPEED_X = 3
BALL_SPEED_Y = 3
# 色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
CYAN = (255, 0, 255)
MAGENTA = (0, 255, 255)
Mainとなる関数を作成し、その中に画面に関する設定を定義します。
# Main関数
def main():
# Pygame関連
pygame.init() # 初期化
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 画面作成
pygame.display.set_caption("PygameSample") # 画面タイトル
clock = pygame.time.Clock() # 時計作成(FPS制御用)
font = pygame.font.Font(None, 36) # 文字定義作成
# Main関数呼び出し
if __name__ == "__main__":
main()
Main関数の上に、パドル(ボールを打ち返す棒)に関する処理を行うクラスを作成します。
ここではパドルの初期化(生成)、上移動、下移動時の処理を定義します。
# パドルクラス
class Paddle(pygame.sprite.Sprite):
# 初期化
def __init__(self, x, y, color):
super().__init__()
self.image = pygame.Surface((PADDLE_WIDTH, PADDLE_HEIGHT))
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.speed = PADDLE_SPEED
# 上移動したとき
def move_up(self):
self.rect.y -= self.speed
if self.rect.top < 0:
self.rect.top = 0
# 下移動したとき
def move_down(self):
self.rect.y += self.speed
if self.rect.bottom > SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
続けて、ボールに関する処理を行うクラスを作成します。
ここでは、ボールの初期化(生成)、表示更新時の処理を定義します。
# ボールクラス
class Ball(pygame.sprite.Sprite):
# 初期化
def __init__(self, color):
super().__init__()
self.image = pygame.Surface((BALL_SIZE, BALL_SIZE), pygame.SRCALPHA)
pygame.draw.circle(self.image, color, (BALL_SIZE // 2, BALL_SIZE // 2), BALL_SIZE // 2)
self.rect = self.image.get_rect()
self.rect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
self.speed_x = BALL_SPEED_X
self.speed_y = BALL_SPEED_Y
# 表示更新
def update(self):
self.rect.x += self.speed_x
self.rect.y += self.speed_y
if self.rect.top <= 0 or self.rect.bottom >= SCREEN_HEIGHT:
self.speed_y = -self.speed_y
今回使用するクラスは上記2つとなります。
Main関数に戻り、「#Pygame関連」に続けて、先ほど作成したクラスを利用し、画面に表示するアイテムを定義します。
# 画面アイテム関連
paddle1 = Paddle(30, SCREEN_HEIGHT // 2, CYAN)
paddle2 = Paddle(SCREEN_WIDTH - 30, SCREEN_HEIGHT // 2, MAGENTA)
ball = Ball(WHITE)
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
score1 = 0
score2 = 0
ここまで作成したら、一回実行してみましょう。
黒いウィンドウが一瞬表示されたのち、閉じると思います。これはまだ中身の処理が記載されていないためです。
ここから、ゲームの中身に関する処理を作成していきます。
【現在の画面イメージ】

先ほどの処理に続けて、準備画面を作成します。
画面上に「Press SPACE to start(スペースキーを押すと開始します)」というメッセージを表示する画面を作成します。
running = False
# runningがFalseのとき:準備画面
while not running:
screen.fill(BLACK) # 画面初期化
text = font.render("Press SPACE to start", True, WHITE) # テキスト定義
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)) # 描画位置定義
screen.blit(text, text_rect) # 描画
pygame.display.flip() # 画面更新
# イベント取得
for event in pygame.event.get():
# 閉じるボタン:終了
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# スペースキーを押した:開始
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
running = True
再度実行すると「Press SPACE to start」と書かれた画面が表示され、スペースキーを押すと閉じます。
スペースキーを押した後、プレイ画面に切り替わるよう処理を追加していきましょう。
【現在の画面イメージ】

先ほどの処理に続けて、以下の処理を記述します。
スペースキーが押された際に表示する画面となります。
# 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)
実行すると、スペースキーを押した後、真っ黒な画面が表示されます。
画面の切替は問題なさそうですね。
描画処理を追加します。「#画面初期化」と「#画面更新」の間に処理を追加します。(以下参照)
# 画面初期化
screen.fill(BLACK)
# 中心線を描画
pygame.draw.line(screen, WHITE, (SCREEN_WIDTH // 2, 0), (SCREEN_WIDTH // 2, SCREEN_HEIGHT), 2)
# アイテム描画
all_sprites.draw(screen)
# 得点描画
score1_text = font.render("Player 1: {}".format(score1), True, CYAN) # テキスト定義
score1_rect = score1_text.get_rect(center=(SCREEN_WIDTH // 4, 20)) # 描画位置定義
screen.blit(score1_text, score1_rect) # 描画
score2_text = font.render("Player 2: {}".format(score2), True, MAGENTA) # テキスト定義
score2_rect = score2_text.get_rect(center=(SCREEN_WIDTH * 3 // 4, 20)) # 描画位置定義
screen.blit(score2_text, score2_rect)
# 画面更新
pygame.display.flip()
clock.tick(60)
実行すると、スペースキーを押した後、各アイテムが描画された画面が表示されます。
これだけだとただ表示されているだけとなるため、パドルやボールを動かす処理を追加していきます。
【現在の画面イメージ】

「#画面初期化」の上に以下の処理を追加します。
# キー判定
keys = pygame.key.get_pressed()
if keys[pygame.K_w]: # Wキー:パドル1を上移動
paddle1.move_up()
if keys[pygame.K_s]: # Sキー:パドル1を下移動
paddle1.move_down()
if keys[pygame.K_UP]:
paddle2.move_up() # ↑キー:パドル2を上移動
if keys[pygame.K_DOWN]:
paddle2.move_down() # ↓キー:パドル2を下移動
all_sprites.update() # アイテム描画
# ボールとパドルの衝突判定
if pygame.sprite.spritecollide(ball, [paddle1], False) or pygame.sprite.spritecollide(ball, [paddle2], False):
ball.speed_x = -ball.speed_x
実行すると、パドルにボールが衝突した際に、跳ね返るようになりました!
ただし、このままだとボールが画面外に行ってもリセットされません。
そこで、得点が入ったらボール位置をリセットする処理を追加します。
【現在の画面イメージ】

「#ボールとパドルの衝突判定」の下に以下の処理を追加します。
# ボールがゴールに入ったら得点を加算
if ball.rect.left <= 0:
score2 += 1 # 得点加算
ball.rect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2) # ボール位置リセット
elif ball.rect.right >= SCREEN_WIDTH:
score1 += 1 # 得点加算
ball.rect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2) # ボール位置リセット
これで処理は完成です!早速実行してみましょう。
3. 実行してみる
操作方法
Player1は「W」で上方向、「S」で下方向へパドルが移動します。
Player2は「↑」で上方向、「↓」で下方向へパドルが移動します。
バッチリ動作していますね。
効果音を入れたり、一時停止機能を追加したりするとより良くなりそうです。
おまけ. ソースコード全文
最後に、今回作成したソースコード全文を掲載します。
Pygameをインストールしたのち、以下のソースコードをコピペすれば実行できます。
import pygame
import sys
# ゲーム画面のサイズ
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
# パドルのサイズ,速度
PADDLE_WIDTH = 10
PADDLE_HEIGHT = 100
PADDLE_SPEED = 10
# ボールのサイズ,速度
BALL_SIZE = 15
BALL_SPEED_X = 3
BALL_SPEED_Y = 3
# 色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
CYAN = (255, 0, 255)
MAGENTA = (0, 255, 255)
# パドルクラス
class Paddle(pygame.sprite.Sprite):
# 初期化
def __init__(self, x, y, color):
super().__init__()
self.image = pygame.Surface((PADDLE_WIDTH, PADDLE_HEIGHT))
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.speed = PADDLE_SPEED
# 上移動したとき
def move_up(self):
self.rect.y -= self.speed
if self.rect.top < 0:
self.rect.top = 0
# 下移動したとき
def move_down(self):
self.rect.y += self.speed
if self.rect.bottom > SCREEN_HEIGHT:
self.rect.bottom = SCREEN_HEIGHT
# ボールクラス
class Ball(pygame.sprite.Sprite):
# 初期化
def __init__(self, color):
super().__init__()
self.image = pygame.Surface((BALL_SIZE, BALL_SIZE), pygame.SRCALPHA)
pygame.draw.circle(self.image, color, (BALL_SIZE // 2, BALL_SIZE // 2), BALL_SIZE // 2)
self.rect = self.image.get_rect()
self.rect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
self.speed_x = BALL_SPEED_X
self.speed_y = BALL_SPEED_Y
# 表示更新
def update(self):
self.rect.x += self.speed_x
self.rect.y += self.speed_y
if self.rect.top <= 0 or self.rect.bottom >= SCREEN_HEIGHT:
self.speed_y = -self.speed_y
# Main関数
def main():
# Pygame関連
pygame.init() # 初期化
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 画面作成
pygame.display.set_caption("PygameSample") # 画面タイトル
clock = pygame.time.Clock() # 時計作成(FPS制御用)
font = pygame.font.Font(None, 36) # 文字定義作成
# 画面アイテム関連
paddle1 = Paddle(30, SCREEN_HEIGHT // 2, CYAN)
paddle2 = Paddle(SCREEN_WIDTH - 30, SCREEN_HEIGHT // 2, MAGENTA)
ball = Ball(WHITE)
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
score1 = 0
score2 = 0
running = False
# runningがFalseのとき:準備画面
while not running:
screen.fill(BLACK) # 画面初期化
text = font.render("Press SPACE to start", True, WHITE) # テキスト定義
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)) # 描画位置定義
screen.blit(text, text_rect) # 描画
pygame.display.flip() # 画面更新
# イベント取得
for event in pygame.event.get():
# 閉じるボタン:終了
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# スペースキーを押した:開始
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
running = True
# 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_w]: # Wキー:パドル1を上移動
paddle1.move_up()
if keys[pygame.K_s]: # Sキー:パドル1を下移動
paddle1.move_down()
if keys[pygame.K_UP]:
paddle2.move_up() # ↑キー:パドル2を上移動
if keys[pygame.K_DOWN]:
paddle2.move_down() # ↓キー:パドル2を下移動
all_sprites.update() # アイテム描画
# ボールとパドルの衝突判定
if pygame.sprite.spritecollide(ball, [paddle1], False) or pygame.sprite.spritecollide(ball, [paddle2], False):
ball.speed_x = -ball.speed_x
# ボールがゴールに入ったら得点を加算
if ball.rect.left <= 0:
score2 += 1 # 得点加算
ball.rect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2) # ボール位置リセット
elif ball.rect.right >= SCREEN_WIDTH:
score1 += 1 # 得点加算
ball.rect.center = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2) # ボール位置リセット
# 画面初期化
screen.fill(BLACK)
# 中心線を描画
pygame.draw.line(screen, WHITE, (SCREEN_WIDTH // 2, 0), (SCREEN_WIDTH // 2, SCREEN_HEIGHT), 2)
# アイテム描画
all_sprites.draw(screen)
# 得点表示
score1_text = font.render("Player 1: {}".format(score1), True, CYAN) # テキスト定義
score1_rect = score1_text.get_rect(center=(SCREEN_WIDTH // 4, 20)) # 描画位置定義
screen.blit(score1_text, score1_rect) # 描画
score2_text = font.render("Player 2: {}".format(score2), True, MAGENTA) # テキスト定義
score2_rect = score2_text.get_rect(center=(SCREEN_WIDTH * 3 // 4, 20)) # 描画位置定義
screen.blit(score2_text, score2_rect) # 描画
# 画面更新
pygame.display.flip()
clock.tick(60)
# 終了
pygame.quit()
sys.exit()
# Main関数呼び出し
if __name__ == "__main__":
main()
最後に
今回は Pythonでゲームが作れるライブラリ について調査してみました。
GUIが作成できるため、ゲームを作成する用途以外にも活用できそうです。
皆さんも息抜きに作成してみてはいかがでしょうか?
ここまで読んでいただき、ありがとうございました。
ご質問・ご要望・ご相談などは、下記お問い合わせフォームからお気軽にご連絡ください。
http://www.net-nsi.co.jp/toiawase.html

この記事が面白いと思ったらGoodボタンを押してね~