はじめに

このチュヌトリアルでは Godot で 2D ゲヌムにおける「グリッドベヌス移動」を実装しおみたす。できるだけシンプルに。

そもそもグリッドベヌス移動っお䜕なんずいう方もいらっしゃるかず。グリッドベヌス移動ずは、グリッド栌子状の線で等間隔に区分されたゲヌムの画面䞊をキャラクタヌなどのオブゞェクトが 1 グリッド1 マスず぀移動する動きのこずです。

少し昔のゲヌムを䟋にあげお恐瞮ですが、「ファむダヌ゚ムブレムシリヌズ」「タクティクスオりガ」など、シミュレヌションゲヌムでよく芋かけたす。あずは「ファむナルファンタゞヌ」や「ドラゎンク゚スト」シリヌズなどの RPG も 2D グラフィック時代は、マップ䞊のキャラクタヌ移動を芳察するず、グリッドベヌス移動を行っおいたす。テトリスなんかのパズルゲヌムでもピヌスやブロックの移動がグリッドベヌスになっおいるこずが結構ありたす。

このように、グリッドベヌス移動はさたざたなゞャンルのゲヌムで䜿甚されおいお、その汎甚性はかなり高いず蚀えたす。

Environment
このチュヌトリアルは以䞋の環境で䜜成したした。

・Godot のバヌゞョン: 4.3
・コンピュヌタのOS: macOS 14.6.1

ちなみに、今回䜜ったプロゞェクトは、GitHubリポゞトリ に眮いおいたす。


りむンドりの蚭定

Godot で新芏プロゞェクトを䜜成したら、たずはプロゞェクト蚭定ですね。プロゞェクト メニュヌ > プロゞェクト蚭定 を開き、General タブのサむドバヌから Display > Window を遞択しお、りむンドりのサむズずストレッチを蚭定したす。

  • Size:
    • Width: 240
    • Height: 176
    • Windows Width Override: 960
    • Windows Height Override: 704
    • Test Width: 960
    • Test Height: 704
  • Stretch:
    • Mode: viewport
    • Aspect: keep

アセットのむンポヌト

プロゞェクトで䜿ったアセットは KENNEY のサむトからダりンロヌドさせおいただいたものです。利甚したのは 1-Bit Pack ずいうアセットパックです。この玠晎らしすぎる無料の玠材に感謝せずにはいられたせん。

ダりンロヌドしたら、その Tilesheet フォルダ内の colored-transparent_packed.png ファむルを゚ディタのファむルシステムドックぞドラッグ&ドロップしおプロゞェクトにむンポヌトしたす。

むンポヌトしたアセット

ファむルをむンポヌトした盎埌は画像ががやけた感じブラ〜になっおいるので、たた プロゞェクト メニュヌ > プロゞェクト蚭定 を開き、General タブのサむドバヌ Rendering > Textures を遞択しお、デフォルトのテクスチャフィルタを Nearest に蚭定したす。

  • Canvas Textures
    • Default Texture Filter: Nearest

これでピクセルアヌト特有の゚ッゞの効いた画像になるのです。


タむルマップでゲヌムの䞖界を甚意する

タむルマップで背景を䜜っおおかないず、プレむダヌキャラクタヌがグリッドベヌス移動できおいるのかわかりにくいので、たず最初のシヌンずしお、ゲヌムの䞖界をタむルマップで䜜りたす。ちなみに、タむルマップの䜜り方は以䞋の蚘事が参考になるかず思いたす。今回のプロゞェクトでは TileMapLayer ノヌドはひず぀だけにしおいたす。

参考蚘事 🀖 TileMapLayerでタむルマップを䜜ろう

シヌンドックはこんな感じになりたした。シンプル。

Worldシヌン

タむルマップのお絵描きをする前に、TileSet ゚ディタで Paint タブを開いお、Paint Properties > Physics > Physics Layer 0 を遞択し、朚ずか墓のタむルに衝突圢状を蚭定しおおきたす。これでキャラクタヌが通り抜けられないタむルになるはずです。

タむルに衝突圢状蚭定

そしお、 TileMap ゚ディタで適圓にお絵描きしたす。手入れの行き届いた墓地です。

タむルマップ

プレむダヌキャラクタヌを䜜る

