<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>ガイド on Codigrowa Docs</title><link>https://codigrowa.batako.net/docs/guides/</link><description>Recent content in ガイド on Codigrowa Docs</description><generator>Hugo</generator><language>ja-jp</language><atom:link href="https://codigrowa.batako.net/docs/guides/index.xml" rel="self" type="application/rss+xml"/><item><title>Entity 実装ガイド</title><link>https://codigrowa.batako.net/docs/guides/new-entity/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://codigrowa.batako.net/docs/guides/new-entity/</guid><description>&lt;p>このガイドでは新しい Entity を &lt;code>engine/entities/&lt;/code> に追加し、Game へ組み込むまでの流れを説明します。&lt;/p>
&lt;h2 id="1-クラス定義">1. クラス定義&lt;a class="anchor" href="#1-%e3%82%af%e3%83%a9%e3%82%b9%e5%ae%9a%e7%be%a9">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>&lt;code>engine/entities/MyEntity.ts&lt;/code> を作成。&lt;/li>
&lt;li>&lt;code>Entity&lt;/code> を継承し、&lt;code>MyEntitySnapshot&lt;/code> 型を定義。&lt;/li>
&lt;li>コンストラクタで &lt;code>tickRate&lt;/code> や初期座標を渡す。&lt;/li>
&lt;li>&lt;code>_process(elapsed)&lt;/code> に 1 tick 分のロジックを書く。&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ts" data-lang="ts">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">import&lt;/span> { &lt;span style="color:#a6e22e">Entity&lt;/span>, &lt;span style="color:#a6e22e">EntitySnapshot&lt;/span> } &lt;span style="color:#66d9ef">from&lt;/span> &lt;span style="color:#e6db74">&amp;#39;./Entity&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">MyEntitySnapshot&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">EntitySnapshot&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span> { &lt;span style="color:#a6e22e">hp&lt;/span>: &lt;span style="color:#66d9ef">number&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">MyEntity&lt;/span> &lt;span style="color:#66d9ef">extends&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>&amp;lt;&lt;span style="color:#f92672">MyEntitySnapshot&lt;/span>&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#a6e22e">hp&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">protected&lt;/span> &lt;span style="color:#a6e22e">_process() {&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 例: 徐々に減衰
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">hp&lt;/span> &lt;span style="color:#f92672">=&lt;/span> Math.&lt;span style="color:#a6e22e">max&lt;/span>(&lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">hp&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">getSnapshot() {&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">y&lt;/span> } &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>.&lt;span style="color:#a6e22e">getPosition&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> { &lt;span style="color:#a6e22e">id&lt;/span>: &lt;span style="color:#66d9ef">this.id&lt;/span>, &lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">y&lt;/span>, &lt;span style="color:#a6e22e">hp&lt;/span>: &lt;span style="color:#66d9ef">this.hp&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="2-world-へ登録">2. World へ登録&lt;a class="anchor" href="#2-world-%e3%81%b8%e7%99%bb%e9%8c%b2">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ts" data-lang="ts">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">entity&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#a6e22e">MyEntity&lt;/span>({ &lt;span style="color:#a6e22e">tickRate&lt;/span>: &lt;span style="color:#66d9ef">1&lt;/span> &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">30&lt;/span>, &lt;span style="color:#a6e22e">x&lt;/span>: &lt;span style="color:#66d9ef">50&lt;/span>, &lt;span style="color:#a6e22e">y&lt;/span>: &lt;span style="color:#66d9ef">120&lt;/span> });
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">game&lt;/span>.&lt;span style="color:#a6e22e">addEntity&lt;/span>(&lt;span style="color:#a6e22e">entity&lt;/span>);&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>Game.addEntity&lt;/code> が World 経由で &lt;code>_ready()&lt;/code> を一度だけ呼びます。&lt;/li>
&lt;li>画面遷移やアンマウント時は &lt;code>game.removeEntity(entity.id)&lt;/code> を必ず実行。&lt;/li>
&lt;/ul>
&lt;h2 id="3-描画スナップショットの更新">3. 描画スナップショットの更新&lt;a class="anchor" href="#3-%e6%8f%8f%e7%94%bb%e3%82%b9%e3%83%8a%e3%83%83%e3%83%97%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88%e3%81%ae%e6%9b%b4%e6%96%b0">#&lt;/a>&lt;/h2>
&lt;p>Skia や React 側が必要とする最小情報だけを &lt;code>getSnapshot()&lt;/code> に詰めます。大きなオブジェクトを渡すと render 毎にシリアライズコストが掛かるため、描画に不要なロジック用フィールドは含めないでください。&lt;/p></description></item><item><title>デバッグ &amp; 運用</title><link>https://codigrowa.batako.net/docs/guides/debugging/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://codigrowa.batako.net/docs/guides/debugging/</guid><description>&lt;p>エンジンを拡張する際に役立つ検証フローとチェックリストです。&lt;/p>
&lt;h2 id="1-ログと-hud">1. ログと HUD&lt;a class="anchor" href="#1-%e3%83%ad%e3%82%b0%e3%81%a8-hud">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;code>Game.update&lt;/code> は &lt;code>__DEV__&lt;/code> 時に &lt;code>dt&lt;/code> をログ出力します。大量に出る場合は &lt;code>expo start --no-dev&lt;/code> で実機挙動を確認。&lt;/li>
&lt;li>&lt;code>Game.onRender&lt;/code> から受け取る &lt;code>GameRenderPayload&lt;/code> を HUD 表示し、&lt;code>elapsed&lt;/code> / &lt;code>tick&lt;/code> / &lt;code>entities.length&lt;/code> をリアルタイムに監視。&lt;code>components/game-canvas.tsx&lt;/code> の &lt;code>functionLogs&lt;/code> 実装を流用できます。&lt;/li>
&lt;/ul>
&lt;h2 id="2-テスト駆動のすすめ">2. テスト駆動のすすめ&lt;a class="anchor" href="#2-%e3%83%86%e3%82%b9%e3%83%88%e9%a7%86%e5%8b%95%e3%81%ae%e3%81%99%e3%81%99%e3%82%81">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;code>World&lt;/code> と &lt;code>Entity&lt;/code> は純粋な TypeScript クラスなので Jest で単体テスト可能。&lt;/li>
&lt;li>&lt;code>Scheduler&lt;/code> は &lt;code>update(dt)&lt;/code> を段階的に呼び、&lt;code>task.callback&lt;/code> が発火するかで検証できます。&lt;code>getTaskCount()&lt;/code> を監視すればリーク検知が容易です。&lt;/li>
&lt;/ul>
&lt;h2 id="3-典型的なトラブルシュート">3. 典型的なトラブルシュート&lt;a class="anchor" href="#3-%e5%85%b8%e5%9e%8b%e7%9a%84%e3%81%aa%e3%83%88%e3%83%a9%e3%83%96%e3%83%ab%e3%82%b7%e3%83%a5%e3%83%bc%e3%83%88">#&lt;/a>&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>症状&lt;/th>
 &lt;th>対処&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Entity が停止する&lt;/td>
 &lt;td>&lt;code>tickRate&lt;/code> が大きすぎて &lt;code>_process&lt;/code> が呼ばれていない可能性。&lt;code>__DEV__&lt;/code> ログで &lt;code>dt&lt;/code> を確認。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Renderer に反映されない&lt;/td>
 &lt;td>&lt;code>getSnapshot()&lt;/code> で必要なフィールドを返しているか確認。&lt;code>GameCanvas&lt;/code> 側で型ガードを追加。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Scheduler タスクが残り続ける&lt;/td>
 &lt;td>&lt;code>game.cancelTask(id)&lt;/code> を &lt;code>useEffect&lt;/code> のクリーンアップで呼ぶ。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>複数画面で Game を共有したい&lt;/td>
 &lt;td>&lt;code>useGameStore&lt;/code> の &lt;code>game&lt;/code> インスタンスをシングルトンとして取り回し、各画面で &lt;code>onRender&lt;/code> を個別登録。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="4-将来の拡張ポイント">4. 将来の拡張ポイント&lt;a class="anchor" href="#4-%e5%b0%86%e6%9d%a5%e3%81%ae%e6%8b%a1%e5%bc%b5%e3%83%9d%e3%82%a4%e3%83%b3%e3%83%88">#&lt;/a>&lt;/h2>
&lt;p>&lt;code>docs/game_engine_develop_plan.md&lt;/code> に記載されている Step #4 以降（タップ入力、Signal、Sprite 切替など）は現行アーキテクチャを前提としています。API 変更時は互換性を保つため、Hugo ドキュメント内の該当章も更新してください。&lt;/p></description></item></channel></rss>