10-3 移動
同人誌について
この連載は、同人誌『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 pygame
from .. import data, game, image
from . import event
MOVE_CYCLE = 250
last_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 pygame
from .. import data, game, image
from . import event
定数と変数
`MOVE_CYCLE`は、1マス歩くのにかかるミリ秒です。
`last_move`は、最終移動時間です。この時間から`MOVE_CYCLE`のミリ秒が経過したら、次のマスに移動します。
MOVE_CYCLE = 250
last_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`を決定します。また、移動先が水のマス(侵入不可マス)の場合は、移動先を直前のマスに戻します。
次の内容については省略します。こちらは同人誌をご覧ください。
10-4 イベント管理
10-5 描画1 キャラクター
10-6 描画2 土地
10-7 描画3 アイテム
10-8 描画4 ミニ マップ
10-9 描画5 その他の表示
同人誌について
この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで290ページの本になります。ぜひ、こちらもご購入ください。
(2024-03-28:ver1.0.4 に更新、2024-03-10:ver1.0.3 に更新)
このnoteの記事と、Webページに一部抜粋版を掲載しています。
技術系同人誌など まとめページ
この記事が気に入ったらサポートをしてみませんか?