2023-10-10に更新

Godot で一時停止を実装しようぜ(^~^)?

親記事から来た

📖 Godot って何だぜ(^~^)?

はじめに

ramen-tabero-futsu2.png
「 例えば エスケープ・キーを押したら ゲームがピタッと 一時停止するような、制御を練習しようぜ?」

kifuwarabe-futsu.png
「 ポーズ機能ぐらい 標準で実装されてないのか? 先に調べてみろだぜ」

ramen-tabero-futsu2.png
「 調べていて でてきたんだが BGM って和製英語で 海外人に通じないみたいだな」

ohkina-hiyoko-futsu2.png
「 和製英語で検索するのは 止めなさい」

ramen-tabero-futsu2.png
「 そんなん言ったって 和製英語を通じて 世の中を見てるし できあがった土台を疑うのは大変だぜ」

kifuwarabe-futsu.png
「 👇 ポーズ機能は フレームワークで用意されているようだぜ」

📖 GODOT DOCS / Pausing games and process mode

ramen-tabero-futsu2.png
「 説明読んでも分からんし、使って覚えるかあ」

ルートを停止すると、ルートも止まる

func _unhandled_key_input(event):

    #   何かキーを押したとき
    if event.is_pressed():

        #   エスケープ・キー
        if event.keycode == KEY_ESCAPE:

            if not get_tree().paused:
                # 全体を止める
                get_tree().paused = true
            else:
                # 全体を止めているのを解除
                get_tree().paused = false

ramen-tabero-futsu2.png
「 👆 ルートで 木を停止すると、ルートも止まるので 上記のコードでは 一時停止を解除できない」

kifuwarabe-futsu.png
「 矛盾が無いぜ」

ohkina-hiyoko-futsu2.png
「 素直な挙動だから、これで 狙って指定したノードだけ 一時停止できそうね」

どのノードを止めたらゲームが止まるの?

ohkina-hiyoko-futsu2.png
「 どのノードを止めたらゲームが止まるの?」

ramen-tabero-futsu2.png
「 アミバみたいだな」

202310__godot__09-1437--Tree.png

ramen-tabero-futsu2.png
「 👆 どのノードを止めるといった 分け方をしてないしな」

kifuwarabe-futsu.png
「 なんか よく分からんなあ。 お父ん、いったん 思うように 再構成してみてくれだぜ」

ツリーを再構成しようぜ?

202310__godot__09-1445--ScenarioWritere-o2o0.png

ramen-tabero-futsu2.png
「 👆 ゲーム制作の チーム作業を 模擬して、
第2階層のフォルダーには 誰がそのフォルダーを開ければいいのかが分かるように
役職名を書いていこう」

ohkina-hiyoko-futsu2.png
「 ある種の ダイナミック・プログラミング(Dynamic Programming;動的計画法)を行うのね」

kifuwarabe-futsu.png
「 手の付けやすいところを先に固めていけば 難しい所が最後に残るわけか」

202310__godot__09-1457--BackgroundArtist-o2o0.png

ramen-tabero-futsu2.png
「 👆 Background も、 BackgroundArtist にリネームしよう」

202310__godot__09-1510--LocationCoordinator-o2o0.png

ramen-tabero-futsu2.png
「 👆 Scenes も、 LocationCoordinator にリネームしよう」

202310__godot__09-1517--Windows-o2o0.png

kifuwarabe-futsu.png
「 ウィンドウって 誰の仕事なんだぜ?」

ramen-tabero-futsu2.png
「 誰なんだろな?」

ohkina-hiyoko-futsu2.png
「 マシ―ナリー(machinery;機械装置)なんじゃないの?」

ramen-tabero-futsu2.png
「 ウィンドウは、わたしの思っている機械と違う」

ramen-tabero-futsu2.png
「 👇 スクウェアエニックス 中途採用 ゲーム開発 で検索。
どんな職種があるか 調べたろ」

📖 募集中の職種

ramen-tabero-futsu2.png
「 UI デザイナー と、 UI アーティスト は何が違うんだぜ? 表記ゆれ?」

kifuwarabe-futsu.png
「 デザイナーと アーティストの違いが さっぱり分からん。
実態は どう違うんだぜ?」

ramen-tabero-futsu2.png
「 アーティストは 自分勝手なやつで、
デザイナーは 顧客が思っていた本当に欲しかったものとは違うものを作ってくる勝手なやつじゃないのか?」