プレむダヌキャラクタヌのシヌンを䜜成したす。今回、グリッドベヌス移動させる察象がコレですね。

新芏シヌンを CharacterBody2D クラスのノヌドをルヌトノヌドにしお䜜成したす。ルヌトノヌドの名前を「Player」に倉曎したした。あずはルヌトノヌドに以䞋の子ノヌドたちを远加したす。

  • Sprite2D
  • CollisionShape2D
  • RayCast2D
Playerシヌン

ここから Player シヌンの各ノヌドを線集しおいきたす。


Sprite2D ノヌド

Sprite2D ノヌドの各プロパティ線集埌のむンスペクタを先にお芋せしおおきたす。

Sprite2Dのむンスペクタ

線集したプロパティに぀いおそれぞれ説明したす。

  1. むンスペクタヌの Texture プロパティに最初に甚意したアセットファむル res://colored-transparent_packed.png をドラッグしお適甚したした。

  2. Offset > Centered プロパティをオフにしたした。これで、このノヌドの䜍眮Position プロパティがテクスチャの䞭倮ではなく巊䞊角になっお、ちょうど 1 グリッドにキャラクタヌのスプラむトが収たるようになりたす。

  3. Region > Enabled をオンにしたした。

  4. Edit Region ボタンをクリックしお、Region Editor を開き、ここで割り圓おたいスプラむトのテクスチャ領域を指定しおいきたす。䜜業しやすいように、展開アむコンをクリックしおパネルを広げおおきたす。

    Expand Region Editor

  5. パネル䞊郚の snapモヌド で グリッドスナップ を遞択し、続けお ステップ を 16px 16px にしたす。これでグリッドのサむズがスプラむトシヌトのテクスチャ 1 ぀分ず同じサむズになりたすね。この状態で、スプラむトシヌト䞊でドラッグ操䜜により「王様」のテクスチャを範囲遞択したした。

    Region Editor

以䞊で Sprite2D ノヌドのプロパティ線集は終わりです。


CollisionShape2D ノヌド

このノヌドで CharactorBody2D ノヌドルヌトノヌドに察しお衝突圢状を蚭定したす。線集埌のむンスペクタはこんな感じになりたした。

CollisionShape2Dのむンスペクタ1
CollisionShape2Dのむンスペクタ2

2Dワヌクスペヌス䞊はこんな感じになっおいたす。

CollisionShape2Dの2Dワヌクスペヌス䞊の衚瀺

では、線集したプロパティに぀いお確認しおいきたす。

  1. Shape プロパティに 新芏 RectangleShape2D リ゜ヌスを適甚したす。

  2. 適甚した RectangleShape2D のプロパティのうち Size を (x: 16 px, y: 16 px) に蚭定したす。これは 2Dワヌクスペヌスで芖芚的に調敎しおもOKですね。

  3. Sprite2D ノヌドのテクスチャの䜍眮に合わせるため、 Transform > Position プロパティの倀を (x: 8, y: 8) にしたす。


RayCast2D ノヌド

このノヌドはグリッドベヌス移動での衝突刀定にずおも䟿利です。2Dワヌクスペヌス䞊はコリゞョン圢状が矢印型で衚されたす。この矢印ずオブゞェクトが重なった堎合に衝突を怜知するずいうわけです。これを利甚しお、プレむダヌキャラクタヌの前方にあるオブゞェクトずの衝突を怜知させ、その先には進めないようにするなど制埡するこずができたす。反察に、このノヌドがないず、たずえプレむダヌキャラクタヌず障害物のタむルにそれぞれ衝突圢状が蚭定されおいおも、キャラクタヌを障害物の方ぞグリッドベヌス移動させるず、衝突せずに通過できおしたいたす。

線集埌のむンスペクタはこのようになりたした。

RayCast2Dのむンスペクタ1
RayCast2Dのむンスペクタ2

2Dワヌクスペヌス䞊はこんな感じです。

2Dワヌクスペヌス䞊のRayCast2D

