この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。
(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)
「src/mymod/image/screen.py」の説明です。画面描画の基礎になる関数群です。
『Pygame』の例として紹介したプログラムでは、画面を作ったあと、スクリーンに直接描画をおこなっていました。この本で作るゲームでは、小さなバッファに描画をおこないます。そして、各フレームの最後に拡大してスクリーンに描画します。そうしたことをおこなうための関数群が、「screen.py」に入っています。
import pygamefrom ..data.app import W, H, TITLE, IMAGE_ICON
buffer: pygame.Surface = pygame.Surface((W, H))
# ウィンドウの初期化def init_win(): # 開始画面サイズの計算と画面の作成 d = pygame.display.get_desktop_sizes()[0] scale = min(d[0] * 0.8 // W, d[1] * 0.8 // H) # 開始倍率 size = (W * scale, H * scale) # 開始画面サイズ pygame.display.set_mode(size, pygame.RESIZABLE) # 画面作成
# ウィンドウの設定 pygame.display.set_caption(TITLE) # タイトルバー icon = pygame.image.load(IMAGE_ICON) pygame.display.set_icon(icon) # アイコン
# バッファ取得def get_buffer() -> pygame.Surface: return buffer
# 更新の前処理def update_pre(): pygame.display.update() # 画面を更新
# 画面の消去def clear(): buffer.fill(pygame.Color(0, 0, 0)) # 画面を塗りつぶす
# 更新の後処理def update_post(): # 拡大率を計算して、バッファを拡大 win = pygame.display.get_window_size() scale = min(win[0] / W, win[1] / H) dst = (W * scale, H * scale) scaled_buffer = pygame.transform.scale(buffer, dst)
# オフセット位置を計算して描画 offset = ((win[0] - dst[0]) / 2, (win[1] - dst[1]) / 2) screen = pygame.display.get_surface() screen.blit(scaled_buffer, offset)
pygame.display.flip() # 画面フリップ
インポート部分を示します。
import pygamefrom ..data.app import W, H, TITLE, IMAGE_ICON
data
パッケージから、横幅のW
、高さのH
、タイトルのTITLE
、アイコン用画像のパスのIMAGE_ICON
を読み込みます。
このモジュールでは、ゲーム画面を作るために小さなSurface
を作り、そこに描画をおこないます。そのために用いるSurface
を作り、変数buffer
に格納します。
buffer: pygame.Surface = pygame.Surface((W, H))
次はウィンドウの初期化です。まずは画面作成の部分です。
# ウィンドウの初期化def init_win(): # 開始画面サイズの計算と画面の作成 d = pygame.display.get_desktop_sizes()[0] scale = min(d[0] * 0.8 // W, d[1] * 0.8 // H) # 開始倍率 size = (W * scale, H * scale) # 開始画面サイズ pygame.display.set_mode(size, pygame.RESIZABLE) # 画面作成
pygame.display.get_desktop_sizes()
関数でディスプレイのサイズを得ます。関数のあとに[0]
を書いているのは、関数の戻り値のリストの0番目の要素(0番目のディスプレイ、主要なディスプレイ)を得ているためです。この値を変数d
に代入します。
次に、ディスプレイの横幅d[0]
の0.8
倍を、ゲーム画面の横幅W
で割って整数にします。また、ディスプレイの高さd[1]
の0.8
倍を、ゲーム画面の高さH
で割って整数にします。そしてmin()
関数を使い、2つの値の小さい方を得て、開始時の拡大率scale
に代入します。
続いて、拡大率scale
をもとに、開始画面サイズsize
を計算します。そしてpygame.display.set_mode()
関数で画面を作成します。
画面作成では、pygame.display.set_mode()
の第2引数に、pygame.RESIZABLE
を設定します。第2引数には、いくつかの設定を|
繋ぎで書けます。ここでは、リサイズ可能にするpygame.RESIZABLE
のみを書きます。
リサイズ可能にしても、『Pygame』は描画サイズを自動で調整してくれません。そのため、自分で拡大描画する必要があります。
次は、ウィンドウの設定です。
# ウィンドウの設定 pygame.display.set_caption(TITLE) # タイトルバー icon = pygame.image.load(IMAGE_ICON) pygame.display.set_icon(icon) # アイコン
タイトルバーの文字を設定します。また、ウィンドウ左上用のアイコン画像(PNG画像)を読み込み、セットします。
次は、バッファの取得、更新の前処理、画面の消去といった小さな処理の関数です。
処理自体はそれぞれ1行ですが、外部から抽象化して呼び出せるように関数化しています。
# バッファ取得def get_buffer() -> pygame.Surface: return buffer
# 更新の前処理def update_pre(): pygame.display.update() # 画面を更新
# 画面の消去def clear(): buffer.fill(pygame.Color(0, 0, 0)) # 画面を塗りつぶす
最後は更新の後処理です。
# 更新の後処理def update_post(): # 拡大率を計算して、バッファを拡大 win = pygame.display.get_window_size() scale = min(win[0] / W, win[1] / H) dst = (W * scale, H * scale) scaled_buffer = pygame.transform.scale(buffer, dst)
# オフセット位置を計算して描画 offset = ((win[0] - dst[0]) / 2, (win[1] - dst[1]) / 2) screen = pygame.display.get_surface() screen.blit(scaled_buffer, offset)
pygame.display.flip() # 画面フリップ
ウィンドウのサイズから拡大率を計算して、サイズを拡大したバッファを作成します。そして、画面の中央に描画するようにオフセット位置を計算して、スクリーンへの描画をおこないます。
ウィンドウ サイズはpygame.display.get_window_size()
関数で得ます。ウィンドウに内接する拡大率scale
を計算して、拡大後のサイズdst
を求めます。このサイズdst
をもとに、バッファを拡大したSurface
を、pygame.transform.scale()
で得ます。
スクリーンのSurface
は、pygame.display.get_surface()
関数で得ます。『Pygame』のサンプルでは、pygame.display.set_mode()
の戻り値でスクリーンを得ていましたが、こうした関数でも得られます。
次の内容については省略します。こちらは同人誌をご覧ください。
この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。
(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)