<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>2D on Godot 4 レシピ</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/index.html</link><description>Recent content in 2D on Godot 4 レシピ</description><generator>Hugo -- gohugo.io</generator><language>ja</language><atom:link href="https://kamera25.github.io/godot_recipes/4.x/ja/2d/index.xml" rel="self" type="application/rss+xml"/><item><title>タイルマップ：タイルを検出する</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/tilemap_collision/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/tilemap_collision/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;&lt;i class="gd-CharacterBody2D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody2D&lt;/code&gt;キャラクターが&lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt;と衝突しており、どのタイルに衝突したのかを確認したい場合。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;&lt;i class="gd-CharacterBody2D"&gt;&lt;/i&gt; オブジェクト同士が衝突した場合、衝突データは &lt;code&gt;KinematicCollision2D&lt;/code&gt; オブジェクトとして取得されます。 &lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt; は単一のコリダーとして機能するため、&lt;code&gt;collider&lt;/code&gt; プロパティを参照すると実際にはこの &lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt; ノードが返される点にご注意ください。&lt;/p&gt;
&lt;p&gt;その後、衝突位置にある&lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt;のタイルを特定が必要です。&lt;/p&gt;
&lt;p&gt;以下の状況を想定してください。変数 &lt;code&gt;collision&lt;/code&gt; に &lt;code&gt;KinematicCollision2D&lt;/code&gt; オブジェクトが格納されている場合：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#616e87;font-style:italic"&gt;# Confirm the colliding body is a TileMap&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; collision&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;collider &lt;span style="color:#81a1c1;font-weight:bold"&gt;is&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;TileMap&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Find the character&amp;#39;s position in tile coordinates&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; tile_pos &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; collision&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;collider&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;world_to_map&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;position&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Find the colliding tile position&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tile_pos &lt;span style="color:#81a1c1"&gt;-=&lt;/span&gt; collision&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;normal
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Get the tile id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; tile_id &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; collision&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;collider&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_cellv&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;tile_pos&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;tile_id&lt;/code&gt;を取得した後、&lt;code&gt;TileSet&lt;/code&gt;リソースからタイルのプロパティを取得できます。これは&lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt;オブジェクトの&lt;code&gt;tile_set&lt;/code&gt;プロパティで参照できます。例えば、特定のタイル名を取得するには以下のようにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; tile_name &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; collision&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;collider&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;tile_set&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;tile_get_name&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;tile_id&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、新しい&lt;code&gt;id&lt;/code&gt;を設定することでタイルを変更することもできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; collision&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;collider&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;set_cellv&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;tile_pos&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; new_id&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="関連レシピ"&gt;関連レシピ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/2d/autotile_intro/"&gt;タイルマップ: オートタイルを使う&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/2d/tilemap_animation/"&gt;タイルマップ: アニメーションタイル&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="この動画が気に入ったら"&gt;この動画が気に入ったら？&lt;/h4&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/OzgK__VowVs?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;</description></item><item><title>プラットフォームキャラクター</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/platform_character/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/platform_character/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;2Dプラットフォーマースタイルのキャラクターを作成したいです。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;経験が少ない開発者は、プラットフォームキャラクターをプログラミングするのがいかに複雑かを知って驚くことがよくあります。Godotには組み込みツールが用意されているものの、ゲームごとに解決策が異なるため、万能な答えはありません。このチュートリアルでは、ダブルジャンプやしゃがみ動作、ウォールジャンプ、アニメーションといった機能について詳しく掘り下げることはしません。ここではプラットフォーマー移動の基本原理に焦点を当てます。他の課題については、残りのレシピを参照してください。&lt;/p&gt;
&lt;div class="box notices cstyle tip"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-lightbulb"&gt;&lt;/i&gt; ヒント&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;&lt;i class="gd-RigidBody2D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody2D&lt;/code&gt; を使用してプラットフォーマーキャラクターを作成することはできますが、ここでは &lt;i class="gd-CharacterBody2D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody2D&lt;/code&gt; に焦点を当てます。運動制御ボディはプラットフォームゲームに最適です。このようなゲームでは、リアルな物理挙動よりも反応の良いアーケードライクな操作感が重視されるためです。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;まず &lt;i class="gd-CharacterBody2D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody2D&lt;/code&gt; ノードを作成し、その上に &lt;i class="gd-Sprite2D"&gt;&lt;/i&gt;&lt;code&gt;Sprite2D&lt;/code&gt; と &lt;i class="gd-CollisionShape2D"&gt;&lt;/i&gt;&lt;code&gt;CollisionShape2D&lt;/code&gt; を追加してください。&lt;/p&gt;
&lt;p&gt;以下のスクリプトをキャラクターノードのルートに追加してください。なお、ここでは[インプットマップ]で定義した入力アクション（&lt;code&gt;&amp;quot;walk_right&amp;quot;&lt;/code&gt;、&lt;code&gt;&amp;quot;walk_left&amp;quot;&lt;/code&gt;、および &lt;code&gt;&amp;quot;jump&amp;quot;&lt;/code&gt;）を使用しています。詳細は &lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/input/input_actions/"&gt;InputActions&lt;/a&gt; をご覧ください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;CharacterBody2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; jump_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;&lt;span style="color:#b48ead"&gt;1800&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; gravity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;4000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Add gravity every frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; gravity &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Input affects x axis only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_axis&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;walk_left&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;walk_right&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; speed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move_and_slide&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Only allow jumping when on the ground&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_just_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;jump&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;is_on_floor&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; jump_speed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;speed&lt;/code&gt;、&lt;code&gt;gravity&lt;/code&gt;、&lt;code&gt;jump_speed&lt;/code&gt;に用いる値は、プレイヤースプライトのサイズに大きく依存します。このサンプルではプレイヤーテクスチャが &lt;code&gt;108x208&lt;/code&gt; ピクセルです。もしスプライトが小さい場合は、より小さい値を使用が必要です。また、ゲーム操作が速く反応するように、適切な高数値を設定することが重要です。重力を低く設定すると浮遊感の強いゲームプレイになり、逆に高く設定するとすぐに地面に戻って再びジャンプできる状態になります。&lt;/p&gt;</description></item><item><title>画面ループ</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/screen_wrap/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/screen_wrap/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;クラシックな2Dゲーム（『パックマン』タイプの作品など）でよく使われる、プレイヤーキャラクターが画面端から反対側に移動する機能を実装したいです。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;スクリーンサイズ（ビューポート）を取得します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@onready&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; screen_size &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;get_viewport_rect&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;size
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;get_viewport_rect()&lt;/code&gt; は &lt;code&gt;CanvasItem&lt;/code&gt; の派生ノードであればどれでも利用できます。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;プレイヤーの座標を比較します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt; screen_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; screen_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt; screen_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; screen_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：この処理ではノードの&lt;code&gt;position&lt;/code&gt;を使用しています。これは通常、スプライトまたはボディの中心座標を指します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;wrapf()&lt;/code&gt; を使用して、シンプルに実装します。&lt;/p&gt;
&lt;p&gt;上記のコードは、GDScriptの&lt;code&gt;wrapf()&lt;/code&gt;関数を使用することで簡略化できます。この関数は指定された範囲内で値を「ループ」させます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;wrapf&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; screen_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;wrapf&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; screen_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>画面への入力／出口</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/enter_exit_screen/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/enter_exit_screen/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;オブジェクトが画面内に表示、また非表示になるタイミングを検知したい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この目的のためのノードが用意されています。&lt;i class="gd-VisibleOnScreenNotifier2D"&gt;&lt;/i&gt;&lt;code&gt;VisibleOnScreenNotifier2D&lt;/code&gt;。このノードをオブジェクトにアタッチすれば、&lt;code&gt;screen_entered&lt;/code&gt;シグナルと&lt;code&gt;screen_exited&lt;/code&gt;シグナルを利用可能になります。
*&lt;/p&gt;
&lt;h4 id="例-1"&gt;例 1&lt;/h4&gt;
&lt;p&gt;発射後に直線軌道で移動する投射物を考えてみます。継続的に射撃を続けると、画面上から外れた物体であってもエンジンが追跡すべき対象が大量に発生し、結果的にラグの原因となる可能性があります。&lt;/p&gt;
&lt;p&gt;以下に発射体の移動コードを示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Area2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;500&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; velocity &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;プロジェクトイルが画面外に移動した際に自動的に削除されるようにするには、&lt;i class="gd-VisibleOnScreenNotifier2D"&gt;&lt;/i&gt;&lt;code&gt;VisibleOnScreenNotifier2D&lt;/code&gt;を追加し、その&lt;code&gt;screen_exited&lt;/code&gt;シグナルを接続してください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_on_VisibleOnScreenNotifier2D_screen_exited&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;queue_free&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="例2"&gt;例2&lt;/h4&gt;
&lt;p&gt;敵キャラクターがいて、経路に沿って移動したりアニメーションを再生したりするなどの動作を行います。大規模なマップで多数の敵が存在する場合、同時に画面上に表示されるのはそのうちのわずか数人だけです。&lt;i class="gd-VisibleOnScreenNotifier2D"&gt;&lt;/i&gt;&lt;code&gt;VisibleOnScreenNotifier2D&lt;/code&gt; を使用することで、オフスクリーン状態の間だけ敵の動作を無効化できます。&lt;/p&gt;
&lt;p&gt;コードの一部：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; active &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; active&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;play_animation&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_on_VisibleOnScreenNotifier2D_screen_entered&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; active &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_on_VisibleOnScreenNotifier2D_screen_exited&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; active &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>見下ろし型での移動</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/topdown_movement/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/topdown_movement/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;2D見下ろし方式のゲームを開発しており、キャラクターの動きを制御が必要です。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;ここでは、以下の入力アクションが定義されているとします。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;アクション&lt;/th&gt;
&lt;th&gt;キー&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;up&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;W,↑&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;down&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;S,↓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;right&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;D,→&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;left&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A,←&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;click&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;マウスボタン1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;またここでは、&lt;i class="gd-CharacterBody2D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody2D&lt;/code&gt; ノードを使用していると想定します。&lt;/p&gt;
&lt;p&gt;この問題は、求める行動の種類に応じてさまざまな方法で解決できます。&lt;/p&gt;
&lt;h3 id="その18方向移動方式"&gt;その1：8方向移動方式&lt;/h3&gt;
&lt;p&gt;このシナリオでは、プレイヤーは4方向キー（斜め移動含む）を使って操作します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;CharacterBody2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;400&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# speed in pixels/sec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; direction &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_vector&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;right&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;up&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;down&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; direction &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; speed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move_and_slide&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="その2-回転と移動を組み合わせる場合"&gt;その2: 回転と移動を組み合わせる場合&lt;/h3&gt;
&lt;p&gt;この操作方法では、左右でキャラクターを回転させ、上下で向いている方向に前進・後退します。これは「アステロイド風」と呼ばれる伝統的な操作方式です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;CharacterBody2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;400&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# move speed in pixels/sec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; rotation_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1.5&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# turning speed in radians/sec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; move_input &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_axis&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;down&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;up&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; rotation_direction &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_axis&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;right&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; move_input &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; speed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rotation &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; rotation_direction &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; rotation_speed &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move_and_slide&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="box notices cstyle note"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-circle"&gt;&lt;/i&gt; メモ&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;Godotでは角度 &lt;code&gt;0&lt;/code&gt; 度を&lt;code&gt;x&lt;/code&gt;軸に沿っていることを意味します。これは、ノードの前方方向（&lt;code&gt;transform.x&lt;/code&gt;）が右向きであることを示しています。キャラクタースプライトも同様に、右側に向かって描画されるように設定してください。&lt;/p&gt;</description></item><item><title>分割画面マルチプレイヤー</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/splitscreen_demo/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/splitscreen_demo/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="はじめに"&gt;はじめに&lt;/h2&gt;
&lt;p&gt;このデモでは、見下ろし型の迷路ゲームを例に、ローカルマルチプレイヤーゲームを考えます。このゲームでは2人のプレイヤーが参加し、一方は矢印キー、もう一方はWASDキーで操作します。これは問題ありませんが、もしゲーム世界全体が1画面に収められる程度の大きさであれば、特に問題はありません。しかし、マップが非常に広い場合、両プレイヤーを個別に表示する「分割画面」ビューが必要になるでしょう。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-77082ac8cd45dd14acb6f92cf6bfb3dc" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/splitscreen2.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-77082ac8cd45dd14acb6f92cf6bfb3dc"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/splitscreen2.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;また、ミニマップ表示をすばやく設定する方法についても解説します。&lt;/p&gt;
&lt;h3 id="ゲーム設定"&gt;ゲーム設定&lt;/h3&gt;
&lt;p&gt;ゲーム世界のセットアップに多くの時間をかけるつもりはありません。登場する2人のキャラクターは
シンプルな8方向移動を実装した&lt;i class="gd-CharacterBody2D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody2D&lt;/code&gt; オブジェクトです。&lt;/p&gt;
&lt;div class="box notices cstyle note"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-circle"&gt;&lt;/i&gt; メモ&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;このパーツのセットアップでお困りの場合は、公式Godotドキュメントの以下のセクションをご覧ください: &lt;a href="https://docs.godotengine.org/ja/stable/tutorials/2d/2d_movement.html" target="_blank"&gt;2D移動の概要&lt;/a&gt;。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;各操作は、プロジェクト設定の[インプットマップ]セクションで個別に設定されています。「right_1」は右矢印キー、「right_2」はDキーなどです。このように命名することで、コード内で以下の構文を使用でき、開発効率を大幅に向上させられます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; id &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;get_input&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#39;right_&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;%s&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#39;&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;%&lt;/span&gt; id&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# etc.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;この方法であれば、キャラクターが同じ移動スクリプトを使用できます。各プレイヤーに適切な値を &lt;code&gt;id&lt;/code&gt; として割り当てるだけです。&lt;/p&gt;
&lt;p&gt;以下の手順に従って、2つのプレイヤーを &lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt; を含む「World」シーンに追加してください。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-0faab8b8aa55b5043bd05871ae7b5ab3" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/splitscreen_map.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-0faab8b8aa55b5043bd05871ae7b5ab3"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/splitscreen_map.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ご希望であれば、ワールドが既に設定済みの開始プロジェクトをこちらからダウンロードできます。&lt;/p&gt;
&lt;!-- !LINK --&gt;
&lt;p&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/blog/img/splitscreen_start.zip"&gt;splitscreen_start.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このマップはゲーム画面よりもはるかに大きいことに注意してください。ただ、それ以外の点ではすべて正常に動作します。このようにゲームの「World」を個別に設定することで、ビューポートの設定が格段に容易になり、より柔軟に扱えるようになります。&lt;/p&gt;
&lt;h3 id="ビューポートカメラおよびワールドについて"&gt;ビューポート、カメラ、およびワールドについて&lt;/h3&gt;
&lt;p&gt;まず、2つのビューポートを含む新しいシーンを作成します。
ルートノードとして使用するノードを作成します。通常、&lt;code&gt;Node&lt;/code&gt;を使用します。このノードには独自のプロパティが何もないため（単にシーンの他の要素を保持するためのものです）、使い勝手が良いからです。&lt;/p&gt;
&lt;p&gt;各ビューポートノード（&lt;i class="gd-Viewport"&gt;&lt;/i&gt;&lt;code&gt;Viewport&lt;/code&gt;）には位置情報が含まれません（&lt;i class="gd-Node3D"&gt;&lt;/i&gt;&lt;code&gt;Node3D&lt;/code&gt;や&lt;i class="gd-Node2D"&gt;&lt;/i&gt;&lt;code&gt;Node2D&lt;/code&gt;を継承していません）。ここでは、各ビューポートを管理するために&lt;i class="gd-SubViewportContainer"&gt;&lt;/i&gt;&lt;code&gt;ViewportContainer&lt;/code&gt;を使用します。このコンテナは&lt;i class="gd-Control"&gt;&lt;/i&gt;&lt;code&gt;Control&lt;/code&gt;ノードの一種です。それらを横並びに配置するためには、&lt;i class="gd-HBoxContainer"&gt;&lt;/i&gt;&lt;code&gt;HBoxContainer&lt;/code&gt;を使います。&lt;/p&gt;
&lt;p&gt;&lt;i class="gd-HBoxContainer"&gt;&lt;/i&gt;&lt;code&gt;HBoxContainer&lt;/code&gt;の配置を「中央」に設定し、2つのビューポート間に小さな隙間を設けるには、_カスタム定数/間隔_に &lt;code&gt;5&lt;/code&gt; を設定してください。「Layout(レイアウト)」メニューでは「Full Rect」を選択します。&lt;/p&gt;
&lt;p&gt;次に、2つの&lt;i class="gd-SubViewportContainer"&gt;&lt;/i&gt;&lt;code&gt;ViewportContainer&lt;/code&gt;を子要素として追加し、それぞれに&lt;code&gt;2&lt;/code&gt;と&lt;code&gt;1&lt;/code&gt;という名前を付けます（これらは表示するプレイヤーに対応するためです）。両方のコンテナについて &lt;em&gt;Size Flags&lt;/em&gt; を「Fill, Expand」に設定してください。これにより、各コンテナが画面の半分を埋めるように拡大されます。さらに、 &lt;em&gt;Stretch&lt;/em&gt; プロパティもチェックすることで、&lt;i class="gd-Viewport"&gt;&lt;/i&gt;&lt;code&gt;Viewport&lt;/code&gt;が自動的にコンテナのサイズに合わせて調整されるようになります。&lt;/p&gt;</description></item><item><title>グリッドベースの移動</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/grid_movement/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/grid_movement/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;グリッド状に移動する2Dキャラクターが必要です。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;グリッド制またはタイルベースの移動方式では、キャラクターの位置が制限されます。特定のタイル上にのみ立つことができ、2枚のタイルの間に立ち続けることはできません。&lt;/p&gt;
&lt;h3 id="キャラクター設定"&gt;キャラクター設定&lt;/h3&gt;
&lt;p&gt;以下がプレイヤーで使用するノードです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i class="gd-Area2D"&gt;&lt;/i&gt;&lt;code&gt;Area2D&lt;/code&gt; (&amp;ldquo;プレイヤー&amp;rdquo;): &lt;i class="gd-Area2D"&gt;&lt;/i&gt;&lt;code&gt;Area2D&lt;/code&gt; を使用することで、オブジェクトのピックアップや敵との衝突判定が可能になります。
&lt;ul&gt;
&lt;li&gt;&lt;i class="gd-Sprite2D"&gt;&lt;/i&gt;&lt;code&gt;Sprite2D&lt;/code&gt;: ここではスプライトシートを使用できます（アニメーション設定は後述します）。&lt;/li&gt;
&lt;li&gt;&lt;i class="gd-CollisionShape2D"&gt;&lt;/i&gt;&lt;code&gt;CollisionShape2D&lt;/code&gt;: ヒットボックスが大きすぎないように注意してください。プレイヤーがタイルの中心に立つため、オーバーラップ判定も中央から行われます。&lt;/li&gt;
&lt;li&gt;&lt;i class="gd-RayCast2D"&gt;&lt;/i&gt;&lt;code&gt;RayCast2D&lt;/code&gt;: 指定された方向への移動が可能かどうかを確認する際に使われます。&lt;/li&gt;
&lt;li&gt;&lt;i class="gd-AnimationPlayer"&gt;&lt;/i&gt;&lt;code&gt;AnimationPlayer&lt;/code&gt;: キャラクターの歩行アニメーションを再生に使います。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;インプットマップに操作を追加してください。この例では「上」「下」「左」「右」を使用します。&lt;/p&gt;
&lt;h3 id="基本的な動き"&gt;基本的な動き&lt;/h3&gt;
&lt;p&gt;まず、アニメーションや補間なしで、タイル単位の移動設定から始めてください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Area2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; tile_size &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; inputs &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;right&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;RIGHT&lt;span style="color:#eceff4"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;LEFT&lt;span style="color:#eceff4"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;up&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&lt;span style="color:#eceff4"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;down&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;DOWN&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;tile_size&lt;/code&gt;にはタイルのサイズに合わせて適切な値を設定してください。大規模なプロジェクトでは、メインシーンからプレイヤーインスタンスを生成する際にこを設定します。以下の例では 64×64ピクセルのタイルを使用しています。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;inputs&lt;/code&gt; Dictonaryは入力アクション名と方向ベクトルを対応付けます。ここでの名前とインプットマップでの表記が完全一致していることを確認してくください（大文字小文字の区別に注意！）。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_ready&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;snapped&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ONE &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; tile_size&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ONE &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; tile_size&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;&lt;span style="color:#b48ead"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;snapped()&lt;/code&gt; 関数は位置をタイルの増分に最も近い値に「丸め」ます。さらに、半タイル量を追加することで、プレイヤーが必ずタイル中心に配置されるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_unhandled_input&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;event&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;for&lt;/span&gt; dir &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt; inputs&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;keys&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; event&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;dir&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;dir&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;move&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;dir&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; inputs&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;dir&lt;span style="color:#eceff4"&gt;]&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; tile_size
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下が実際の移動処理コードです。入力イベントが発生すると、4方向をチェックし、該当する方向を特定した後に&lt;code&gt;move()&lt;/code&gt;関数に渡して位置を変更します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-890d5b8505b15ff371b70ceffad19bab" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/grid_example1.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-890d5b8505b15ff371b70ceffad19bab"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/grid_example1.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;</description></item><item><title>投射物の発射</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/2d_shooting/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/2d_shooting/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;プレイヤー／モブなどから投射物を発射させたい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;h3 id="弾丸の設定"&gt;弾丸の設定&lt;/h3&gt;
&lt;p&gt;まず、インスタンス化可能な「弾丸」オブジェクトを設定します。使用するノードは以下の通りです。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&lt;i class="gd-Area2D"&gt;&lt;/i&gt; Area2D: Bullet
&lt;i class="gd-Sprite2D"&gt;&lt;/i&gt; Sprite2D
&lt;i class="gd-CollisionShape2D"&gt;&lt;/i&gt; CollisionShape2D
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;i class="gd-Sprite2D"&gt;&lt;/i&gt;&lt;code&gt;Sprite2D&lt;/code&gt;のテクスチャは、好きな画像を使用できます。以下は例です。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-360f434ef94dbfb2782922eb6fe87c19" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/laserRed01.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-360f434ef94dbfb2782922eb6fe87c19"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/laserRed01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ノードの設定とスプライトおよび衝突判定形状を構成します。テクスチャが上向きに配置されている場合（上記例のように）は、&lt;i class="gd-Sprite2D"&gt;&lt;/i&gt;&lt;code&gt;Sprite&lt;/code&gt; ノードを &lt;code&gt;90°&lt;/code&gt; 回転させて右方向に向け、親オブジェクトの「前方」方向に一致するように調整してください。&lt;/p&gt;
&lt;p&gt;スクリプトを追加し、&lt;i class="gd-Area2D"&gt;&lt;/i&gt;&lt;code&gt;Area2D&lt;/code&gt;の&lt;code&gt;body_entered&lt;/code&gt;シグナルに接続してください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Area2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;750&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; speed &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_on_Bullet_body_entered&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;body&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; body&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_in_group&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;mobs&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; body&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;queue_free&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;queue_free&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この例では、オブジェクトが何かを衝突した場合、即座に弾丸を除去します。また、「mobs」グループにタグ付けされた対象物もすべて削除します。&lt;/p&gt;
&lt;h3 id="射撃"&gt;射撃&lt;/h3&gt;
&lt;p&gt;弾丸の出現位置を設定が必要です。&lt;i class="gd-Marker2D"&gt;&lt;/i&gt;&lt;code&gt;Marker2D&lt;/code&gt;コンポーネントを追加し、弾丸を出現させたい場所に配置してください。以下は具体例で、銃身の先端に設置しています。「Muzzle」という名前を付けています。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-bef4e07758a528e90820dedb41f54cf3" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/2d_shoot_01.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-bef4e07758a528e90820dedb41f54cf3"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/2d_shoot_01.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;「プレイヤーが回転するにつれ、Muzzleの&lt;code&gt;transform&lt;/code&gt;は銃に対して常に同じ向きを保つことに注目してください。これは弾丸をスポーンさせる際に非常に便利です。変換行列を使用することで、適切な位置と方向を簡単に取得できるからです。新しい弾丸の&lt;code&gt;transform&lt;/code&gt;は、単にMuzzleのものと等しく設定するだけで済みます。&lt;/p&gt;
&lt;div class="box notices cstyle tip"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-lightbulb"&gt;&lt;/i&gt; ヒント&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この手法は「回転・移動」スタイルに限らず、あらゆる文字タイプに適用できます。単に、弾丸を表示させたい位置に &lt;i class="gd-Marker2D"&gt;&lt;/i&gt;&lt;code&gt;Marker2D&lt;/code&gt; タグを挿入するだけで済みます。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;キャラクタースクリプト内で、インスタンス化用の弾丸シーンを保持する変数を追加してください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; Bullet &lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;PackedScene&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;入力アクションが定義されているか確認してください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_just_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;shoot&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;shoot&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで&lt;code&gt;shoot()&lt;/code&gt;関数内では、弾丸インスタンスを生成しツリーに追加できます。よくあるミスとして、プレイヤーノードの子要素として直接追加してしまうケースがあります&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;shoot&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; b &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; Bullet&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;instantiate&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;add_child&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;b&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Muzzle&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;問題は、弾丸がプレイヤーの子オブジェクトであるため、プレイヤーが移動または回転した際に影響を受ける点です。&lt;/p&gt;</description></item><item><title>車のステアリング操作</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/car_steering/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/car_steering/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;2D見下ろし方式カーコントローラーを作成したい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この問題に取り組む際、初心者はしばしば実際の車とはかけ離れた挙動のゲームを作ってしまいがちです。アマチュアが作ったカーゲームでよく見られる失敗例をご紹介します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自動車は中心軸を中心に旋回するものではありません。別の言い方をすれば、後輪が左右に滑ることはありません。（ドリフト走行時はこの限りではないが、その点については後述します）&lt;/li&gt;
&lt;li&gt;自動車は動いている時にのみ方向転換が可能で、その場で回転することはできません。&lt;/li&gt;
&lt;li&gt;自動車は列車ではありません。レールに縛られていません。高速で曲がる際にはある程度の横滑り（ドリフト）が伴うべきです。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2Dカー物理の実装には様々なアプローチ方法があり、主に「リアル志向」か「アーケードスタイル」かによって選択が分かれます。ここでは、リアリティよりもアクション性を優先する「アーケードレベル」の現実感を追求していきます。&lt;/p&gt;
&lt;div class="box notices cstyle note"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-circle"&gt;&lt;/i&gt; メモ&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;以下の方法は、こちらのアルゴリズムに基づいています。 &lt;a href="https://engineeringdotnet.blogspot.com/2010/04/simple-2d-car-physics-in-games.html" target="_blank"&gt;https://engineeringdotnet.blogspot.com/2010/04/simple-2d-car-physics-in-games.html&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下のレシピは5つのセクションに分かれており、それぞれが車の異なる動作要素を追加してください。必要に応じて自由に組み合わせてご使用ください。&lt;/p&gt;
&lt;h3 id="シーン設定"&gt;シーン設定&lt;/h3&gt;
&lt;p&gt;以下が車シーンの設定内容です。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&lt;i class="gd-CharacterBody2D"&gt;&lt;/i&gt; CharacterBody2D
&lt;i class="gd-Sprite2D"&gt;&lt;/i&gt; Sprite2D
&lt;i class="gd-CollisionShape2D"&gt;&lt;/i&gt; CollisionShape2D
&lt;i class="gd-Camera2D"&gt;&lt;/i&gt; Camera2D
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;このデモでは、&lt;a href="https://kenney.nl/assets/racing-pack" target="_blank"&gt;Kenneyのレーシングパック&lt;/a&gt;のアートワークを使用します。&lt;i class="gd-CapsuleShape2D"&gt;&lt;/i&gt;&lt;code&gt;CapsuleShape2D&lt;/code&gt;は衝突判定に最適な形状です。これにより、車が障害物に引っかかるような鋭い角を防ぐことができます。&lt;/p&gt;
&lt;p&gt;以下の4つの入力操作も使用します。「右旋回」「左旋回」「加速」「ブレーキ」。お好みのキー割り当てを設定してください。&lt;/p&gt;
&lt;h3 id="その1動き"&gt;その1：動き&lt;/h3&gt;
&lt;p&gt;最初のステップは、前述のアルゴリズムに基づいて動作をコーディングすることです。&lt;/p&gt;
&lt;p&gt;以下の変数から始めてください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;CharacterBody2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; wheel_base &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;70&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Distance from front to rear wheel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; steering_angle &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;15&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Amount that front wheel turns, in degrees&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; steer_direction
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;wheelbase&lt;/code&gt; をスプライトに適した値に設定してください。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;steer_direction&lt;/code&gt; には車輪の回転量が設定されます。&lt;/p&gt;
&lt;div class="box notices cstyle note"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-circle"&gt;&lt;/i&gt; メモ&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;キーボード操作を使用している場合、ターンはオン／オフの二択になります。アナログジョイスティックを使用する場合は、代わりにスティックの移動距離に応じてこの値を調整できます。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;get_input&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;calculate_steering&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move_and_slide&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;各フレームでは、入力のチェックとステアリング計算が必要です。その後、算出された&lt;code&gt;速度&lt;/code&gt;を &lt;code&gt;move_and_slide()&lt;/code&gt; 関数に渡します。これら2つの関数については次に定義します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;get_input&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; turn &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_axis&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;steer_left&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;steer_right&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; steer_direction &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; turn &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;deg_to_rad&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;steering_angle&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ZERO
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;accelerate&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; &lt;span style="color:#b48ead"&gt;500&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここではユーザー入力を確認し、移動速度を設定します。注意：速度&lt;code&gt;500&lt;/code&gt;は一時的なもので、動きのテスト用です。これについては次のセクションで対処します。&lt;/p&gt;</description></item><item><title>8方向移動・アニメーション</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/8_direction/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/8_direction/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;2Dキャラクターが必要です。アニメーションを含む8方向移動が可能なものが求められます。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この例では、&lt;a href="https://remos.itch.io/mini-crusader" target="_blank"&gt;Isometric: Mini-Crusader&lt;/a&gt;を使用します。これには待機、歩行、攻撃など8方向に対応したアニメーションが含まれています。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-08c3982808a280abf40a159206a66d0e" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_01.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-08c3982808a280abf40a159206a66d0e"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_01.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;アニメーションはフォルダ単位で整理されており、各フレームごとに個別の画像が用意されています。ここでは&lt;i class="gd-AnimatedSprite2D"&gt;&lt;/i&gt;&lt;code&gt;AnimatedSprite2D&lt;/code&gt;を使用し、各アニメーションにはその動作方向に基づいて名前を付けます。例えば、右向きで時計回りに移動する&lt;code&gt;idle0&lt;/code&gt;から、同じく時計回りに動く&lt;code&gt;idle7&lt;/code&gt;までといった具合です。&lt;/p&gt;
&lt;p&gt;キャラクターが移動する際には、動きの方向に基づいて適切なアニメーションを選択します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-170676e683a3a11787041813f7040df7" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_03w.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-170676e683a3a11787041813f7040df7"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_03w.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;マウスを使って移動します。キャラクターは常にマウスの方向を向き、マウスボタンをクリックするとその方向に走り出します。&lt;/p&gt;
&lt;p&gt;どのアニメーションを再生するか選択するためには、マウスの方向を取得し、それを同じ範囲（&lt;code&gt;0-7&lt;/code&gt;）にマッピングする必要があります。&lt;code&gt;get_local_mouse_position()&lt;/code&gt;を使用することで、キャラクターに対するマウスカーソルの位置を取得できます。次に&lt;code&gt;snappedf()&lt;/code&gt;関数を使用して、マウスベクトルの角度を最も近い45度間隔（&lt;code&gt;PI/4&lt;/code&gt;ラジアン）にスナップさせると、以下の結果が得られます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-427a2be4460c80e3806b0d0275005685" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_04w.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-427a2be4460c80e3806b0d0275005685"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_04w.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;各値を 45°（&lt;code&gt;PI/4&lt;/code&gt; ラジアン）で除算すると、以下のようになります。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-499d9a4d871eb3181e68292db2181d36" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_02w.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-499d9a4d871eb3181e68292db2181d36"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_02w.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最終的には、&lt;code&gt;wrapi()&lt;/code&gt;関数を使用して結果の範囲を&lt;code&gt;0-7&lt;/code&gt;にマッピングする必要があります。これにより、正しい値が得られます。この値をアニメーション名の末尾に追加します（&amp;ldquo;idle&amp;rdquo;、&amp;ldquo;run&amp;quot;など）。こうすることで、正しく動作するアニメーションが完成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; current_animation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; mouse &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;get_local_mouse_position&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; angle &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;snappedf&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;mouse&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;angle&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(),&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;PI&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;&lt;span style="color:#b48ead"&gt;4&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;PI&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;&lt;span style="color:#b48ead"&gt;4&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; angle &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;wrapi&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;int&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;angle&lt;span style="color:#eceff4"&gt;),&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;8&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;left_mouse&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; mouse&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;length&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#b48ead"&gt;10&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; current_animation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;run&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; mouse&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;normalized&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; speed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move_and_slide&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $AnimatedSprite2D&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;animation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; current_animation &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;str&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;a&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;動作テストを行ったところ、以下の現象が確認されました：&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-7e101d9760940d4910e0eb5f511868ba" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_05.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-7e101d9760940d4910e0eb5f511868ba"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/8_direction_05.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="キーボード入力"&gt;キーボード入力&lt;/h3&gt;
&lt;p&gt;マウスの代わりにキーボード操作を使用している場合、押されているキーに基づいて移動角度を取得できます。それ以外の手順は同様の方法で進行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; current_animation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; input_dir &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_vector&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;right&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;up&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;down&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; input_dir&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;length&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;!=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; angle &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; input_dir&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;angle&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;PI&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;&lt;span style="color:#b48ead"&gt;4&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; angle &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;wrapi&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;int&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;a&lt;span style="color:#eceff4"&gt;),&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;8&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; current_animation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;run&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; input_dir &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; speed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move_and_slide&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $AnimatedSprite2D&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;play&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;current_animation &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;str&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;angle&lt;span style="color:#eceff4"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="プロジェクトのダウンロード"&gt;&lt;i class="fas fa-code-branch"&gt;&lt;/i&gt; プロジェクトのダウンロード&lt;/h2&gt;
&lt;p&gt;プロジェクトコードはこちらからダウンロードできます。&lt;a href="https://github.com/godotrecipes/8_direction_animation" target="_blank"&gt;https://github.com/godotrecipes/8_direction_animation&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Yソートを使う</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/using_ysort/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/using_ysort/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;多くの2Dゲームでは「3/4視点」と呼ばれるアングルが採用されており、カメラが少し斜め上から見下ろしているような構図になっています。これを実現するためには、より「奥」にあるオブジェクトを先に描画し、手前のオブジェクトの後ろに配置が必要です。実際には、これは「y軸ソート」（描画順序をオブジェクトの&lt;code&gt;y座標&lt;/code&gt;に紐付けること）を意味します。画面上の高い位置にあるものほど遠くに位置するため、レンダリング順序もそれに応じて低く設定されることになります。&lt;/p&gt;
&lt;p&gt;以下のような問題が発生します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-4eabf03b3ea654d454f1a489fb89884d" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_01.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-4eabf03b3ea654d454f1a489fb89884d"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;以下のオブジェクトはデフォルトのレンダリング順序（ツリー順）で描画されています。シーンツリー上での配置は以下の通りです。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-67dd86304c5636510f8aac83d304fa84" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_06.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-67dd86304c5636510f8aac83d304fa84"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_06.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;Godotにはレンダリング順序を変更する組み込みオプションが用意されています。任意の&lt;i class="gd-CanvasItem"&gt;&lt;/i&gt;&lt;code&gt;CanvasItem&lt;/code&gt;ノード（&lt;i class="gd-Node2D"&gt;&lt;/i&gt;&lt;code&gt;Node2D&lt;/code&gt;または&lt;i class="gd-Control"&gt;&lt;/i&gt;&lt;code&gt;Control&lt;/code&gt;）に対して、&lt;strong&gt;Y軸ソート有効化&lt;/strong&gt; プロパティを有効にできます。この機能が有効になると、すべての子ノードがY軸に沿って並べ替えられます。&lt;/p&gt;
&lt;p&gt;上記の例では、&lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt;ノード上でプロパティを有効にできます。ただし、まだ解決すべき問題が残っています。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-8aa5526704f2e368cbdc1811fcb85c6c" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_01.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-8aa5526704f2e368cbdc1811fcb85c6c"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ドロー順序は各オブジェクトの &lt;code&gt;y&lt;/code&gt; 座標に基づいています。デフォルトではこれはオブジェクトの中心座標となります。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-4c4c25a67563948ae1d93c3928deef64" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_04.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-4c4c25a67563948ae1d93c3928deef64"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_04.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;オブジェクトが「地面」の上に配置されているように見せたい場合、オブジェクトの &lt;code&gt;position&lt;/code&gt; プロパティがスプライトの最下部位置と一致するようにオフセットすることで解決できます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-5cad22bb6d5ce119f3bde414a9bf5c68" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_05.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-5cad22bb6d5ce119f3bde414a9bf5c68"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_05.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;だいぶ良くなりました。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-c0aabd06adba01a83ee5c6a9a54567d3" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_02.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-c0aabd06adba01a83ee5c6a9a54567d3"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/ysort_02.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="プロジェクトのダウンロード"&gt;&lt;i class="fas fa-code-branch"&gt;&lt;/i&gt; プロジェクトのダウンロード&lt;/h2&gt;
&lt;p&gt;プロジェクトのサンプルコード: &lt;a href="https://github.com/godotrecipes/using_ysort" target="_blank"&gt;https://github.com/godotrecipes/using_ysort&lt;/a&gt;&lt;/p&gt;</description></item><item><title>タイルマップ：自動タイルを使用</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/autotile_intro/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/autotile_intro/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;&lt;i class="gd-TileMap"&gt;&lt;/i&gt; TileMapを使用し、自動タイル機能を活用してレベル作成を効率化したいです。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;本デモでは、以下のタイルセットを使用します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-fedad2ac0e6544ded8dc1a1063e6ab7a" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_tileset.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-fedad2ac0e6544ded8dc1a1063e6ab7a"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_tileset.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;div class="box notices cstyle note"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-circle"&gt;&lt;/i&gt; メモ&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;これらのタイルはKenney氏の『Topdown Shooter』アートパックに含まれており、こちらから入手できます。&lt;a href="https://kenney.nl/assets/top-down-shooter" target="_blank"&gt;https://kenney.nl/assets/top-down-shooter&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;これらのタイルから地図を作成する場合、1枚ずつ手動で配置していくと非常に手間がかかります。角や交差点、終点部分を合わせるために、常に異なるタイルを切り替えながら作業することになるからです。&lt;/p&gt;
&lt;p&gt;自動タイル機能を使用すると、壁を任意の方向に自由に描画でき、アルゴリズムが正しいタイルを選択して全体をシームレスに配置します。&lt;/p&gt;
&lt;p&gt;以下に具体例を示します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-8f60c25b3b433fce33091aea3e4ae6b1" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_demo.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-8f60c25b3b433fce33091aea3e4ae6b1"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_demo.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="自動タイリングの仕組みについて"&gt;自動タイリングの仕組みについて&lt;/h3&gt;
&lt;p&gt;使用しているタイルは &lt;code&gt;3×3（最小）&lt;/code&gt; のタイリング用に設計されています。単一のタイルを3×3グリッドに分割した場合を考えてみます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-ac3f2134c761f70187bdd737831a2cc8" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_bitmask_tile.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-ac3f2134c761f70187bdd737831a2cc8"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_bitmask_tile.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;タイルの「アクティブ」部分（つまり壁ではない箇所）に目印を付けることができます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-05e2c8a50ea823c918356af06166a84d" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_bitmask_tile2.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-05e2c8a50ea823c918356af06166a84d"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_bitmask_tile2.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これを各タイルごとに実行すれば、コンピュータはどのタイルを隣接させても確実に互換性が確保されるようにできます。&lt;/p&gt;
&lt;p&gt;3×3のグリッド上には、512通りの組み合わせパターンが存在します（2^9）。これらのほとんどは連続した壁を作る上で実用的ではないため、除外して構いません。実際に適切な形で壁面を覆うためには、48枚のタイルが必要であることが分かりました。これはタイルセットに用意されているものです。以下の7枚のタイルは無視することにします - 右下隅に位置する白い背景のタイルです。&lt;/p&gt;
&lt;h3 id="タイルセットの作成方法"&gt;タイルセットの作成方法&lt;/h3&gt;
&lt;p&gt;&lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt;のプロパティにある「タイルセット」設定で「新規タイルセット」を選択し、クリックするとエディターパネルが開きます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-c69f2ccd03b412ef9c1ba2ac0df865e2" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_frame.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-c69f2ccd03b412ef9c1ba2ac0df865e2"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_frame.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;テクスチャを追加するには ⊞ ボタンをクリックし、上記で選択したタイルセットを選択してください。次に「新規オートタイル」を選択し、画像全体をドラッグして選択します。スナップ機能を有効にし、設定を調整する必要があるかもしれません。このタイルセットのタイルは 64x64 ピクセルで、各タイル間は 10 ピクセル間隔になっています。独自のアートワークを使用する場合は、必要な値を手動で入力してください。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-49908fa07d5a1c45aae5d01d14f7e548" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_create.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-49908fa07d5a1c45aae5d01d14f7e548"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_create.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;オートタイルグループを構成するタイルセットを選択したので、次はビットマスクを設定する段階です。画面上部の「ビットマスク」ボタンをクリックし、各タイル上でクリックを開始してください。マスキングされた部分は赤く表示されます。作業が完了すると、以下のような状態になるはずです。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-deafc33c81a1f00e7f79f18893bcb031" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_bitmask.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-deafc33c81a1f00e7f79f18893bcb031"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/autotile_bitmask.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;※右下のタイルは使用していないことに注意してください。&lt;/p&gt;
&lt;p&gt;最後に、「アイコン」ボタンをクリックして、自動タイルグループのアイコンとして使用するタイルを選択してください。これが描画中にカーソル下に表示されるタイルとなります。&lt;/p&gt;
&lt;p&gt;タイルマップに切り替えてください。正常に描画できるはずです。問題がある場合は、ビットマスクを確認し、すべてのタイルに空白部分が残っていないか確認してください。上記の画像と照合して確認してください。&lt;/p&gt;</description></item><item><title>2Dグリッド上での経路探索</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/grid_pathfinding/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/grid_pathfinding/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;グリッドベースの環境があり、ナビゲーションを可能にする経路探索システムを構築したいです。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;Godot は経路探索のための複数の手法を提供しています。今回のレシピでは &lt;code&gt;A*(エースター)&lt;/code&gt; アルゴリズムを取り上げます。&lt;/p&gt;
&lt;div class="box notices cstyle info"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; A*について&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;A*アルゴリズムは、2点間の最短経路を求めるために広く利用されている手法です。グリッドに限らず、あらゆるグラフ構造データに適用できます。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;AStarGrid2D&lt;/code&gt; はGodotの汎用クラス &lt;code&gt;AStar2D&lt;/code&gt; をグリッド環境用に最適化した専用バージョンです。グリッドベースで設計されているため、個々のセルや接続関係を手動で追加する必要がなく、より高速かつ簡単にセットアップできます。&lt;/p&gt;
&lt;h3 id="グリッドの設定"&gt;グリッドの設定&lt;/h3&gt;
&lt;p&gt;最も重要な設定決定事項は、セルのサイズとグリッド自体のサイズです。ここでは例として &lt;code&gt;(64, 64)&lt;/code&gt; を使用しますが、ウィンドウサイズは画面上に収まるセル数を決定に使います。ただし、セルサイズが異なっても基本的な動作原理は同じです。&lt;/p&gt;
&lt;p&gt;このコードを &lt;i class="gd-Node2D"&gt;&lt;/i&gt;&lt;code&gt;Node2D&lt;/code&gt;に追加してください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Node2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; cell_size &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2i&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;64&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;64&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; astar_grid &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;AStarGrid2D&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;new&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; grid_size
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_ready&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;initialize_grid&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;initialize_grid&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; grid_size &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2i&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_viewport_rect&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;size&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; cell_size
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; astar_grid&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;size &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; grid_size
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; astar_grid&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;cell_size &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; cell_size
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; astar_grid&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;offset &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; cell_size &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#b48ead"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; astar_grid&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;update&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコードでは、画面サイズを &lt;code&gt;cell_size&lt;/code&gt; で割ることでグリッド全体の寸法を計算しています。これにより、&lt;code&gt;AStarGrid2D&lt;/code&gt; オブジェクトの &lt;code&gt;size&lt;/code&gt; プロパティを適切に設定できます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;offset&lt;/code&gt;プロパティは、2点間のパスを取得する際に重要な役割を果たします。&lt;code&gt;cell_size / 2&lt;/code&gt;を使用することで、パスはセルの角ではなく中心から計算されるようになります。&lt;/p&gt;
&lt;p&gt;最後に、&lt;code&gt;AStarGrid2D&lt;/code&gt;のプロパティを設定または変更した後は必ず&lt;code&gt;update()&lt;/code&gt;メソッドを呼び出す必要があります。&lt;/p&gt;
&lt;h3 id="グリッド線の描画"&gt;グリッド線の描画&lt;/h3&gt;
&lt;p&gt;本デモでは、グリッドの描画をプログラムコードで実装します。実際のゲームアプリケーションでは、通常 &lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt; クラスやその他の視覚的表現を用いて世界を表現になります。&lt;/p&gt;
&lt;p&gt;以下は、グリッドを描画するためのコード例です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_draw&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;draw_grid&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;draw_grid&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;for&lt;/span&gt; x &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt; grid_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;draw_line&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; cell_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; cell_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; grid_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; cell_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y&lt;span style="color:#eceff4"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8fbcbb"&gt;Color&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;DARK_GRAY&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;2.0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;for&lt;/span&gt; y &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt; grid_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;draw_line&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; y &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; cell_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y&lt;span style="color:#eceff4"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;grid_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; cell_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; y &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; cell_size&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y&lt;span style="color:#eceff4"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#8fbcbb"&gt;Color&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;DARK_GRAY&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;2.0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これによりグリッドが視覚的に明確に表示されます。&lt;/p&gt;</description></item><item><title>アニメーションタイル(タイルマップ)</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/tilemap_animation/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/tilemap_animation/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;タイルマップでアニメーションタイルを使用したい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この問題に対処する最も直接的な方法は、&lt;code&gt;AnimatedTexture&lt;/code&gt;リソースを使用することです。&lt;/p&gt;
&lt;h3 id="アニメーションテクスチャの作成方法"&gt;アニメーションテクスチャの作成方法&lt;/h3&gt;
&lt;p&gt;以下の水タイルを使用して説明します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-b9f13e1efe525d9292e6136b4eba2e06" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_tiles.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-b9f13e1efe525d9292e6136b4eba2e06"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_tiles.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これらの画像をダウンロードしてください。&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/files/water_tiles.zip"&gt;water.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;画像ファイルをプロジェクトフォルダに解凍してください。
インスペクタで「新しいリソースを作成」ボタンをクリックします。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-67338181771841e64a7f1bf6d52a41f7" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/create_new_resource.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-67338181771841e64a7f1bf6d52a41f7"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/create_new_resource.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;AnimatedTexture&lt;/code&gt;を選択し、［フレーム］プロパティを&lt;code&gt;5&lt;/code&gt;に設定します。各フレームごとに、対応する画像を［テクスチャ］プロパティにドラッグしてください。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-359fb1747a03d8bb89543d74fe7fecaa" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_texture_add.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-359fb1747a03d8bb89543d74fe7fecaa"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_texture_add.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;アニメーション全体の速度は &lt;em&gt;Fps&lt;/em&gt; プロパティで、各フレームごとの遅延時間は &lt;em&gt;Delay Sec&lt;/em&gt; で個別に調整できます。&lt;/p&gt;
&lt;p&gt;「保存」ボタンをクリックしてリソースを保存します。&lt;code&gt;water_anim.tres&lt;/code&gt;のような名前を付けてください。&lt;/p&gt;
&lt;h3 id="tilemapでのanimatedtextureの使用について"&gt;TileMapでのAnimatedTextureの使用について&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;AnimatedTexture&lt;/code&gt; が保存されたので、これで&lt;code&gt;TileSet&lt;/code&gt;で使用できるようになります。新規または既存の&lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt;を開き、その &lt;em&gt;Tile Set&lt;/em&gt; プロパティを選択します。新しいテクスチャを&lt;code&gt;TileSet&lt;/code&gt;に追加するには、ボタンをクリックしてください。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-8d748ed27a2ded9358d7e7cae8b9cf1b" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_tile_add.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-8d748ed27a2ded9358d7e7cae8b9cf1b"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_tile_add.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;追加された新規テクスチャを選択し、「単一タイルとして新規作成」をクリックします。テクスチャを囲むようにボックスを描きます（「スナップ機能を有効にする」を設定すると作業が楽になります）。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-197151b2b96b796779c304863c92a45e" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_tile_select.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-197151b2b96b796779c304863c92a45e"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_tile_select.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;これで&lt;code&gt;TileMap&lt;/code&gt;内のタイルを選択して、他の通常のタイルと同じように描画できるようになります。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-8923f47dfbab387d72e555ce5c1ad1cf" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_tile_draw.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-8923f47dfbab387d72e555ce5c1ad1cf"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/anim_tile_draw.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;translation&gt;&lt;/translation&gt;&lt;/p&gt;
&lt;h2 id="関連するレシピ"&gt;関連するレシピ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/autotile_intro"&gt;タイルマップ：オートタイルの活用&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>コヨーテタイム</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/coyote_time/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/coyote_time/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;プラットフォームゲームのジャンプ操作に違和感があります。プレイヤーはコントロールが取りづらく、場合によっては足場に正しく飛び降りられないことがあります。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この問題を解決するには、「コヨーテタイム」と呼ばれるテクニックが有効です。これはプレイヤーにより高い操作感覚と、プラットフォームの端を移動するプロセスにおいて若干の「余裕時間」を提供します。また、プレイヤーがより自然にジャンプ操作を行えるようになります。&lt;/p&gt;
&lt;p&gt;「コヨーテタイム」の仕組みは以下の通りです。&lt;/p&gt;
&lt;p&gt;プレイヤーがプラットフォームの端から離れた場合、数フレームの間は依然として地面にいるかのようにジャンプできます。&lt;/p&gt;
&lt;div class="box notices cstyle info"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; そもそもなぜコヨーテ？&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;「コヨーテタイム」という名称は、地面を見下ろすまで落下しないカートゥーンキャラクターのコヨーテに由来しています。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-c2426ea7cbfcda9bf6cd7002c0706041" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/coyote.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-c2426ea7cbfcda9bf6cd7002c0706041"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/coyote.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;この機能を既存のプラットフォームキャラクターに追加してください。設定方法については&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/2d/platform_character/"&gt;プラットフォームキャラクター&lt;/a&gt;を参照してください。&lt;/p&gt;
&lt;p&gt;タイミング処理に関しては、&lt;code&gt;CoyoteTimer&lt;/code&gt;という名前の&lt;i class="gd-Timer"&gt;&lt;/i&gt;&lt;code&gt;Timer&lt;/code&gt;ノードを追加し、設定を&lt;strong&gt;One Shot&lt;/strong&gt;にします。&lt;/p&gt;
&lt;p&gt;コヨーテタイム管理に必要な新しい変数を用意しましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; coyote_frames &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;6&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# How many in-air frames to allow jumping&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; coyote &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;false&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Track whether we&amp;#39;re in coyote time or not&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; last_floor &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;false&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Last frame&amp;#39;s on-floor state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;フレーム単位で時間を設定しているため、&lt;code&gt;_ready()&lt;/code&gt;内で&lt;i class="gd-Timer"&gt;&lt;/i&gt;&lt;code&gt;Timer&lt;/code&gt;の長さを設定する際にも次のように変換できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$CoyoteTimer&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;wait_time &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; coyote_frames &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#b48ead"&gt;60.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;各フレームで現在の &lt;code&gt;is_on_floor()&lt;/code&gt; 値を保存し、次のフレームで使用するようにします。したがって、&lt;code&gt;move_and_slide()&lt;/code&gt; の後に &lt;code&gt;_physics_process()&lt;/code&gt; 内に以下を設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; last_floor &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;is_on_floor&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ジャンプ入力を検知した場合、キャラクターが床にいる状態か、またはコヨーテ時間モードかどうかを確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_just_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;jump&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_on_floor&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;or&lt;/span&gt; coyote&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; jump_speed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; jumping &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;コヨーテ状態への移行は、プレイヤーがプラットフォームの端から降りた瞬間に開始されます。これは、前回のフレームでは床の上にいたが、現在は床から離れた位置にいるということです。この条件を確認した上で、ちょうど地面から離れた時にタイマーを起動します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;!&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_on_floor&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; last_floor &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;!&lt;/span&gt;jumping&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; coyote &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $CoyoteTimer&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;start&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;CoyoteTimer&lt;/code&gt;は以下のタイミングでコヨーテ状態の終了を通知します。&lt;/p&gt;</description></item><item><title>動く床</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/moving_platforms/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/moving_platforms/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;2Dプラットフォーマーゲームには動く床が必要です。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この問題には複数のアプローチ方法があります。ここではプラットフォーム部分に &lt;i class="gd-AnimatableBody2D"&gt;&lt;/i&gt;&lt;code&gt;AnimatableBody2D&lt;/code&gt; を使用し、&lt;i class="gd-Tween"&gt;&lt;/i&gt;&lt;code&gt;Tween&lt;/code&gt; で移動させる手法を採用します。これにより、多様な動作パターンを実現しながら、必要なコード量を最小限に抑えることができます。&lt;/p&gt;
&lt;div class="box notices cstyle info"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; 情報&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この移動プラットフォームの実装方法は、Tweenではなく &lt;i class="gd-AnimationPlayer"&gt;&lt;/i&gt;&lt;code&gt;AnimationPlayer&lt;/code&gt; を使用することでもできます。基本的なセットアップ手順は同様ですが、代わりにTweenコードの代わりにボディの &lt;code&gt;position&lt;/code&gt; プロパティをアニメーション化します。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="セットアップ方法"&gt;セットアップ方法&lt;/h3&gt;
&lt;p&gt;まずは&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/2d/platform_character/"&gt;プラットフォームキャラクター&lt;/a&gt;レシピを使用して、基本的なプラットフォーマーのセットアップから始めてください。このレシピで定義されている基本移動機能は、指定されたプラットフォームと問題なく連携します。もしレシピをカスタマイズしていたり、独自の実装を使用している場合でも、動作原理は同じですのでご安心ください。&lt;/p&gt;
&lt;h3 id="プラットフォームの作成"&gt;プラットフォームの作成&lt;/h3&gt;
&lt;p&gt;プラットフォームシーンには以下のノードが含まれています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i class="gd-Node2D"&gt;&lt;/i&gt;&lt;code&gt;Node2D&lt;/code&gt; (&amp;ldquo;MovingPlatform&amp;rdquo;)：この &lt;code&gt;Node2D&lt;/code&gt; の親ノードは、プラットフォームの「アンカー」または開始点として機能します。アニメーションでは、この親ノードを基準としてプラットフォームの &lt;code&gt;座標&lt;/code&gt; を制御します。
&lt;ul&gt;
&lt;li&gt;&lt;i class="gd-AnimatableBody2D"&gt;&lt;/i&gt;&lt;code&gt;AnimatableBody2D&lt;/code&gt;：これは実際に移動するプラットフォーム本体を表します。このノードが移動対象となります。
&lt;ul&gt;
&lt;li&gt;&lt;i class="gd-Sprite2D"&gt;&lt;/i&gt;&lt;code&gt;Sprite2D&lt;/code&gt;：ここではスプライトシート、個別の画像、あるいは &lt;i class="gd-TileMap"&gt;&lt;/i&gt; ノードとしてタイルマップを使用することもできます。&lt;/li&gt;
&lt;li&gt;&lt;i class="gd-CollisionShape2D"&gt;&lt;/i&gt;&lt;code&gt;CollisionShape2D&lt;/code&gt;：ヒットボックスの大きさが大きすぎると、プレイヤーがプラットフォームの端から「浮いて」見える原因になるので注意してください。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;i class="gd-Sprite2D"&gt;&lt;/i&gt;&lt;code&gt;Sprite2D&lt;/code&gt;の&lt;strong&gt;テクスチャ&lt;/strong&gt;と衝突形状を適切に設定してください。&lt;i class="gd-AnimatableBody2D"&gt;&lt;/i&gt;&lt;code&gt;AnimatableBody2D&lt;/code&gt;では、&lt;strong&gt;Sync to Physics(物理演算と同期)&lt;/strong&gt; プロパティを「オン」に設定します。コードでボディを動かしているため、これにより物理演算ステップ時に正しく移動され、プレイヤーや他の物理オブジェクトと連動した動きを維持できます。&lt;/p&gt;
&lt;p&gt;次にルートノードの&lt;i class="gd-Node2D"&gt;&lt;/i&gt;&lt;code&gt;Node2D&lt;/code&gt;にスクリプトを追加してください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Node2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; offset &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;&lt;span style="color:#b48ead"&gt;320&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; duration &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;5.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_ready&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;start_tween&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;start_tween&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; tween &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;get_tree&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;create_tween&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;set_process_mode&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Tween&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;TWEEN_PROCESS_PHYSICS&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tween&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;set_loops&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;set_parallel&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;false&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tween&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;tween_property&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;$AnimatableBody2d&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;position&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; offset&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; duration &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#b48ead"&gt;2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tween&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;tween_property&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;$AnimatableBody2d&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;position&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ZERO&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; duration &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#b48ead"&gt;2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;i class="gd-Tween"&gt;&lt;/i&gt;以下の機能をスムーズに動作させるために、&lt;code&gt;Twien&lt;/code&gt; のオプションを活用しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;set_process_mode()&lt;/code&gt;：物理演算処理段階でのみ移動が行われるようにします。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;set_loops()&lt;/code&gt;：Tween再生を繰り返す設定です。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;set_parallel(false)&lt;/code&gt;：デフォルトでは、すべての &lt;code&gt;tween_property()&lt;/code&gt; 変更が同時に実行されます。これを無効にすると、2つの動作が順次行われます。オフセットの一方端に移動した後、開始位置に戻るという流れになります。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;翻訳された2つのプロパティを使用することで、プラットフォームの移動を調整できます。&lt;code&gt;offset&lt;/code&gt;を設定してTweenが開始点から相対的に移動する位置を指定し、&lt;code&gt;duration&lt;/code&gt;を設定してサイクルを完了するまでの時間を決定します。&lt;/p&gt;
&lt;p&gt;自分のレベル／ワールドにプラットフォームを追加し、実際に試してみてください。&lt;/p&gt;
&lt;p&gt;&lt;video controls src="https://kamera25.github.io/godot_recipes/4.x/img/moving_platform4.webm" autoplay="true"&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h2 id="プロジェクトのダウンロード"&gt;&lt;i class="fas fa-code-branch"&gt;&lt;/i&gt; プロジェクトのダウンロード&lt;/h2&gt;
&lt;p&gt;プロジェクトコードはこちらからダウンロードできます。 &lt;a href="https://github.com/godotrecipes/2d_moving_platforms" target="_blank"&gt;https://github.com/godotrecipes/2d_moving_platforms&lt;/a&gt;&lt;/p&gt;</description></item><item><title>マルチターゲットカメラ</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/multi_target_camera/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/multi_target_camera/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;複数のオブジェクトを同時に画面上に表示し続けるために、移動・ズーム機能を備えたダイナミックなカメラシステムを作りたいです。&lt;/p&gt;
&lt;p&gt;2人用ゲームで両プレイヤーを画面内に表示したまま、互いに近づき離れていく様子を表現する場合などです。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-4f530b8367ba1b9a346ff0e3aa09373d" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/multi_cam_01.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-4f530b8367ba1b9a346ff0e3aa09373d"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/multi_cam_01.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;シングルプレイヤーモードでは、カメラをプレイヤーに追従させるのが一般的な手法です。しかし、ここでは2人以上のプレイヤーやその他の重要オブジェクトが常に画面に表示され続ける必要があるため、同様の方法は適用できません。&lt;/p&gt;
&lt;p&gt;以下の3つの機能をカメラに実装が必要です。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ターゲットを任意の数だけ追加/削除可能&lt;/li&gt;
&lt;li&gt;カメラの位置をターゲット群の中心点に固定表示&lt;/li&gt;
&lt;li&gt;すべてのターゲットが画面内に収まるようズームレベルを調整&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以下の手順で新規シーンを作成し、&lt;i class="gd-Camera2D"&gt;&lt;/i&gt;&lt;code&gt;Camera2D&lt;/code&gt;コンポーネントを追加してスクリプトを割り当てます。作業が完了したら、このカメラをゲームに統合します。&lt;/p&gt;
&lt;p&gt;スクリプトの動作原理を分解して説明します。&lt;/p&gt;
&lt;div class="box notices cstyle note"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-circle"&gt;&lt;/i&gt; メモ&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;スクリプトの全文は&lt;a href="#%e5%85%a8%e3%82%b9%e3%82%af%e3%83%aa%e3%83%97%e3%83%88"&gt;記事の末尾&lt;/a&gt;で確認できます。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下にスクリプトの開始部分を示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Camera2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; move_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;30&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# camera position lerp speed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; zoom_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;3.0&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# camera zoom lerp speed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; min_zoom &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;5.0&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# camera won&amp;#39;t zoom closer than this&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; max_zoom &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0.5&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# camera won&amp;#39;t zoom farther than this&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; margin &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;400&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;200&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# include some buffer area around targets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; targets &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#eceff4"&gt;[]&lt;/span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Array of targets to be tracked.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@onready&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; screen_size &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;get_viewport_rect&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;size
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これらの設定によりカメラ動作を調整できるようになります。すべてのカメラ変更を &lt;code&gt;lerp()&lt;/code&gt; で補間処理するため、移動速度やズーム速度を低く設定した場合、突然の変化に対してカメラが「追いつく」まで若干の遅延が生じます。&lt;/p&gt;</description></item><item><title>Line2D衝突判定</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/line_collision/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/line_collision/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;衝突検出を &lt;i class="gd-Line2D"&gt;&lt;/i&gt;&lt;code&gt;Line2D&lt;/code&gt; に対して行いたい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;h3 id="ノード設定"&gt;ノード設定&lt;/h3&gt;
&lt;p&gt;以下のノードをシーンに追加し、必要に応じてラインを描いてください。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&lt;i class="gd-Line2D"&gt;&lt;/i&gt; Line2D
&lt;i class="gd-StaticBody2D"&gt;&lt;/i&gt; StaticBody2D
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;まだボディに衝突形状を追加しないでください！&lt;/p&gt;
&lt;div class="box notices cstyle note"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-circle"&gt;&lt;/i&gt; メモ&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;衝突ではなく線との重複を検出したい場合は、代わりに &lt;i class="gd-Area2D"&gt;&lt;/i&gt;&lt;code&gt;Area2D&lt;/code&gt; を使用することもできます。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;次に、ボディに衝突形状を追加が必要です。以下の2つのオプションがあります。&lt;/p&gt;
&lt;h3 id="その1hahahugoshortcode99s4hbhbsegmentshape2dの使用"&gt;その1：&lt;i class="gd-SegmentShape2D"&gt;&lt;/i&gt;&lt;code&gt;SegmentShape2D&lt;/code&gt;の使用&lt;/h3&gt;
&lt;p&gt;&lt;i class="gd-SegmentShape2D"&gt;&lt;/i&gt;&lt;code&gt;SegmentShape2D&lt;/code&gt; は線分衝突形状です。この手法の目的は、直線上の各点ペアに対して個別のセグメント衝突を作成することです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Line2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_ready&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;for&lt;/span&gt; i &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt; points&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;size&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; new_shape &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;CollisionShape2D&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;new&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $StaticBody2D&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;add_child&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;new_shape&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; segment &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;SegmentShape2D&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;new&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; segment&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;a &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; points&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;i&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; segment&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;b &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; points&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;i &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&lt;/span&gt;&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; new_shape&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;shape &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; segment
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="その2hahahugoshortcode99s6hbhbrectangleshape2dを使用する場合"&gt;その2：&lt;i class="gd-RectangleShape2D"&gt;&lt;/i&gt;&lt;code&gt;RectangleShape2D&lt;/code&gt;を使用する場合&lt;/h3&gt;
&lt;p&gt;&lt;i class="gd-SegmentShape2D"&gt;&lt;/i&gt;&lt;code&gt;SegmentShape2D&lt;/code&gt; は幅成分を持たないため、線の衝突判定に厚みが必要な場合には、代わりに矩形の衝突判定を使用することをオススメします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Line2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_ready&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;for&lt;/span&gt; i &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt; points&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;size&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; new_shape &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;CollisionShape2D&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;new&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $StaticBody2D&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;add_child&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;new_shape&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; rect &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;RectangleShape2D&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;new&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; new_shape&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;position &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;points&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;i&lt;span style="color:#eceff4"&gt;]&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; points&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;i &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&lt;/span&gt;&lt;span style="color:#eceff4"&gt;])&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#b48ead"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; new_shape&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;rotation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; points&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;i&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;direction_to&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;points&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;i &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&lt;/span&gt;&lt;span style="color:#eceff4"&gt;])&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;angle&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; length &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; points&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;i&lt;span style="color:#eceff4"&gt;]&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;distance_to&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;points&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;i &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&lt;/span&gt;&lt;span style="color:#eceff4"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rect&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;extents &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;length &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#b48ead"&gt;2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; width &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#b48ead"&gt;2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; new_shape&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;shape &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; rect
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="プロジェクトのダウンロード"&gt;&lt;i class="fas fa-code-branch"&gt;&lt;/i&gt; プロジェクトのダウンロード&lt;/h2&gt;
&lt;p&gt;プロジェクトのサンプルコードはこちらからダウンロードできます。&lt;a href="https://github.com/godotrecipes/line2d_collision" target="_blank"&gt;https://github.com/godotrecipes/line2d_collision&lt;/a&gt;&lt;/p&gt;</description></item><item><title>タッチスクリーンカメラ</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/touchscreen_camera/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/touchscreen_camera/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;モバイルゲームには、タッチ操作対応の2Dカメラが必要です。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;このレシピでは、複数のタッチ操作に対応した汎用2Dカメラを作成します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ドラッグで画面移動&lt;/li&gt;
&lt;li&gt;2本指でピンチイン/アウトすると拡大縮小できます&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="設定手順"&gt;設定手順&lt;/h3&gt;
&lt;p&gt;当社のカメラは内蔵ノードを拡張するため、新しいシーンに &lt;i class="gd-Camera2D"&gt;&lt;/i&gt;&lt;code&gt;Camera2D&lt;/code&gt; を追加し、「TouchCamera」と名前を付けてください。保存後、スクリプトをアタッチします。&lt;/p&gt;
&lt;p&gt;以下に必要となる変数を示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Camera2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; target&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;NodePath&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#616e87;font-style:italic"&gt;# Optional: export these properties for convenient editing.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; target_return_enabled &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; target_return_rate &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0.02&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; min_zoom &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; max_zoom &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; zoom_sensitivity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; zoom_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0.05&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; events &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; last_drag_distance &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もし&lt;code&gt;target&lt;/code&gt;が設定されている場合、カメラはその対象物を追いかける、または自動的にその位置に戻ることができます。その他のカメラ動作を制御するプロパティ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;target_return_enabled&lt;/code&gt; - これを &lt;code&gt;true&lt;/code&gt; に設定すると、ドラッグ後にカメラは自動的にターゲット位置に復帰します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;target_return_rate&lt;/code&gt; - カメラがターゲット位置に戻る速度を調整します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;min_zoom&lt;/code&gt; / &lt;code&gt;max_zoom&lt;/code&gt; - ズームの最小/最大倍率制限値を設定します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zoom_sensitivity&lt;/code&gt; - ピンチ操作によるズーム感度を設定します - これは「ズーム動作」が開始されるために必要なピクセル単位の動きを指定します。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zoom_speed&lt;/code&gt; - ズーム操作をより滑らかに実行するためのパラメータです。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下のプロパティも &lt;code&gt;export&lt;/code&gt; することで、インスペクターで調整できるようになります。&lt;/p&gt;</description></item><item><title>弾道銃弾</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/ballistic_bullet/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/ballistic_bullet/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;ご希望の2D弾は弧を描くように移動したり、弾道曲線を描いたりする仕様でしょうか？&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この問題に対する解決策の一つとして、&lt;i class="gd-RigidBody2D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody2D&lt;/code&gt; コンポーネントを使用することが考えられます。組み込みの物理演算システムにより、発射後も重力によって自動的に地球へ引き戻されるよう設定できます。&lt;/p&gt;
&lt;p&gt;ただし、&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/2d/2d_shooting/"&gt;2Dシューティングゲームのレシピ&lt;/a&gt;で解説されているように、&lt;i class="gd-Area2D"&gt;&lt;/i&gt;&lt;code&gt;Area2D&lt;/code&gt;は単純な弾丸やその他の投射物に非常に適しています。衝突判定やバウンド、その他の物理挙動を必要としない場合には特に便利です。弾道計算自体は難しくないため、物理エンジンの助けを借りるほどでもありません。&lt;/p&gt;
&lt;h3 id="弾丸の設定"&gt;弾丸の設定&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;-&lt;/span&gt; Bullet (Area2D)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;-&lt;/span&gt; Sprite
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;-&lt;/span&gt; CollisionShape2D
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下の方法で利用できます。&lt;i class="gd-Area2D"&gt;&lt;/i&gt;&lt;code&gt;Area2D&lt;/code&gt; の &lt;code&gt;gravity&lt;/code&gt; プロパティを設定します。初期テストでは値を &lt;code&gt;150&lt;/code&gt; に設定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Area2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;350&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; gravity &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; velocity &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rotation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;angle&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_on_BallisticBullet_body_entered&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;body&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;queue_free&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで必要なのは&lt;a href="https://www.khanacademy.org/science/physics/one-dimensional-motion/kinematic-formulas/a/what-are-the-kinematic-formulas" target="_blank"&gt;運動方程式&lt;/a&gt;を適用するだけです。&lt;code&gt;velocity&lt;/code&gt; の初期値は単なるテスト用です。ブレットシーンを実行してください。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-d15f3419da9109c601dd81577c293ebf" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/2d_ballistic_01.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-d15f3419da9109c601dd81577c293ebf"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/2d_ballistic_01.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;現在の射撃オブジェクトでは、弾丸インスタンスを作成し、初期プロパティを設定できます。以下のいずれかの射撃処理関数／入力ハンドラに実装してください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; muzzle_velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;350&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; gravity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;250&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;shoot&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; b &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; Bullet&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;instantiate&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; owner&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;add_child&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;b&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Barrel/Marker2D&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_transform
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; b&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; muzzle_velocity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;gravity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; gravity
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下に実際の使用例をご紹介します。&lt;/p&gt;</description></item><item><title>軌跡を描画</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/2d/2d_draw_trajectory/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/2d/2d_draw_trajectory/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;戦車のような弾道射撃の軌道を描きたい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;h3 id="設定手順"&gt;設定手順&lt;/h3&gt;
&lt;p&gt;この例では、以下のレシピから「弾道弾丸」を使用します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/2d/ballistic_bullet/"&gt;弾道弾の実装方法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そして、以下のように設定されたタンクの配置です。ここでは弾丸が生成される箇所を示すために の &lt;i class="gd-Marker2D"&gt;&lt;/i&gt;&lt;code&gt;Marker2D&lt;/code&gt; 要素を使用しています。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-c70cc66b667b78d3eded72566e670d43" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/tank_01.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-c70cc66b667b78d3eded72566e670d43"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/tank_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;タンクのスクリプトでは、弾丸を以下のようにインスタンス化しています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_unhandled_input&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;event&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; event&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_released&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;shoot&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; can_shoot&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; b &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; Bullet&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;instantiate&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; owner&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;add_child&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;b&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Barrel/Muzzle&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_transform
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; b&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; muzzle_velocity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;gravity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; gravity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; can_shoot &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このインスタンスでは弾丸オブジェクトを作成し、「World」ノード（戦車の&lt;code&gt;owner&lt;/code&gt;）の下に子要素として追加し、初期プロパティを設定します。なお、この例では重力定義に戦車を利用していますが、これは単なるデモンストレーション用です。実際のプロジェクトでは、グローバルな値を使用する方が望ましいでしょう。&lt;/p&gt;
&lt;p&gt;以下に、初期設定の動作例をご紹介します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-f5e059c2d7180a321394e507bb049036" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/tank_02.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-f5e059c2d7180a321394e507bb049036"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/tank_02.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="ライン設定"&gt;ライン設定&lt;/h3&gt;
&lt;p&gt;メインシーン内（タンクと地面を含む部分）に、&lt;i class="gd-Line2D"&gt;&lt;/i&gt;&lt;code&gt;Line2D&lt;/code&gt; を追加しました。これが軌跡を描画するための要素となります。&lt;/p&gt;
&lt;p&gt;ラインの見た目を改善するため、&lt;strong&gt;幅&lt;/strong&gt;を&lt;code&gt;15&lt;/code&gt;に設定し、すべての&lt;strong&gt;角処理&lt;/strong&gt;オプションを「丸み」に変更しました。さらに、 &lt;strong&gt;Fill(塗りつぶし)&lt;/strong&gt; セクションに&lt;code&gt;Gradient(グラデーション)&lt;/code&gt;を追加しました。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-fe981f14d4dfe95e7915159c5025a20c" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/2d_tank_03.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-fe981f14d4dfe95e7915159c5025a20c"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/2d_tank_03.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="線を引くこと"&gt;線を引くこと&lt;/h3&gt;
&lt;p&gt;これで線を引く準備が整いました。目標は、投影された軌道に沿って移動しながら、進行状況に応じて線に点を追加していくことです。発射時の初速度と弾丸が使用する重力がわかっているので、同じ計算式を適用できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@onready&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; tank &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Tank
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@onready&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; muzzle &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Tank/Barrel/Muzzle
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@onready&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; line &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Line2D
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; max_points &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;250&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;update_trajectory&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; line&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;clear_points&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; pos &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; muzzle&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_position
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; vel &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; muzzle&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; tank&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;muzzle_velocity
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;for&lt;/span&gt; i &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt; max_points&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; line&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;add_point&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;pos&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; vel&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; tank&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;gravity &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pos &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; vel &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; pos&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt; $Ground&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;position&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; &lt;span style="color:#b48ead"&gt;25&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;shoot&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; line&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;show&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;update_trajectory&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_on_Bullet_exploded&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;pos&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tank&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;can_shoot &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; line&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;hide&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;max_points&lt;/code&gt;でラインに追加するポイント数の上限を設定します。&lt;code&gt;update_trajectory()&lt;/code&gt;関数では、タンクから弾丸の初期位置と速度を取得します（この例では重力もタンク内で定義されています）。その後、これらの点を繰り返し処理し、各「ステップ」でポジションを、1フレーム中に弾丸が移動する量と同じだけ移動させます。&lt;/p&gt;</description></item></channel></rss>