 
      
      
この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。
(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)
「src/mymod/scene_battle/proc/my.py」の説明です。自分のアクションをおこなう関数群です。開始、描画、終了があります。
import pygamefrom ... import datafrom .. import battle, effectfrom . import enemy, growthfrom ...image.dialog import a_showfrom ...game.audio import play_bgm, play_sefrom ...game.scene import Managerfrom .. import main  # 型ヒント用
MES_ESC_SUCCESS = "逃げるのに\n成功しました"MES_ESC_FAIL = "逃げるのに\n失敗しました"MES_MP_FAIL = "MPが足りません"MES_WIN = "%sを\n倒しました"MES_ENDING = "あなたは王国を\n救いました"MES_ENDING2 = "Congratulations!\nYou are the hero!"
# 自アクション開始async def start(p: "main.SceneBattle"):    action = p.menu.texts[p.menu.sel]    r = p.res = battle.my.exec(action)  # 自行動実行
    if r.is_escape == True:   # 逃走        if r.success_escape == True:    # 逃走成功            await a_show(MES_ESC_SUCCESS)            Manager.set_next(data.scene.MAP)        else:   # 逃走失敗            await a_show(MES_ESC_FAIL)            enemy.start(p)        return
    if r.success_mp == False: # MP不足        await a_show(MES_MP_FAIL)        return
    # SEとエフェクト表示    play_se(r.se)   # SE再生    effect.manage.init()    a = data.action    if r.action == a.SWORD : p.enemy.shake(True)    if r.action == a.FIRE  : p.enemy.shake(True)    p.proc = data.battle.PROC_MY_DRAW
# 自アクション描画async def draw(r: data.battle.Res, screen: pygame.Surface):    is_end = effect.manage.draw(r.action, screen)    effect.sub.draw_num(screen, r.res_num)    return is_end
# 自アクション終了async def end(p: "main.SceneBattle"):    p.enemy.shake(False)      # 敵の揺れを終了
    if battle.util.is_enemy_death():    # 敵死亡→勝利        pygame.time.wait(500)        e = data.enemy.enemy_now        if e.is_last == False:            # 通常の敵            play_bgm(data.audio.WIN)            await a_show(MES_WIN % e.name + "\n" + growth.growth())            Manager.set_next(data.scene.MAP)        else:            # ラスボス            play_bgm(data.audio.ENDING)            await a_show(MES_WIN % e.name)            await a_show(MES_ENDING)            await a_show(MES_ENDING2)            Manager.set_next(data.scene.TITLE)        return
    enemy.start(p)  # 敵の行動を開始まずはインポート部分を示します。かなり多いです。モジュール内の行数が多いので、その分だけ利用するモジュールがあります。
import pygamefrom ... import datafrom .. import battle, effectfrom . import enemy, growthfrom ...image.dialog import a_showfrom ...game.audio import play_bgm, play_sefrom ...game.scene import Managerfrom .. import main  # 型ヒント用 data battle effectパッケージ、enemy growthモジュールを読み込みます。
 また、プログラムを短く書くためにa_show play_bgm play_se関数、Managerクラスを直接読み込みます。
 型ヒント用にmainモジュールも読み込みます。
定数部分です。各種のメッセージです。ダイアログ表示に使います。
MES_ESC_SUCCESS = "逃げるのに\n成功しました"MES_ESC_FAIL = "逃げるのに\n失敗しました"MES_MP_FAIL = "MPが足りません"MES_WIN = "%sを\n倒しました"MES_ENDING = "あなたは王国を\n救いました"MES_ENDING2 = "Congratulations!\nYou are the hero!" 次は自分のアクションを開始するstart()関数です。かなり長いので、序盤と中盤と終盤に分けます。
まずは序盤です。関数定義とアクションの決定です。
# 自アクション開始async def start(p: "main.SceneBattle"):    action = p.menu.texts[p.menu.sel]    r = p.res = battle.my.exec(action)  # 自行動実行 現在のカーソル位置p.menu.selから、行動actionを決定します。
中盤です。
    if r.is_escape == True:   # 逃走        if r.success_escape == True:    # 逃走成功            await a_show(MES_ESC_SUCCESS)            Manager.set_next(data.scene.MAP)        else:   # 逃走失敗            await a_show(MES_ESC_FAIL)            enemy.start(p)        return
    if r.success_mp == False: # MP不足        await a_show(MES_MP_FAIL)        return メニューで「ESCAPE」を選んだとき(res.is_escape == Trueのとき)は、逃走の結果(res.is_escape_success)によって処理を分岐します。
 また、魔法を選んでMPが足りないとき(res.mp_success == Falseのとき)は、MP不足のメッセージを表示して、メニュー選択に戻ります。
終盤です。
    # SEとエフェクト表示    play_se(r.se)   # SE再生    effect.manage.init()    a = data.action    if r.action == a.SWORD : p.enemy.shake(True)    if r.action == a.FIRE  : p.enemy.shake(True)    p.proc = data.battle.PROC_MY_DRAW有効な行動が実行されれば、SEを鳴らして、エフェクトを初期化して、進行を描画に移行します。
 攻撃時(SWORD FIREのとき)は、p.enemy.shake(True)を実行して敵を揺らします。
 進行を描画に移行するには、p.procをPROC_MY_DRAWに変更します。
 次は、自分のアクションの描画をおこなうdraw()関数です。
# 自アクション描画async def draw(r: data.battle.Res, screen: pygame.Surface):    is_end = effect.manage.draw(r.action, screen)    effect.sub.draw_num(screen, r.res_num)    return is_end effect.manage.draw()関数でエフェクトを描画します。実行結果がTrueのときは描画が終了しています。実行結果は変数is_endに代入して、戻り値としてreturn文で返します。
 また、effect.sub.draw_num()関数で、数字を描画します。
 この描画をおこなうdraw()関数は、エフェクトが終わるまで繰り返し呼び出されます。
 自分のアクションの終了をおこなうend()関数です。
# 自アクション終了async def end(p: "main.SceneBattle"):    p.enemy.shake(False)      # 敵の揺れを終了
    if battle.util.is_enemy_death():    # 敵死亡→勝利        pygame.time.wait(500)        e = data.enemy.enemy_now        if e.is_last == False:            # 通常の敵            play_bgm(data.audio.WIN)            await a_show(MES_WIN % e.name + "\n" + growth.growth())            Manager.set_next(data.scene.MAP)        else:            # ラスボス            play_bgm(data.audio.ENDING)            await a_show(MES_WIN % e.name)            await a_show(MES_ENDING)            await a_show(MES_ENDING2)            Manager.set_next(data.scene.TITLE)        return
    enemy.start(p)  # 敵の行動を開始 まず、p.enemy.shake(False)で敵の揺れを終了します。
敵が死んだときはメッセージを表示してシーンを移動します。この処理は、通常の敵とラスボスで分岐します。
通常の敵のときは、マップ シーンに移動します。ラスボスのときは、エンディング用のダイアログを複数出したあとタイトル シーンに移動します。
 敵が死んでいないときは、enemy.start()関数を実行して、敵の行動を開始します。
次の内容については省略します。こちらは同人誌をご覧ください。
この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。
(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)