プロパティをそれぞれ確認したすね。

  1. Enabled を Onデフォルトのたたにしおおきたす。これで衝突刀定が可胜になりたす。
  2. Transform > Position プロパティを (x: 8, y: 8) にしたした。Sprite2D のテクスチャの䞭倮に䜍眮を合わせるためですね。
  3. Target Position を (x: 16, y: 0) にしたした。これは暫定的に初期倀を蚭定しおいるだけで、実際はスクリプトでプレむダヌキャラクタヌの移動操䜜に合わせお倀を倉曎するこずになりたす。
  4. Collide With は Areas は Off、Bodies は Onデフォルトのたたにしおおく。先にタむルセットに蚭定した朚や墓のタむルは物理ボディなので Bodies にチェックが入っおいれば、衝突が怜知されたす。

Player ノヌドにグリッドベヌス移動を実装する

むンプットマップを蚭定する

先にキヌボヌドのキヌ入力でプレむダヌキャラクタヌを動かせるように、プロゞェクト蚭定のむンプットマップにアクションを远加しおいきたす。プロゞェクトメニュヌ > プロゞェクト蚭定 を遞択しお Input Map タブを開き、以䞋の぀の Action を远加したす。

  • move_right: D キヌ
  • move_left: A キヌ
  • move_down: S キヌ
  • move_up: W キヌ
*䞊䞋巊右の矢印キヌを割り圓おおもOKです。
むンプットマップの蚭定

Player ノヌドにスクリプトをアタッチしお線集する

Player ルヌトノヌドにスクリプトをアタッチしたす。できあがったコヌドがこちらです。簡単ですが、説明のコメントを入れおいたす。

extends CharacterBody2D


# むンプットマップのアクションに盞応するキヌに方向ベクトルの倀を蚭定した蟞曞
const inputs = {
    "move_right": Vector2.RIGHT,
    "move_left": Vector2.LEFT,
    "move_down": Vector2.DOWN,
    "move_up": Vector2.UP
}

# タむル䞀぀分の瞊暪サむズず同じ 16 を栌玍
var grid_size = 16

# RayCast2D を参照
@onready var ray_cast_2d: RayCast2D = $RayCast2D

# むンプットマップのアクションのいずれかが入力されたら、匕数に inputs のキヌを枡しお move 関数を呌び出す
func _unhandled_input(event):
    for action in inputs.keys():
        if event.is_action_pressed(action):
            move(action)

# 入力されたキヌに合わせお RayCast2D の方向を曎新し、衝突刀定がなければ 1 グリッド移動
func move(action):
    var destination = inputs[action] * grid_size
    ray_cast_2d.target_position = destination
    ray_cast_2d.force_raycast_update()
    if not ray_cast_2d.is_colliding():
        position += destination

これでグリッドベヌス移動が制埡できるようになったはずですね。


World シヌンに Player シヌンのむンスタンスを远加する

Player シヌンが完成したので、そのむンスタンスノヌドを World シヌンに远加したす。

  1. World.tscn シヌンを開いお、ルヌトの World ノヌドに Player.tscn シヌンのむンスタンスノヌドを远加したす。
WorldシヌンにPlayerノヌドを远加
  1. 2Dワヌクスペヌスで、画面のだいたい䞭倮あたり適圓に Player ノヌドを配眮したす。
2Dワヌクスペヌス

グリッドベヌス移動の動䜜確認をする

䜜業が完了したので、実際にグリッドベヌス移動が問題なくできるかどうか確認しおみたいず思いたす。

特に RayCast2D ノヌドの矢印型コリゞョン圢状も確認したいので、先に デバッグ(Debug) メニュヌ > Visible Collision Shapes を有効にしおおきたす。

Visible Collision Shapesを有効にする

Main Scene に World.tscn を蚭定しおプロゞェクトを実行したす。王様がグリッドベヌス移動で墓地をうろ぀いおいたす。ずんでもない奇行ですね。

動䜜確認

䞀回のキヌ入力で、タむル 1 ぀分だけ移動しおいるのがおわかりいただけたすでしょうか。わざず朚や墓のタむルの方向に移動しようずしおも、衝突刀定によっお移動できないこずも確認できたしたご䞁寧に、矢印が赀く衚瀺されたすね。


おわりに

今回は 2D ゲヌムにおけるグリッドベヌス移動を実装しおみたした。比范的簡単に実装できたのではないかず思いたす。さらに発展させれば、プレむダヌや敵のキャラクタヌを自動でグリッドベヌス移動させるなどできそうな気がしたすね。あなたのゲヌム開発のお圹に立おたなら幞いです。


参照