この連載は、同人誌『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 に更新)