kifuwarabe-futsu.png
「 だから 違いが分からん」

ohkina-hiyoko-futsu2.png
「 👇 調べましょう」

📖 デザイナーとアーティストの違いって? 実は存在目的が明確に違うんです!

ramen-tabero-futsu2.png
「 アーティストは その人本人に価値があって それを会社側が ゲヘヘ と下心をこめて利用するもので、
デザイナーは 下請けか」

kifuwarabe-futsu.png
「 お父んの頭では それぐらいの理解が 精一杯だな」

ohkina-hiyoko-futsu2.png
「 あんたは どの役職なら入れそうなの?」

ramen-tabero-futsu2.png
「 ゲーム制作は専門技術なんで、それ用の技術を持ってないので どこも無理だぜ」

kifuwarabe-futsu.png
「 なんで そんなやつが きふわらべRPG 作ろうとするんだぜ?」

ramen-tabero-futsu2.png
「 DesignerArtist だと、 Artist の方が つづりが短いから こっちを採用しよう」

ramen-tabero-futsu2.png
「 あと UI は意味が広すぎる。 GUI にしよう」

202310__godot__09-1551--GuiArtist-o2o0.png

ramen-tabero-futsu2.png
「 👆 他の職業は 制作の裏方さんという感じなのに、
GuiArtist は 本番中に めっちゃ 働くんだけど」

kifuwarabe-futsu.png
「 実態は ウィンドウだからな」

ohkina-hiyoko-futsu2.png
「 裏方と オン・エアで 大分類を切った方がベターなのかしらねえ?」

ramen-tabero-futsu2.png
「 そこは あとで考えよう」

202310__godot__09-1556--SecondFolders.png

ramen-tabero-futsu2.png
「 👆 第2階層は こんな感じでどうだぜ?」

ohkina-hiyoko-futsu2.png
「 オンエアが始まる前に仕事が終わってる人たちと、
オンエアに仕事をしてる人たちで 別れるんじゃないの?」

ramen-tabero-futsu2.png
「 上演中にシナリオを書き換えるシェークスピアみたいなやつとか 分類できないだろ」

kifuwarabe-futsu.png
「 ツリー構造には向いてないなあ」

自律するかどうか

kifuwarabe-futsu.png
「 現状の実装では ユーザーがキー入力すると
メッセージ・ウィンドウへ送られ、
台本の次の行が読み込まれ、それに従って さらに動く、
オートマタが 完成しているのが、 一時停止を都合悪くする原因だろう」

ramen-tabero-futsu2.png
「 自律 するかどうかより 連続 かどうかが問題だぜ。
連続に 切れ目なんか無いぜ」

ohkina-hiyoko-futsu2.png
「 停止した瞬間は どんな状態にあるの?」

ramen-tabero-futsu2.png
「 数学的には 無限の狭間を永遠に彷徨っていて定まらないと思うが、
情報処理的には プログラム・カウンターが止まっているところだぜ」

kifuwarabe-futsu.png
「 都合のわるい所、変なところであったとしても、
止まっているノードに対して 編集を行わず、かつ、行う処理が 再開 だけなのであれば
問題は起こらないと思うぜ」

ramen-tabero-futsu2.png
「 それを保証する仕組みが あるかどうか分からん」

状態を持つものと、持たないもの

ohkina-hiyoko-futsu2.png
「 状態を持つものと、持たないものがあるのよ」

ramen-tabero-futsu2.png
「 そうそう」

kifuwarabe-futsu.png
「 Godot の GUI の思想が中途半端なんだぜ。
位置情報のような固定できる設定と、
メッセージ表示のような ランタイム時に状態を持つ設定が 分かれていない」

ramen-tabero-futsu2.png
「 今どきのエディター、ほとんどの素材が ダイナミックだしな」

ohkina-hiyoko-futsu2.png
「 ラベルなどのコントロールは CanvasLayer の下に管理される前提よね」

kifuwarabe-futsu.png
「 入力系や 自律的な系は DirectorAssistantDirector に抑えさせよう。
他は 指示待ちで」

階層は浅く

202310__godot__09-1645--GuiArtistFolder-o2o0.png

ohkina-hiyoko-futsu2.png
「 👆 GuiArtist のフォルダーが深くて 開けるのが手間よ」

