この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。
(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)
「src/mymod/scene_map/move.py」の説明です。マップ上での移動を管理するモジュールです。上下左右のキーを押すことで、主人公を移動(マップをスクロール)させます。
import pygamefrom .. import data, game, imagefrom . import event
MOVE_CYCLE = 250last_move = 0
# 初期化def init(): global last_move last_move = pygame.time.get_ticks()
# 移動管理async def manage_move(key_keep: str): global last_move d = data.game.data time = pygame.time.get_ticks()
if time < last_move + MOVE_CYCLE: # 移動中処理 d.move_rate = (time - last_move) / MOVE_CYCLE return else: # 到着処理 last_move = time move_goal(d) # 到着処理
# イベント発生判定 res = event.try_exec(d.x, d.y) if res.type != event.NONE: await image.dialog.a_show(res.text) if res.type == event.BATTLE: game.scene.Manager.set_next(data.scene.BATTLE) return
move_next(key_keep, d) # 次回移動処理
# 到着処理def move_goal(d: data.game.Game): d.move_rate = 0 d.x = d.next_x d.y = d.next_y
# 次回移動処理def move_next(key_keep: str, d: data.game.Game): k = key_keep; e = game.event if k == e.K_LEFT and d.x > 0: d.next_x = d.x - 1 if k == e.K_RIGHT and d.x + 1 < d.map_w: d.next_x = d.x + 1 if k == e.K_UP and d.y > 0: d.next_y = d.y - 1 if k == e.K_DOWN and d.y + 1 < d.map_h: d.next_y = d.y + 1
# 水なら戻す i = d.next_x + d.next_y * d.map_w if d.data_map.map[i] == data.map.WATER: d.next_x = d.x d.next_y = d.y
まずはインポート部分を示します。
import pygamefrom .. import data, game, imagefrom . import event
MOVE_CYCLE
は、1マス歩くのにかかるミリ秒です。
last_move
は、最終移動時間です。この時間からMOVE_CYCLE
のミリ秒が経過したら、次のマスに移動します。
MOVE_CYCLE = 250last_move = 0
変数と、初期化をおこなうinit()
関数です。
# 初期化def init(): global last_move last_move = pygame.time.get_ticks()
初期化では、last_move
に、pygame.time.get_ticks()
関数を使って「ゲーム開始時点からの経過時間」を代入します。
次は移動管理をおこなうmanage_move()
関数です。キー押しっぱなしの状態を表すkey_keep
を引数にとります。
# 移動管理async def manage_move(key_keep: str): global last_move d = data.game.data time = pygame.time.get_ticks()
if time < last_move + MOVE_CYCLE: # 移動中処理 d.move_rate = (time - last_move) / MOVE_CYCLE return else: # 到着処理 last_move = time move_goal(d) # 到着処理
# イベント発生判定 res = event.try_exec(d.x, d.y) if res.type != event.NONE: await image.dialog.a_show(res.text) if res.type == event.BATTLE: game.scene.Manager.set_next(data.scene.BATTLE) return
move_next(key_keep, d) # 次回移動処理
前回移動からの経過時間がMOVE_CYCLE
未満なら、移動中処理として、GameData
のmove_rate
を更新します。
前回移動からの経過時間がMOVE_CYCLE
以上なら、到着と見なして、到着処理をおこないます。
次のマスに到着したときは、last_move
を更新します。そして、到着処理move_goal()
をおこない、イベント発生判定をおこなうevent.try_exec()
関数を実行します。そして結果をres
に代入します。
res.type
がevent.NONE
でない、つまりイベントが発生したときは、ダイアログを表示します。イベントの種類が戦闘のときは、バトル シーンに移動します。戦闘でも、そうでなくても、return
文で処理を打ち切ります。
イベントが発生しなかったときは、次回移動処理move_next()
関数を実行します。
到着処理move_goal()
を示します。
# 到着処理def move_goal(d: data.game.Game): d.move_rate = 0 d.x = d.next_x d.y = d.next_y
GameData
のmove_rate
を0
にリセットして、x
y
を更新します。
次回移動処理move_next()
を示します。
# 次回移動処理def move_next(key_keep: str, d: data.game.Game): k = key_keep; e = game.event if k == e.K_LEFT and d.x > 0: d.next_x = d.x - 1 if k == e.K_RIGHT and d.x + 1 < d.map_w: d.next_x = d.x + 1 if k == e.K_UP and d.y > 0: d.next_y = d.y - 1 if k == e.K_DOWN and d.y + 1 < d.map_h: d.next_y = d.y + 1
# 水なら戻す i = d.next_x + d.next_y * d.map_w if d.data_map.map[i] == data.map.WATER: d.next_x = d.x d.next_y = d.y
key_keep
の状態によって、次の移動マスnext_x
next_y
を決定します。また、移動先が水のマス(侵入不可マス)の場合は、移動先を直前のマスに戻します。
次の内容については省略します。こちらは同人誌をご覧ください。
この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。
(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)