PyGame の基本 #
参考書1 p.111(Chapter 1.2) 参考書2 p.75(Chapter 3.2)
PyGame は起動すると基本的に動き続けています。 メインループと呼ばれる繰り返し処理の中で、画像を表示したり、キー入力やマウスの動きを調べたりしています。
PyGame のプログラの基本的な流れは次のようになっています。 基本的にはパラパラ漫画の作り方と似ています。
# ゲームを作る7ステップ
1. ゲームの準備をする。
2. メインループ(ずっとループし続ける)
2-1. 画面を初期化する。
2-2. ユーザからの入力を調べる。
2-3. 絵を描いたり、判定したりする。
2-4. 画面を表示する。
2-5. 閉じるボタンが押されたら、終了する。
四角形を描く #
まずは四角形を描くだけのプログラム、draw_rect.py を書いてみましょう。
ユーザからの入力はないため、2-2 は省略します。
import pygame as pg # PyGame をインポートし、pg という名前で使えるようにする。
import sys # sys モジュールをインポートする(終了処理で使う)。
# 1. ゲームの準備をする。
pg.init() # PyGame の環境を初期化する。
screen = pg.display.set_mode((800, 600))
# 800x600 ピクセルのスクリーンを作成し、screen に代入する。
# 2. メインループ
while True:
# 2-1 画面を初期化する。
screen.fill(pg.Color("WHITE")) # 画面を白色で塗りつぶす。
# 2-3. 絵を描いたり、判定したりする。
pg.draw.rect(screen, pg.Color("RED"), (100, 100, 100, 150))
# 2-4. 画面を表示する。
pg.display.update()
# 2-5. 閉じるボタンが押されたら終了する。
for event in pg.event.get(): # イベント一覧を取得して、各イベントを調べる。
if event.type == pg.QUIT: # もし、閉じるボタンが押されたら。
pg.quit() # PyGame を終了する。これだけではウィンドウは閉じない。
sys.exit() # ウィンドウを閉じて、プログラムを終了する。
実行すると、下のようなウィンドウが開き、白い背景に赤い四角形が表示されます。
まずはpg.init() を呼び出して、ゲームの準備をします。
そして、ゲームやアニメーションを描画するウィンドウを 800x600 ピクセルの大きさで作成し、screen 変数に代入しています。
メインループはずっと回り続けているため、ループ内で終了処理(pg.quit() と sys.exit())を呼び出さなければプログラムが終了しません。
必ず終了処理を呼び出すようにしてください。
ループ内では、前のループの内容を消して(2-1)、今回のループの内容を描いて(2-2, 2-3)、画面を更新(2-4)していきます。
画面の初期化処理(2-1)では、画面全体を白色で塗りつぶしています(screen.fill(pg.Color("WHITE")))。
これで、前のループで描いた内容が消えます。
2-3 の描画処理では、pg.draw.rect 関数を使って四角形を描いています。
第1引数に描画先の画面(screen)、第2引数に色(pg.Color("RED"))、
第3引数に四角形の位置と大きさ((100, 100, 100, 150))を指定しています。
位置と大きさは、左上の x 座標、y 座標、幅、高さを表しています。
続いて、2-4 の画面更新処理では、pg.display.update() を呼び出して、画面に描いた内容を表示しています。
PyGame では、四角形を描けと命令しても、すぐに画面に表示されるわけではありません。
なぜなら、画面を書くという処理は時間がかかる、重い処理であるため、その都度描画していると処理全体が遅くなってしまうからです。
そのため、PyGame では裏側で絵を全て描いておいて、一気に表示される方法が採用されています。
手順 2-3 で screen に四角形を描きましたが、裏側にある絵に四角形を描いただけで、画面には表示されていません。
裏側で書いていた絵を一気にウィンドウ画面に表示させる処理が pg.display.update()(手順2-4)です。
最後に、2-5 の終了処理では、pg.event.get() 関数を使って、ユーザからの入力イベントを取得しています。
ユーザが行ったキー入力やマウスクリックなどの行為(イベントと呼ぶ)を調べて、必要に応じて処理を行います。
for event in pg.event.get(): とすることで、取得したイベントを1つずつ event 変数に代入して繰り返し処理ができます。
次に、if event.type == pg.QUIT: とすることで、event が閉じるボタンが押されたイベントかどうかを調べています。
閉じるボタンが押された場合は、pg.quit() と sys.exit() を呼び出して、プログラムを終了しています。
図形や文字、画像を描こう #
参考書1 p.119(Chapter 1.3) 参考書2 p.80(Chapter 3.3)
座標系 #
PyGame の座標系は左上が原点 \((0, 0)\) で、右に進むほど \(x\) 軸の値が増加し、下に進むほど \(y\) 軸の値が増加します。 例えば、以下の図のように横幅 800 ピクセル、高さ 600 ピクセルのウィンドウの場合、右下の座標は \((800, 600)\) となります。
図形を描く #
draw関数を用いると、様々な図形を描くことができます。
# 四角形(Rectangle)を描く。
# pg.draw.rect(screen, 色,(X, Y, 幅, 高さ))
pg.draw.rect(screen, pg.Color("RED"), (100, 100, 100, 150))
# 線(Line)を描く.始点位置:(X1, Y1), 終点位置:(X2, Y2)を指定して描く
# pg.draw.rect(screen, 色,(X1, Y1), (X2, Y2), 太さ)
pg.draw.line(screen, pg.Color("BLUE"), (250, 100), (350, 250), 5)
# 円(Ellipse)を描く。指定された (X, Y, 幅,高さ) に内接する円(楕円)を描く。
# pg.draw.ellipse(screen,色,(X, Y, 幅, 高さ),太さ)
pg.draw.ellipse(screen, pg.Color("GREEN"), (400, 100, 150, 150), 5)
例題11-1. 3つの図形を描く #
以下のプログラムの 2-3 の部分をコメントにあるように書き換えて、四角形、線、円を描いてみましょう。(draw_shapes.py)
import pygame as pg # PyGame をインポートし、pg という名前で使えるようにする。
import sys # sys モジュールをインポートする(終了処理で使う)。
# 1. ゲームの準備をする。
pg.init() # PyGame の環境を初期化する。
screen = pg.display.set_mode((800, 600))
# 800x600 ピクセルのスクリーンを作成し、screen に代入する。
# 2. メインループ
while True:
# 2-1 画面を初期化する。
screen.fill(pg.Color("WHITE")) # 画面を白色で塗りつぶす。
# 2-3. 絵を描いたり、判定したりする。
# (100, 100, 100, 150) で赤い四角形を描く。
# (250, 100) から (350, 250) までの青い線を太さ5で描く。
# (400, 100, 150, 150) に内接する楕円を緑色で太さ5で描く。
# 2-4. 画面を表示する。
pg.display.update()
# 2-5. 閉じるボタンが押されたら終了する。
for event in pg.event.get(): # イベント一覧を取得して、各イベントを調べる。
if event.type == pg.QUIT: # もし、閉じるボタンが押されたら。
pg.quit() # PyGame を終了する。これだけではウィンドウは閉じない。
sys.exit() # ウィンドウを閉じて、プログラムを終了する。
完成すれば、値や色を変更して、図形の位置や大きさ、色を変えてみましょう。
🏁 解答例
import pygame as pg # PyGame をインポートし、pg という名前で使えるようにする。
import sys # sys モジュールをインポートする(終了処理で使う)。
# 1. ゲームの準備をする。
pg.init() # PyGame の環境を初期化する。
screen = pg.display.set_mode((800, 600))
# 800x600 ピクセルのスクリーンを作成し、screen に代入する。
# 2. メインループ
while True:
# 2-1 画面を初期化する。
screen.fill(pg.Color("WHITE")) # 画面を白色で塗りつぶす。
# 2-3. 絵を描いたり、判定したりする。
# (100, 100, 100, 150) で赤い四角形を描く。
pg.draw.rect(screen, pg.Color("RED"), (100, 100, 100, 150))
# (250, 100) から (350, 250) までの青い線を太さ5で描く。
pg.draw.line(screen, pg.Color("BLUE"), (250, 100), (350, 250), 5)
# (400, 100, 150, 150) に内接する楕円を緑色で太さ5で描く。
pg.draw.ellipse(screen, pg.Color("GREEN"), (400, 100, 150, 150), 5)
# 2-4. 画面を表示する。
pg.display.update()
# 2-5. 閉じるボタンが押されたら終了する。
for event in pg.event.get(): # イベント一覧を取得して、各イベントを調べる。
if event.type == pg.QUIT: # もし、閉じるボタンが押されたら。
pg.quit() # PyGame を終了する。これだけではウィンドウは閉じない。
sys.exit() # ウィンドウを閉じて、プログラムを終了する。
画像を表示する #
次に画像を描画してみましょう。 その前に次のサイトから画像をダウンロードして、プログラムと同じフォルダに置いておいてください。
画像を描画するには、以下の2つの手順で行います。
- 画像を読み込む。
- 画像を画面に描画する。
画像を読み込むには、pg.image.load関数を用います。
読み込む画像ファイルがプログラムファイルから見てどこにあるのかを相対パスで指定します。
読み込んだ画像は画像用の変数に代入しておきましょう。
画像の大きさを取得したり、画像を描画するときに読み込んだ画像の変数を使います。
画像の大きさを変更するには、pg.transform.scale 関数を利用します。
この関数に、大きさを変更したい画像と、変更後のサイズを指定すると変更後の画像が取得できます。
ただし、変更後のサイズは画像のアスペクト比(縦横比)は保持しないので、縦横比を維持したい場合は、
幅、高さのどちらかを固定した上で、もう一方の値を計算で算出する必要があります。
画像を画面に描画するには、screen の blit関数を使います。
blitとは、Block Image Transfer の略で、指定された画像を、指定された位置に描画しています。
# 画像変数 = pg.image.load("画像ファイルの相対パス")
img01 = pg.image.load("cat.png")
x, y = img01.get_size() # 画像の大きさを取得する。
img02 = pg.transform.scale(img01, (100, 100)) # img01 を (100, 100) の大きさに変更する。
# ... screen の初期化
# screen 上の (50, 50) の位置が img02 の原点になるように img02 を描画する。
screen.blit(img02, (50, 50))
⚠️ File is not a Windows BMP file というエラーが出て画像読み込みに失敗した。
PyGame のインストール時に、さまざまな形式の画像ファイルを読み込めるよう、 インストール済みのライブラリを調べて、読み込めるようにしています。 PyGame をソースファイルからビルドしてインストールする方法と、ビルド済みのものをダウンロードしてインストールする方法があり、利用する Python のバージョンによって、いずれかの方法が選ばれます。 そして、ソースファイルからビルドしてインストールする方法は、ローカル環境に利用するライブラリが存在しなければ Windows BMP 以外は未対応の PyGame としてインストールされます。
Python 3.14 でこのようなエラーが出た場合、Python 3.12 にバージョンを落としてから、PyGame をインストールすると後者のインストール方法が採用されて、問題が解決することが多いです。 Python のバージョンとインストール方法を確認してみてください。
例題11-2. 画像を表示するプログラム #
以下のプログラムのコメントにあうようにプログラムを書き加えて、画像を表示するプログラムを完成させましょう(draw_image.py)。
import pygame as pg # PyGame をインポートし、pg という名前で使えるようにする。
import sys # sys モジュールをインポートする(終了処理で使う)。
# 1. ゲームの準備をする。
pg.init()
screen = pg.display.set_mode((800, 600))
# 800x600 ピクセルのスクリーンを作成し、screen に代入する。
img01 = # sys.argv[1] から画像を読み込む。
img02 = # img01 を 100x100 の大きさにリサイズする。
# 2. メインループ
while True:
# 2-1 画面を初期化する。
screen.fill(pg.Color("WHITE")) # 画面を白色で塗りつぶす。
# 2-3. 絵を描いたり、判定したりする。
# img01 を (10, 10) の位置に描画する。
# img02 を (10, 10) の位置に描画する。
# 2-4. 画面を表示する。
pg.display.update()
# 2-5. 閉じるボタンが押されたら終了する。
for event in pg.event.get(): # イベント一覧を取得して、各イベントを調べる。
if event.type == pg.QUIT: # もし、閉じるボタンが押されたら。
pg.quit() # PyGame を終了する。これだけではウィンドウは閉じない。
sys.exit() # ウィンドウを閉じて、プログラムを終了する。
🏁 解答例
import pygame as pg, sys
# 1. ゲームの準備をする。
pg.init()
screen = pg.display.set_mode((800, 600))
# 800x600 ピクセルのスクリーンを作成し、screen に代入する。
img01 = pg.image.load(sys.argv[1]) # sys.argv[1] から画像を読み込む。
img02 = pg.transform.scale(img01, (100, 100)) # img01 を 100x100 の大きさにリサイズする。
# 2. メインループ
while True:
# 2-1 画面を初期化する。
screen.fill(pg.Color("WHITE")) # 画面を白色で塗りつぶす。
# 2-3. 絵を描いたり、判定したりする。
# img01 を (10, 10) の位置に描画する。
screen.blit(img01, (10, 10))
# img02 を (10, 10) の位置に描画する。
screen.blit(img02, (10, 10))
# 2-4. 画面を表示する。
pg.display.update()
# 2-5. 閉じるボタンが押されたら終了する。
for event in pg.event.get(): # イベント一覧を取得して、各イベントを調べる。
if event.type == pg.QUIT: # もし、閉じるボタンが押されたら。
pg.quit() # PyGame を終了する。これだけではウィンドウは閉じない。
sys.exit() # ウィンドウを閉じて、プログラムを終了する。
文字を描画する #
参考書1 p.126(Chapter 1.3)PyGame は図形もしくは画像しか表示できません。 そのため、文字を描画するには、文字を画像に変換してから表示することになります。 PyGame で文字を表示する手順は次の通りです。
- フォントを用意する。
- そのフォントを用いて、文字列の画像を生成する。
- 生成した画像を描画する。
1. フォントを用意する #
PyGame でフォントを用意するには、pg.font.Font で、フォント名と文字サイズを指定して読み込みます。
デフォルトのフォントを用いるには、pg.font.Font(None, 12) のようにフォント名のところを None にすることで読み込みます。
ただし、デフォルトのフォントでは日本語を扱えません。
もし、日本語を使いたい場合は、pg.font.SysFont 関数を用いてシステムのフォントを利用するよう指示します。
- Windows
msgothicmsuigothicmspgothicmenryomeiryomeiryouimenryountainc
- macOS
hiraginosansgbfottsukuardgothicstde
df = pg.font.Font(None, 50) # デフォルトのフォントを大きさ50で利用する。日本語は使えない。
jf = pg.font.SysFont("hiraginosansgb", 50) # システムフォントを利用する。環境に応じて読み替えること。
2. そのフォントを用いて、文字列の画像を生成する #
文字列の画像を生成するには、pg.font.Fontもしくは pg.font.SysFont で得られた Font 型のオブジェクトに対して、render メソッドを呼び出します。
render の引数は、表示させたい文字列、True/False、そして、文字の色です。
2番目の引数の True/False は文字を滑らかにする指定です(アンチエイリアス処理)。
3番目の引数で文字の色を指定します。例えば、pg.Color("RED") などで指定できます。
得られた文字列の画像は、通常の画像と同じように、blit 関数にて描画します。
例題11-3. 文字列を表示するプログラム #
以下のプログラムのコメントにあうようにプログラムを書き加えて、画像を表示するプログラムを完成させましょう(draw_string.py)。
import pygame as pg # PyGame をインポートし、pg という名前で使えるようにする。
import sys # sys モジュールをインポートする(終了処理で使う)。
# 1. ゲームの準備をする。
pg.init()
screen = pg.display.set_mode((800, 600))
dFont = # デフォルトのフォント、大きさ 50 のオブジェクトを得る。
sFont = # システムのフォント、大きさ 50 のオブジェクトを得る。
img01 = # Hello World をデフォルトのフォントを用いて画像化する(青色)。
img02 = # 「こんにちは! PyGame」をシステムのフォントを用いて画像化する(赤色)。
# 2. メインループ
while True:
# 2-1 画面を初期化する。
screen.fill(pg.Color("WHITE")) # 画面を白色で塗りつぶす。
# 2-3. 絵を描いたり、判定したりする。
# img01 を (10, 10) の位置に描画する。
# img02 を (10, 100) の位置に描画する。
# 2-4. 画面を表示する。
pg.display.update()
# 2-5. 閉じるボタンが押されたら終了する。
for event in pg.event.get(): # イベント一覧を取得して、各イベントを調べる。
if event.type == pg.QUIT: # もし、閉じるボタンが押されたら。
pg.quit() # PyGame を終了する。これだけではウィンドウは閉じない。
sys.exit() # ウィンドウを閉じて、プログラムを終了する。
実行結果は次のようになります。 システムのフォントによっては文字の形が多少異なるかもしれません。
完成すれば、render の第2引数の True/False を変更してみたり、違うフォントを試してみたりしましょう。
🏁 解答例
import pygame as pg # PyGame をインポートし、pg という名前で使えるようにする。
import sys # sys モジュールをインポートする(終了処理で使う)。
# 1. ゲームの準備をする。
pg.init()
screen = pg.display.set_mode((800, 600))
# デフォルトのフォント、大きさ 50 のオブジェクトを得る。
dFont = pg.font.Font(None, 50)
# システムのフォント、大きさ50のオブジェクトを得る。
sFont = pg.font.SysFont("hiraginosansgb", 50)
# Hello World をデフォルトのフォントを用いて画像化する(青色)。
img01 = dFont.render("Hello World", True, pg.Color("BLUE"))
# 「こんにちは! PyGame」をシステムのフォントを用いて画像化する(赤色)。
img02 = sFont.render("こんにちは! PyGame", True, pg.Color("RED"))
# 2. メインループ
while True:
# 2-1 画面を初期化する。
screen.fill(pg.Color("WHITE")) # 画面を白色で塗りつぶす。
# 2-3. 絵を描いたり、判定したりする。
# img01 を (10, 10) の位置に描画する。
screen.blit(img01, (10, 10))
# img02 を (10, 100) の位置に描画する。
screen.blit(img02, (10, 100))
# 2-4. 画面を表示する。
pg.display.update()
# 2-5. 閉じるボタンが押されたら終了する。
for event in pg.event.get(): # イベント一覧を取得して、各イベントを調べる。
if event.type == pg.QUIT: # もし、閉じるボタンが押されたら。
pg.quit() # PyGame を終了する。これだけではウィンドウは閉じない。
sys.exit() # ウィンドウを閉じて、プログラムを終了する。