見出し画像

[Pyxel] ゲームシーンの切替方法

ゲームには様々な画面(=シーン)がありますよね。

会社ロゴが出てくるスプラッシュに始まり、タイトル、キャラ作成、オープニング、キャンプ、調理、就寝、倉庫、などなど沢山のシーンが存在するゲームは多いかと思います。
始めて作ったゲームもどきはタイトルもなく、ゲーム、クリアの2画面でした。

DQのメニューはシーンの上に乗っかる存在だと思いますが、FF系の専用メニュー画面に切り替わるタイプは1つのシーンの位置付けかと思います。

そういった様々なシーンに応じて実行するプログラム箇所も変わります。
この実行箇所切替、以前はIDで分岐させてました。

    #Pyxel Update処理
    def update(self):
        try:
            match self.now_scene:
            #タイトル画面
                case 0:
                    self.menu.update()
                    return
            #キャラ選択
                case 10:
                    if not self.menu.update():

とかいう感じで。
これが「case 〇〇画面のID:」という感じで延々続きます。上記サンプルのゲームでは分岐が十数個発生してて、update関数の中身は500行程ありました。怖いですね。
修正したい時に、メニューの分岐はどこだ~~~っと探して修正して、ステップ実行しながらデバッグしてる間にも分岐はどこだ~~~って探して、探して、探して探してさがしてさがしさがさがさがさが千葉滋賀佐賀

まあ面倒この上ないというのは想像に難くないと思います。

最初のゲームはそれほど複雑じゃなかったのですが、RPGはやっぱりやる事が色々あって状況その時々の内容が全然違って、それが一つの関数にずらっと並んでるのは見通しが悪すぎました。

この対策として最初に考えたのが「シーンごとの処理をそれぞれ別関数に切り出す」だったんです。

が。

結局あんまり見通しよくならないんですよね。
責務として、とか今なら考えるんですけど当時は単に見易さが上がればよくって、でも同じクラス内にデカい関数が沢山書いてあって結局見に行くのは手間。操作で多少楽とは言っても長すぎてすぐ見失っちゃう。

そういう紆余曲折を経て試案した末に辿り着いたのが「スタック方式」でした。

各シーンをスタックに詰め込んで、例えばタイトルからニューゲーム、ならニューゲームでキャンセルボタン押せばニューゲームシーンをpopすればスタックにはタイトルシーンが残ってるのでそのままさっきの続きが可能。
エネミーエンカウントがあればバトルシーンをpushして、戦闘が終わったらバトルシーンをpopすればさっきのフィールド状態へ。キャラのアドレスや向き等、後から復旧するのではなく「もともとそこにあったものへそのまま戻る」という流れが可能になります。

さく:くろおど

このスタック方式を思い付いてから、DQ式メニューの前後管理もこの方式にしました。バトルシーンの各キャラ動作もコマンドスタックを準備して、みんなが行動を決めたらイニシアチブ順に処理できるようスタック(コマンドはFIFOのデキュー)で処理したり。
思想が流用出来たお陰で実装のイメージもすぐ湧いて、機能実現までがなかなか早かったです。


というような事などなどは・・・

長らくゲーム作ってるような方からすれば「は?当然っしょ?」と思うような事なんでしょうかねえ?気の向くままプログラムを書いているので、知らない「当たり前」がいっぱいあるんだろうとは思います。
基本のキを学ぼうと、Pyxel開発者北尾さんの著書を買って写本したり改変して喜んだり(昔ベーマガでやってたように)遊びながら学んではみたのですが。。。修行の道は遠いですね。
AIにやって貰えば早いんでしょうけど、プログラムを書く・書けるようになる、を楽しんでるので。

これからものんびりPyxelライフを楽しんでいこうと思います。