SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

レトロ風ゲームを作って学ぶPython入門

【作って学ぶPython】ゲームを開発してみよう!タイトル、マップ画面の実装編

レトロ風ゲームを作って学ぶPython入門 第4回


  • X ポスト
  • このエントリーをはてなブックマークに追加

 自動化やAIなどさまざまな分野で活用され、需要が高いPython。この連載では、小さなレトロ風ゲームを作りながら、Pythonを学ぶことができます。第4回は、第3回までに学んだことを使った実践編です!今回はレトロ風RPGの前半部分として、タイトル画面とマップ画面を作成していきます。

  • X ポスト
  • このエントリーをはてなブックマークに追加

はじめに

 前回は、次のようなことを学びました。

  • Pythonの文法:関数
  • Pythonの文法:モジュールとパッケージ
  • Pygameのさまざまな機能

 今回からは実践編として、非常に小さなレトロ風RPGを作っていきます。

 ゲームは非常にシンプルなものです。主人公の勇者はマップの左上から旅を始めて、右下の魔王城に住む魔王を倒すとゲームが終了します。

 マップ移動中に遭遇する敵と戦闘することで、経験値が集まりキャラクターが成長します。街に着くとHPとMPが回復します。数分程度でクリアできるゲームとなっています。

スタートとゴール
スタートとゴール

 今回は、このレトロ風RPGの前半部分として、タイトル画面とマップ画面を作成します。コードを書く際のプログラムは、なるべく短くなるように心掛けます。

タイトル画面
タイトル画面
マップ画面
マップ画面

補助的モジュール

 まずは、ゲームの処理を補助するモジュールを3つ作ります。ゲームの基本データをまとめたモジュールと、画像の処理、音声の処理をおこなうモジュールです。

作成するモジュール
モジュール 内容
data.py 各種のデータ
img.py 画像の読み込みと他
audio.py 音声の読み込みと他

 ファイル構成は次のとおりです。新しいモジュールを作るときは、ここにファイルを足していきます。

ファイル構成
data.py
img.py
audio.py
image/
    chara.png
    land.png
font/
    PixelMplus12-Regular.ttf
audio/
    bgm/
        maou_bgm_8bit01.mp3
        (他略)
    se/
        maou_se_8bit22.wav

data.py

 まず解説するのは、各種のデータをまとめたdata.pyモジュールです。ゲーム共通で使うデータをここで定義します。

data.py
import pygame

# システム
U = 16 * 3      # 描画単位
W = 20 * U      # 横幅
H = 15 * U      # 高さ
screen = pygame.Surface((0, 0))     # スクリーン
key = {"down": None, "keep": {}}    # キー

# シーン  title, map, battle
scene = ""              # シーン
scene_next = "title"    # 次回更新

# 色
COL_B = (0, 0, 0)           # 黒
COL_BT = (0, 0, 0, 128)     # 黒半透明
COL_W = (255, 255, 255)     # 白
COL_G = (64, 64, 64)        # 灰

 それぞれの変数について解説します。

 Uはマップ1マスや、キャラクター1体の描画サイズです。この単位で描画をおこないます。Wはウィンドウの描画領域の横幅、Hは高さです。このサイズでウィンドウを作成します。

 screenは、ウィンドウの描画領域のSurfaceオブジェクトを保持します。まだウィンドウは作成していないので、ダミーでサイズ0Surfaceを代入します。のちほどこの変数には、初期化したウィンドウの描画領域を代入します。

 keyは、キーの状態を保持する辞書です。この変数には、描画ループごとにキーの状態を代入します。

 scenescene_nextは、画面(タイトル、マップ、バトル)の移動を管理する変数です。sceneは現在の画面の名前です。scene_nextは移動を予約するための名前です。のちほど作る処理で、scene_nextの値が書き換わると、表示する画面を変更します。

 COL_~は色のタプルです。黒、黒半透明、白、灰を用意しています。黒半透明だけ、要素が4つあります。4つ目の要素はアルファ値(透明度)です。

img.py

 画像の読み込みと分割、保持をおこなうimg.pyモジュールです。フォントの読み込みもおこないます。

img.py
import pygame, pygame.freetype, data

# 画像分割
def load(p):
    image = pygame.image.load(p)    # 画像読み込み
    w, h = image.get_size()         # 横幅、高さ取得
    unit = 16       # 画像ピクセル単位
    images = []     # 画像リスト
    for y in range(0, h, unit):
        for x in range(0, w, unit):
            # 1枚分のSurfaceを生成して貼り付ける
            piece = pygame.Surface((unit, unit), pygame.SRCALPHA)
            piece.blit(image, (0, 0), (x, y, unit, unit))

            # 拡大して画像リストに追加
            piece = pygame.transform.scale(piece, (data.U, data.U))
            images.append(piece)
    return images