202310__godot__09-1659--GuiArtistFolderToShallow-o2o0.png

ramen-tabero-futsu2.png
「 👆 少し浅くしたぜ」

時間軸で勝手に動いているもののうち、邪魔なものは止めろだぜ

ramen-tabero-futsu2.png
「 何を pause すればいいのか分かってきた……、
入力は一元的に抑え、
時間軸で勝手に動いているもののうち、邪魔なものを止めればいいんだぜ」

ohkina-hiyoko-futsu2.png
「 今の実装だと ブリンカー ぐらいねえ」

ramen-tabero-futsu2.png
「 停止する世界と 停止しない世界 が共存していえ、
デッドロックしない仕組みを どう実現しているのか 分からないが……」

kifuwarabe-futsu.png
「 容赦なくデッドロックするんだぜ。
勝手に上手く停止させろよ、という方針なのだろうなんだぜ」

ramen-tabero-futsu2.png
「 パイトニックだな……」

全部止まった

$"GuiArtist".get_tree().paused = true

ramen-tabero-futsu2.png
「 👆 ウィンドウだけ止めようと思って .get_tree().paused = true したら、音楽も止まった……」

ohkina-hiyoko-futsu2.png
「 サブ・ツリーだけ 止められないの?」

ramen-tabero-futsu2.png
「 👇 .get_tree().paused は、ゲーム全体を止めるものらしいぜ」

📖 【Godot】オブジェクトを一時停止する方法

kifuwarabe-futsu.png
「 思ってたものと違うな」

ohkina-hiyoko-futsu2.png
「 .set_process(false) を使うと、 _process(delta) が呼び出されなくなるそうよ」

ramen-tabero-futsu2.png
「 使ってみるか……」

ramen-tabero-futsu2.png
「 メソッドを呼び出したノードだけ一時停止して、その子ノードは一時停止しない……」

kifuwarabe-futsu.png
「 子ノードまで再帰的に止めるオプションは無いのかだぜ?」

ramen-tabero-futsu2.png
「 👇 無いぜ」

📖 GODOT DOCS / set_process

ohkina-hiyoko-futsu2.png
「 じゃあ メソッドを自作ねえ」

ノード毎にメソッドを自作

202310__godot__10-0254--PauseSubtree.png

ramen-tabero-futsu2.png
「 👆 この書き方 かっこよくね?」

kifuwarabe-futsu.png
「 ちゃんと動くのかな?」

202310__godot__10-0304--ProcessSubtree.png

ramen-tabero-futsu2.png
「 👆 Godot の習慣に合わせると、こっちの 書き方の方がいいか?」

ノードが自作のメソッドを持っているか確認

ramen-tabero-futsu2.png
「 👇 ダック・タイピング できるのか」

📖 How to check have the node a custom function?

#   サブツリーの is_process を設定。ポーズ(Pause;一時停止)の逆の操作
func set_process_subtree(is_process):
    print("[テキストブロック] プロセッシング:" + str(is_process))

    #   処理しろ (true) という指示のとき、処理していれば  (true) 、何もしない(pass)。
    #   処理するな(false)という指示のとき、処理していれば  (true) 、停止する (false)。
    #   処理しろ (true) という指示のとき、処理していなければ(false)、再開する (true)。
    #   処理するな(false)という指示のとき、処理していなければ(false)、何もしない(pass)
    if is_process != self.is_processing():
        self.set_process(is_process)

        #   子ノード
        for child in self.get_children():
            if child.has_method("set_process_subtree"):
                child.set_process_subtree(is_process)

ramen-tabero-futsu2.png
「 👆 これを 各ノードのスクリプトに貼り付けていけば良さげ、めんどくせ」

ramen-tabero-futsu2.png
「 👇 ポーズ・ボタンを実装したぜ」  

📺 動画

親記事へ戻る

📖 Godot って何だぜ(^~^)?

.

ツイッターでシェア
みんなに共有、忘れないようにメモ

むずでょ

光速のアカウント凍結されちゃったんで……。ゲームプログラムを独習中なんだぜ☆電王戦IIに出た棋士もコンピューターもみんな好きだぜ☆▲(パソコン将棋)WCSC29一次予選36位、SDT5予選42位▲(パソコン囲碁)AI竜星戦予選16位

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント