見出し画像

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ページに一部抜粋版を掲載しています。

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


この記事が気に入ったらサポートをしてみませんか?