PythonとPygameで作る レトロ風RPG 全コード

同人誌について

 この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。

 同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。

(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)


11-4 進行2 自分の行動

公開:2024-09-02

説明と全体コード

 「src/mymod/scene_battle/proc/my.py」の説明です。自分のアクションをおこなう関数群です。開始、描画、終了があります。

import pygame
from ... import data
from .. import battle, effect
from . import enemy, growth
from ...image.dialog import a_show
from ...game.audio import play_bgm, play_se
from ...game.scene import Manager
from .. 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 pygame
from ... import data
from .. import battle, effect
from . import enemy, growth
from ...image.dialog import a_show
from ...game.audio import play_bgm, play_se
from ...game.scene import Manager
from .. 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!"

自分のアクションを開始1 アクションの決定

 次は自分のアクションを開始する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を決定します。

自分のアクションを開始2 逃走とMP不足

 中盤です。

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不足のメッセージを表示して、メニュー選択に戻ります。

自分のアクションを開始3 SEとエフェクトと進行

 終盤です。

# 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.procPROC_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 に更新)

 技術系同人誌など まとめページ


トップページに戻る
Cronus Crown(クロノス・クラウン)のトップページに戻る
(c)2002-2024 Cronus Crown (c)1997-2024 Masakazu Yanai
ご意見・お問い合わせはサイト情報 弊社への連絡までお願いします
個人情報の取り扱い、利用者情報の外部送信について