scenario-godot-2d について
scenario-godot-2dは、Godot 4.7.2で2Dゲームを制作・監査するエージェント向けスキルです。移動、カメラ、ピクセルアート、タイル、照明を数値化し、決定論的な実行と画面キャプチャで検証します。
主な機能
- 01計測可能な横スクロール・見下ろし操作
- 02ピクセルアートの拡大率とカメラ設定
- 03TileSet生成と地形監査
- 04スプライトとインポートの検証
- 05決定論的な物理・画面チェック
活用シーン
- 01目標の高さと時間に合わせたジャンプ調整
- 02ピクセル固定または滑らかなスクロール場面の作成
- 03地形の接続とスプライトの縁の確認
- 04固定フレームレートでの操作検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-godot-2dインストール後、Claude Code で/scenario-godot-2dを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/gd_2d.pyscripts/agentkit/2d/audit_2d.gddual_grid.gdfollow_camera_2d.gdparallax_tools.gdpixel_light.gdshaderpixel_viewport.gdplatformer_body.gdplatformer_tuning.gdsprite_frames_builder.gdterrain_tools.gdtileset_builder.gdtopdown_body.gd詳細
Godot 2D(開発者・アーティスト向け)
対象:Godot 4.7.2 の標準ビルド、macOS。scenario-godot-expert ツールキットを通じて、ヘッドレスまたは小さなウィンドウで実行します。
2D のエキスパートにとって、手触りやピクセルは目測ではなく、数値で測定するものです。ジャンプの高さはタイル数で、コヨーテタイムはティック数で、カメラの遅れはピクセル数で、ピクセルアートの画面は整数倍の拡大率とフリンジの数で表します。エージェントはコードでタイル、コントローラー、カメラを作成し、決定論的な物理演算の実行とフレームの読み戻しで検証してから、完成と判断します。ここに記載されている兄弟スキルが利用可能なスキルにない場合は、ユーザーにインストールを依頼してください(npx skills add scenario-labs/skills --skill <name>)。ユーザーの応答を待たずに進める場合は、ツールスキーマに基づいて作業し、不足していることを明記してください。
必須の前提知識: scenario-godot-expert(チャンネル、レビューの反復手順、ツールキット gd_env、gd_run、gd_review、4.x の注意点)。
姿勢(専門的な知見)
- 操作感は、テストできる数値です。 ジャンプの高さと頂点までの時間から重力と離陸速度を求め、高さをタイルサイズの倍数にします(The Shaggy Dev、Bsy8pknHc0M [00:04:13])。Godot ではその値から約 v·dt/2 が失われます。60 ティックで、56 px の設計値に対して 53.5 px になることを実測しました。このキットでは g·dt/2 を加え、56.25 px になります[追加]。
- 時間と空間に余裕を持たせます。 コヨーテタイム、ジャンプバッファー、コーナー補正、ジャンプカットは、それぞれ数行で実装できます(The Shaggy Dev)。ウィンドウは整数ティックで数えます。浮動小数点タイマーでは、0.1 s でコヨーテ移動が 6 回ではなく 5 回になりました[追加、実測]。
- トップダウンでは、長さの算術ではなく
move_towardを使います。 加算型の加速にはlimit_lengthが必要です。長さから減速量を引くと負になり、振動します(60 ティックで符号が 55 回反転、実測)。ステアリングは最小ステップがないと目標に到達しません(BT Plays Games、m71-kZgYXlw [00:07:30]、[00:14:08])。 - カメラは親に設定するのではなく、設計するものです。 先読み、ジャンプの無視、着地時の基準位置の再設定、減衰、オフにできる揺れを設定します(Mark Brown、GMTK)。減衰による遅れは速度/減衰量になり、先読みを損ないます。先読みを 32 px にしても、速度が 120 px/s のとき先行量は 16 px だったため、両方の数値を明記します。ズームには
Camera2D.zoom(2 で 2 倍に拡大)を使い、ビューポートのサイズ変更は使いません(DevWorm、RlSpjIb7TLo [00:08:14])。 - ジッターはティックレートの問題です。 144 Hz で物理ティックが 60 回の場合、物理補間を有効にすると、どのカメラ設定でも理想的な 0.289 px RMS になりました。無効にすると背景は 0、1、2 px と段階的に動き、Idle のカメラスムージングによってプレイヤーが 3 px ふらつきました。
Camera2D.process_callbackのデフォルトは Idle です。補間が無効の場合は、CAMERA2D_PROCESS_PHYSICSを自分で設定します(Chris' Tutorials、43c-Sm5GMbc [00:28:37])。有効の場合は Godot が Physics に設定します。 - ピクセルパーフェクトは、どのように拡大するかの判断です。
viewportと整数スケーリングを使うと、ライトを含めすべてがアートのピクセルに固定されます。640x360(ドキュメントの基準解像度)と 320x180 は、実測ではどちらも黒帯なしで 720p、1080p、1440p、4K に整数倍で拡大できます。ネイティブのアートサイズに合わせて選びます。排他フルスクリーン(ウィンドウモード 4)でリリースします。1 px の帯があると、4K での 640x360 の拡大率が 6x から 5x に下がります(実測、ドキュメント「Multiple resolutions」)。canvas_itemsでは滑らかな回転とサブピクセル移動が可能です(Heartbeast はこちらを推奨しています)。アートをピクセルに固定しつつカメラを滑らかに動かす場合は、SubViewport を基準解像度より縦横それぞれ 2 px 大きくレンダリングし、拡大した画像を余り分だけずらします(Barry's Dev Hell)。 - タイルは監査できるデータです。 レイヤーごとに TileMapLayer を 1 つ使い、外部 TileSet を使い、地形モードをタイル数に合わせ、隣接ビットをセルごとに確認します。水辺側ではなく陸地を塗ります(DevWorm、ZutpG0_CYrQ [00:32:47])。GUI では、外周リングを先に塗り、その後に中央の十字を塗ります(bluuDevGames、CLcFC6ku240 [00:12:28])。すべての角を同じように丸める必要がある場合は、デュアルグリッド(16 タイル、表示レイヤーを半タイル分ずらす)を選びます(jess::codes、jEWFSv3ivTg [00:02:26])。その後、サンプラーのキャプチャを確認します。インデックスのチェックでは、アートが間違っていても通ってしまうためです[追加]。
- 生成したアートは、インポート前に確認します。 ピクセルスケールとグリッド位相を特定し、グリッドからずれていればスナップし、すべてのクリップを足元のラインに揃え、線形フィルタリング時にキー色の縁が出ないか確認します[scenario-sprite-pipeline を使って追加]。
- 物理レイヤーには名前を付け、オブジェクトごとに 1 つだけ使います。 オブジェクトごとに衝突レイヤーは 1 つ、マスクは複数設定できます。レイヤーには、チェック側が必要とする内容に基づいて(「bombable」など)
layer_names/2d_physics/layer_Nで名前を付けます(Bogner、HFBNd4Z4vXM [00:10:58] から [00:14:17])。新しいボディはレイヤー 1、マスク 1 で始まります。1 をクリアせずにレイヤーを追加すると、ビットが 2 つ立ちます(実測)。
最初に確認すること
| 質問 | 計画に影響する理由 | デフォルト |
|---|---|---|
| ドット絵ですか、それとも滑らかな2Dですか? | ストレッチモード、フィルター、ライトの解像度、カメラ方式 | ドット絵:基本解像度640x360(非常に小さなアートの場合は320x180)、viewport + keep + 整数倍、Nearest、排他的フルスクリーン |
| グリッドに固定しますか、それともピクセル上を滑らかにカメラ移動しますか? | viewport のみか、pixel_viewport.gd を使うか | カメラがゆっくり動く場合は、pixel_viewport.gd による滑らかなカメラ移動 |
| プラットフォーマーですか、それとも見下ろし型ですか? | GROUNDED または FLOATING、どのキットボディを使うか | 依頼内容に従います |
| タイルサイズと地形スタイル | 47タイルブロブ、16タイルの側面、またはデュアルグリッド | 16 px、47タイルブロブの地形 |
| 対象ディスプレイ | 整数倍の倍率と余白 | 1280x720、1366x768、1920x1080、2560x1440、3840x2160 |
| リフレッシュレートとネットワーク | 物理補間を有効にするか無効にするか | 有効(独自のスムージングを行うネットワークゲームでは無効。ドキュメントを参照) |
| アートの入手元 | Scenarioマニフェスト、手作り、プレースホルダー | アートが届くまでは gd_2d.make_* のプレースホルダー |
ワークフロー
- プロジェクト。
P = gd_env.base_project("2d", ...)、gd_2d.install_kit(P)、gd_2d.pixel_art_settings(P, ...)、gd_run.import_project(P)。GATE:stretch_matrix.gdで、 ルートに基本サイズ、モード、整数ストレッチ、Nearest、補間が反映されていることを確認します。 各ターゲットウィンドウの整数倍の倍率とバーが、gd_2d.integer_scalesと一致していることも確認します。 - アートの取り込み。 生成した各画像に対して、
detect_pixel_scale、pixel_grid_checkを実行し、 位相またはスケールがずれている場合はsnap_to_gridを実行します。次にインポートし、audit_importsを実行してから、マニフェストを使ってsprite_frames_builder.gdで SpriteFrames を作成し、 各スプライトでregister()を実行します。GATE:監査で問題がないこと、各クリップの最も低いインクのピクセルが 同じワールド y にあること、整数倍ではないスケールでキャプチャした際のkey_fringeが 0 であることを確認します。 - タイル。
tileset_builder.gd(最初にタイルサイズを設定し、 アルファ値からピアリングビットを導出し、コリジョン、オクルーダー、片方向の縁を設定)を.tresとして保存し、set_cells_terrain_connectでペイントします。アートが16タイルのデュアルセットの場合は、dual_grid.gdを使います。GATE:terrain_tools.audit_layerで 辺の不一致と角の不一致がそれぞれ0件であること、サンプラーのキャプチャ(リング、十字、単一セル、内角)が コンタクトシートで正しく見えることを確認します。 - キャラクター。
platformer_body.gdとplatformer_tuning.gdの Resource、またはtopdown_body.gdを使います。テストで意図を与えられるよう、 思考部分と本体を分離します。GATE(--fixed-fps 60、await body.steppedごとに1回移動):頂点が設計値から0.5 px以内、 コヨーテタイムと入力バッファが移動回数でカウントされること、最大の隙間がタイル単位であること、 タイルの継ぎ目で引っかからないこと、トップダウン移動がちょうど0で停止し、斜め移動の速度が直線移動と等しいことを確認します。 - カメラ。
follow_camera_2d.gd(物理ステップを使い、 レイヤーの使用範囲から境界を設定)、またはロックされたピクセル上を滑らかに表示するpixel_viewport.gdを使います。 GATE:その場でジャンプしている間、カメラの y が動かないこと、着地後に基準位置を取り直すこと、 長い落下でもプレイヤーが画面内に収まること、シェイクをオフにするとオフセットが0になることを確認します。--fixed-fps 144のウィンドウ表示では、補間を有効にした状態で背景の移動が最大1 px であることを確認します。 - ライト、ソート、パララックス。 CanvasModulate と、放射状の GradientTexture2D を使った PointLight2D、 タイルのアルファ値から生成したオクルーダー、足元を原点とする y ソートコンテナ、 各平面の Parallax2D を使います。GATE:プローブ点(照明あり、影あり、オクルーダーなしの場合と比較したオーナーへの照明)の輝度、 手前と奥の重なりの色テスト、パララックスの移動量がカメラの移動量に scroll_scale を掛けた値と等しいこと、 最低ズームでも隙間がないこと、自動スクロール90フレームで継ぎ目がないことを確認します。
- 監査と引き継ぎ。
audit_2d.gd:scenes、gd_run.check_all、kit_compile.gdを実行し、 キャプチャをコンタクトシート(最大1600 px)にまとめて開き、目視で確認します。GATE:警告の指摘がなく、 コンパイルエラーが0件で、シートに壊れたタイル、フリンジ、隙間がないことを確認します。 文書化した計画には、キットなしでも動作するよう、重要なコード(設定キー、ジャンプの計算、コントローラーのステップ、カメラ)を インラインで記載します。キットのファイル名はショートカットとしてのみ記載します。
数値
| 値 | 測定方法または出典 | 基準 |
|---|---|---|
| 基準サイズ 320x180、整数倍率:1280x720 および 1366x768 では 4x(バー 43、24)、1080p では 6x、1440p では 8x、4K では 12x、1170x2532 では 3x | 実測 | ウィンドウサイズ |
| 基準サイズ 640x360、整数倍率:720p および 1366x768 では 2x(バー 43、24)、1080p では 3x、1440p では 4x、4K では 6x。3840x2159 では、320 と 180 px のバーで 5x | 実測 | ウィンドウサイズ |
| ジャンプ 56 px、頂点まで 0.35 s、落下 0.28 s:上昇時の g は 914.3、下降時の g は 1428.6 px/s²、補正ありの離陸速度は 327.6 px/s | 実測、キットのデフォルト値[追加] | 16 px タイル、60 ティック |
| ジャンプカット 0.4:1 ティックのタップで 12.79 px(タイル未満)上昇します。最低高度は約 (cut·v)²/2g です | 実測、キットのデフォルト値 | 16 px タイル |
| コヨーテタイム 0.1 s = 空中移動 6 回、入力バッファー 0.1 s = 着地前の移動 5 回 | 実測 | 60 ティック |
| 角補正 4 px:頭が 3 px ぶつかっても、34 px から最大の 56 px まで上昇できます | 実測 | 10x14 の本体 |
| 走行速度 120 px/s、ジャンプ 56 px:4 タイルは越えられますが、5 タイルは越えられません | 実測 | 16 px タイル |
| トップダウン、120 px/s、加速 900、減速 1200:最大速度まで 8 回移動し、停止まで 6 回移動 | 実測、キットのデフォルト値 | 60 ティック |
| Camera2D のスムージング速度:デフォルトは 5、約 3 が適切に感じられ、10 はスムージングなしのように感じられました | DevWorm、デフォルト値は実測 | px/s のスムージング単位 |
| 8/s の指数減衰:30、60、144 Hz のいずれでも、ジャンプのずれの 90% が 0.30 s で解消されます。遅延 = 速度 / 減衰 | 実測 | フレームレート |
| 144 Hz でのジッターの下限は、補間オンで 0.289 px RMS、オフで 0.55 | 実測 | 画面 px |
| 4x でのサブピクセルカメラ:1 px 刻み、スナップ時は 4 px 刻み | 実測 | 画面 px |
| ビューと同じ幅の平面に対するパララックスの repeat_times:ズーム 1 では 1、0.5 では 3、0.25 では 5 | 実測 | Camera2D ズーム |
バンド状の光:GRADIENT_INTERPOLATE_CONSTANT を設定した 4 段階の Gradient では、64 px にわたって輝度レベルが 4 段階になりました。LINEAR では 64 | 実測 | CanvasModulate 上の PointLight2D |
フリンジ:fix_alpha_border または fix_alpha_edges() なしでは着色された px が 73 個、ありでは 0 個 | 実測 | 0.7x の 96 px フレーム |
品質ゲート
上記のすべての GATE に加え、地形サンプラー、デュアルグリッド、フリンジストリップ、ライトのキャプチャをまとめたコンタクトシートを開いて評価します(角が丸い形状は輪郭につながっていること、浮いた部品がないこと、マゼンタの縁がないこと、影が右側から落ちていること)。評価基準:critique.md。
よくある間違い
| よくある間違い | どのような問題が起きるか | 修正方法 |
|---|---|---|
| project.godot を手書きする | stretch が disabled になり、ピクセルがぼやけます | gd_2d.pixel_art_settings を使い、ルートを読み戻します |
| Match Corners and Sides で側面に16タイルを設定する | 穴やエッジの誤りが発生します(32 + 10 個の不一致) | Match Sides を使うか、47タイルのブロブセットを描きます |
| ピアリングビットを手入力する | エッジピースがランダムになります | タイルのアルファ値から導出し、監査します |
| 数式だけからジャンプを設定する | 頂点が2.5 px低くなり、本来越えられるはずの隙間を越えられません | g·dt/2 を加味するか、計測して調整します |
| Camera2D をプレイヤーの子にするだけ | カメラが固定され、視野が狭く、揺れます | follow_camera_2d.gd |
| アイドルカメラのスムージングを有効にし、補間を無効にする | 144 Hz でプレイヤーが背景に対して揺れます | 物理補間を有効にします |
| 補間を有効にした Camera2D をピクセル用 SubViewport 内に置く | 画像が -5、+3 px 飛びます | canvas_transform を設定します(pixel_viewport.gd) |
| スナップシェーダーで光をピクセル化できると想定する | 減衰が滑らかなままです | viewport のストレッチまたは SubViewport のワールドを使います。バンドは CONSTANT グラデーションから生成し、shadow_filter は None(デフォルト)にします |
| オクルーダーの所有者が暗くなる | 壁やスプライトに光が当たりません | カリングモードを切り替えます(画面上の頂点の順序で決まります)。基準となるものと比較して確認します |
| Yソートコンテナ内でスプライトの原点を中央にする | プレイヤーが、後ろに立っている木より手前に描画されます | 原点を足元に設定し、offset でアートを移動します。背の高いタイルには y_sort_origin を設定します |
| ビューポートやウィンドウのサイズを変えてズームする | UI とピクセルのスケールも変わります | Camera2D.zoom |
| 整数ピクセルアートにフルスクリーン(mode 3)を使う | 1 px 幅の帯で倍率が1段階下がります | 排他的フルスクリーン(mode 4) |
| キャラクタースプライトに影を焼き込む | 後ろにある木の幹の上に影が描画されます | 影用に別の Sprite2D を使い、z_index = -1 にします。キャラクターに独自の z が設定されたら z_as_relative = false にします(DevWorm、lvuLjMAr_BE [00:09:24]) |
| 隣のタイルに重ねてタイルアニメーションを設定する | 「タイルはすでに存在する」状態になり、1フレームが残ります | 先に隣接タイルを消去します(DevWorm、ZutpG0_CYrQ [00:24:13]) |
| repeat_times 1 でパララックスを設定してズームアウトする | マゼンタまたは黒の隙間ができます | parallax_tools.repeat_times_for |
| キー透過スプライトを線形フィルタリングで実行時に読み込む | マゼンタの輪郭ができます | インポートするか、Image.fix_alpha_edges() を使います |
同じ秒内に .import を編集して再インポートする | 古いテクスチャが使われたままになります | gd_2d.set_import_params を使います(bool 値は小文字、mtime を更新)。.ctex が変更されたことを確認します |
引き継ぎ
- 受け取り元 scenario-sprite-pipeline、scenario-game-assets、scenario-sprite-animation:PNG
または WebP のストリップ、タイルセット、および
frames、w、h、groundを含むマニフェスト。ネイティブのピクセルサイズとキーカラーを確認してください。 - 受け取り元 scenario-godot-architecture:プロジェクトのレイアウト、オートロード、入力アクション名。
- 引き渡し先 scenario-godot-gameplay:意図を示すフィールドとシグナル
jumped、landed、steppedを持つボディ。ナビゲーション用の TileMapLayers。scenario-godot-animation:足元に登録された SpriteFrames。 - 引き渡し先 scenario-godot-vfx、scenario-godot-shaders、scenario-godot-ui(
pixel_viewport.world_to_screen経由の HUD)、scenario-godot-performance-export、scenario-godot-audio(landedのフック)。 - エスカレーション先 チャンネルの失敗については scenario-godot-expert。
Godot 4.7 に関する注意事項
- TileMap と ParallaxBackground/ParallaxLayer は 4.3 以降、非推奨です。TileMapLayer(4 引数の
set_cell)と Parallax2D を使用してください。タイルの物理演算は 4.5 以降、physics_quadrant_sizeによってチャンク化されます。一方向の向き(one_way_collision_direction、デフォルト値は (0, 1))は 4.7 で追加されました(deltas file)。 - Camera2D:
enabledとmake_current()、position_smoothing_enabled、ignore_rotationを使用します。補間が有効な場合、ズームの変更は 1 ティックかけて滑らかに反映されます(実測では 2.0 に達するまで 2~3 フレーム)。 - 4.7.2 で確認したデフォルト値:キャンバスのテクスチャフィルターは Linear、2D 変換のスナップはオフ、物理補間はオフ、CharacterBody2D の安全マージンは 0.08、床へのスナップは 1 px です。テクスチャのインポート設定:Lossless、ミップマップなし、
fix_alpha_borderはオン、detect_3d/compress_toは 1。 - 4.7.2 では、1 つのタイルの同一オクルージョンレイヤー上に複数のオクルーダーポリゴンを配置できます(2 つを保存後も保持):4.3 の動画(suzF2Y166eA [00:12:22])にある 2 つ目のオクルージョンレイヤーは不要です。
- 避けるべき Godot 3 の名称:
KinematicBody2D、YSort、ノードとしてのLight2D、set_cellv、world_to_map、Camera2D.current。
参考資料
references/procedures.md:コードと実行結果を含む手順。expert-notes.md:出典ごとの原則とタイムスタンプ。critique.md:セルフチェック用ルーブリック。gui-paths.md:エディターのメニュー。sources.md:動画とドキュメント。scripts/gd_2d.py:設定、インポート監査、ピクセルグリッドの確認、ジャンプ計算、プレースホルダーのアトラス。scripts/agentkit/2d/:タイルセット、地形、デュアルグリッド、ボディ、カメラ、ピクセルビューポート、スプライトフレーム、視差、監査、ライトシェーダー。