chara = load("image/chara.png") # キャラクター
land  = load("image/land.png")  # 土地

fsz = 36    # フォント デフォルト サイズ
font = pygame.freetype.Font("font/PixelMplus12-Regular.ttf", fsz)   # フォント

 変数charalandに、キャラクターの画像と土地の画像 をリスト化したものを代入します。リスト内の画像は、16ピクセルずつに分割して、data.Uのサイズ(48ピクセル)に拡大したものです。

 それぞれの画像は、次のようなリストになります。

分割・拡大してリスト化した画像
分割・拡大してリスト化した画像
分割・拡大してリスト化した画像
分割・拡大してリスト化した画像

 分割と拡大とリスト化をおこなうのはload()関数です。「1枚分のSurfaceを生成して貼り付ける」処理、「拡大する」処理は、前回のPygameの画像描画で紹介した処理の応用です。

 いくつか、新しい内容が出てきているので解説します。

 image.get_size()関数は、Surfaceオブジェクトの横幅と高さのタプルを得ます。w, h = image.get_size()とすることで、戻り値のタプルを分割して、変数whに代入します。

 for y in range(0, h, unit):for x in range(0, w, unit):の入れ子の繰り返し処理は、初心者には少し難しい処理です。

 まず外側のrange(0, h, unit)について解説します。0から始まり、unitずつ値を増やして、h未満のあいだ処理をおこないます。こうすることで、変数yは、0から16ずつ大きくなり、画像の高さ未満のあいだ処理を繰り返します。

 同じように内側のrange(0, w, unit)は、0から始まり、unitずつ値を増やして、w未満のあいだ処理をおこないます。こうすることで、変数xは、0から16ずつ大きくなり、画像の横幅未満のあいだ処理を繰り返します。

 その結果、たとえばchara.pngの画像なら、次の順番で画像を取り出していきます。

画像を取り出す順番
画像を取り出す順番

 そしてpygame.transform.scale()関数で拡大して、images.append(scaled)でリストの末尾に追加していきます。

 このモジュールでは、フォントも読み込みます。

 フォントのデフォルトサイズfsz36にします。そして、パスを"font/PixelMplus12-Regular.ttf"、デフォルトサイズをfszで読み込み、変数fontに代入します。

audio.py

 音声のパスや読み込み、再生をおこなうaudio.pyモジュールです。音声は「魔王魂」さんの音声ファイルを利用します。

 プログラムを以下に示します。

audio.py
from pygame.mixer import Sound, music

FIELD       = "audio/bgm/maou_bgm_8bit01.mp3"   # 野原
BATTLE      = "audio/bgm/maou_bgm_8bit18.mp3"   # 戦闘
LOSE        = "audio/bgm/maou_bgm_8bit20.mp3"   # 敗北
ENDING      = "audio/bgm/maou_bgm_8bit22.mp3"   # エンディング
WIN         = "audio/bgm/maou_bgm_8bit24.mp3"   # 勝利
BATTLE_LAST = "audio/bgm/maou_bgm_8bit25.mp3"   # 最終戦闘

# BGM再生
def play(p):
    music.load(p)   # ロード
    music.play(-1)  # 繰り返し(-1)で再生

damage = Sound("audio/se/maou_se_8bit22.wav")   # ダメージ

 インポート部分では、pygame.mixerからSound, musicを読み込みます。続く前半は、BGM各音声ファイルのパスです。後半は、読み込みや再生処理です。

 BGMはパスだけ用意しておき、モジュール内で定義したplay()関数で読み込みと再生をおこないます。外部からはaudio.play(audio.FIELD)のように実行することで、指定のBGMを再生します。

 SEは事前にSound()で読み込んでおきます。外部からはaudio.damage.play()と実行することでSEを再生します。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
開始プログラムと各画面のファイル

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
レトロ風ゲームを作って学ぶPython入門連載記事一覧

もっと読む

この記事の著者

柳井 政和(ヤナイ マサカズ)

クロノス・クラウン合同会社 代表社員http://crocro.com/オンラインソフトを多数公開。プログラムを書いたり、ゲームを作ったり、記事を執筆したり、マンガを描いたり、小説を書いたりしています。「めもりーくりーなー」でオンラインソフト大賞に入賞。最近は、小説家デビューして小説も書いています(『裏切りのプログラム』他)。面白いことなら何でもOKのさすらいの企画屋です。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/19458 2024/06/10 12:22

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング