とりとめも

藻類が学んだり感じたりしたことを未来の自分のために書き留めるところ

【Godotお勉強メモ】2Dチュートリアルその後 タイルマップで見下ろし型の画面を作ったり壁を作ったり

はじめに

前回までに続いて作業のメモです。

前回

marimomemo.hatenablog.jp

今回は

Godotの2Dチュートリアルを終え、手探りで色々な機能を調べています。
今回はマップの作り方です。

チュートリアルでは「キャラクターの移動範囲=ウィンドウ内」という仕様だったため、マップ(明示的な移動可能範囲)は作成しませんでした。
そこで今回は、タイルマップを使って下図のような見下ろし型の画面を作りました。

今回つくる画面

白い部分が移動可能な床です。黒い部分は壁でキャラクターと衝突します。
青い四角がプレイヤーキャラクターの代わりです。

また、ついでに今回はCharacterBody2Dノードを使ってキャラクターを作ることにしました。
チュートリアルではArea2Dでしたが、CharacterBody2Dのほうがキャラクターのノードとしては一般的っぽいです。

やることまとめ

  • マップを作る
    • タイルマップノードを使う
    • タイルセットリソースについて知る
    • 壁(黒いタイル)と床(白いタイル)をつかってマップを作る
  • キャラクターを作る
    • CharacterBody2Dノードを使う

マップを作る

タイルセット用画像の準備

本当はスプライトシートというものを使うそうですが、今回は黒と白のタイルで構成された画像をもとにタイルセットを作ります。
タイル1枚あたり32x32で白黒2枚。よって64x32の画像ファイルを1枚用意しました。

雑タイル

タイルセットリソースを作る

マップの作成には「タイルマップ」というノードを使いますが、タイルマップには、「タイルセット」というリソースが必要みたいです。

なので、ファイルシステムの「新規リソース」からTileSetリソースを作成します。

TileSetリソースを作る

作ったリソースは「tile_set_test.tres」という名前にしておきます。

リソースという概念もチュートリアルでは触れないので混乱しました。
ノードもリソースも実体はファイルですが、以下の差異があると理解しています。

  • ノード:シーンツリーを構成する
  • リソース:シーンツリーを構成しない。ノードに読み込んで使う。

タイルセットを設定する

ともあれ作成したタイルセットに、先ほどの画像を読み込みます。

下部のエディタに投げ込めばOK

ただし、デフォルトだとタイルが正しく分割されません。
今回は1枚あたり32x32なので、Texture Regionも32x32に設定します(上の画像では設定済)
これで黒と白のタイルに分かれました。

次に黒のタイルにコリジョンを設定します。

TileSetのインスペクターでPhysics Layersから要素を追加します。
いい感じにLayerとMaskを設定します。

今回はどっちも1

黒のタイルにだけコリジョンを適用します。
下部のTIleSetエディタで選択タブを選び、黒のタイルを選択。
物理を開き、+マークのボタンを使って全体を覆います。

真っ赤になった

このあたりはチュートリアルでやった作業と同様ですね。

タイルマップノードを作る

シーンの追加から、TileMapノードを追加します。
インスペクターのTileSetからタイルセットを追加します。読み込み > 先ほど作ったタイルセットリソース

TileMapのインスペクターなので注意

タイルマップエディタにタイルが表示されます。
下部のエディタにはTileSetとTileMapという2つの画面があるので注意。

TileSetエディタで各タイルを有効にして、TileMapエディタからタイルを選択すると、マップ上にタイルを配置できます。

とりあえず配置しました。

ペタペタ

プレイヤーキャラクターを作る

画像の準備

キャラクターの代わりに32x32の単色画像を使います。キャラは青にします。

目を凝らせばキャラクターに見えます

重力を無効にする

今回使うCharacterBody2Dノードでは、自動的に重力が働きます。
しかし、今回は見下ろし型の画面なので重力は不要です。

よって重力は0にします。
プロジェクト > プロジェクト設定 > 「一般」タブ > 物理 > 2D > Default Gravityを0にする

無重力

キャラクター用のシーンを作る。

続けてキャラクターのシーンを準備します。
新しいシーンから、CharacterBody2Dノードを作ります。チュートリアル同様にPlayerという名前にします。
また、子ノードとしてSprite2DノードとCollisionShape2Dノードを追加します。

結果、ツリーはこんな感じ。

チュートリアルのPlayerとほぼ同じ()

キャラクターの設定

Sprite2Dの設定

Sprite2DのインスペクターからTextureを選び、先ほどの青い画像を読み込みます。

CollisionShape2Dの設定

CollisionShape2Dのインスペクターを開いて以下の設定をします。

  • ShapeでRectangleShape2Dを選択
  • TransformのScaleを変更して、Sprite2Dで読み込んだ画像と同じサイズになるようにする

Playerのスクリプトを書く

Playerを右クリック > スクリプトをアタッチ
デフォルトで結構いろいろ書かれてます。ただ、重力関係の処理だったり、今回は不要なものも多そうです。

いろいろ書かれてる

今回は以下のように書き替えました。

extends CharacterBody2D

const SPEED = 300.0

func _physics_process(delta):

    velocity = Vector2(
        Input.get_axis("move_left", "move_right"),
        Input.get_axis("move_up", "move_down")
    )
    velocity = velocity.normalized() * SPEED

    move_and_slide()

重力関連の処理を削除し、上下への移動も可能な形に変更しました。
チュートリアルで使ったis_action_pressedでキーを判別するやり方よりも、get_axisのほうがキャラクターの移動処理には適していそうです。
まだ仕様がいまいち頭に入っていないですが。

また、Area2Dノードでは計算したvelocityに基づいてpositionを書き換えて移動を実現しました。
CharacterBody2Dでは、velocityを変更してmove_and_slide()を実行すると、そのときのvelocityに基づいて移動してくれるみたいです。
さらにその際deltaに関する補正計算は自動的にやってくれる便利仕様。かしこい。

Mainシーンを作る

2つのシーンをぶら下げます。

できた

これで準備完了です。

以上でできました。確かに壁にもぶつかれます。

ぶつかれる(伝わらない)

まとめと今後

そんなわけで、ようやくマップを作って、そのうえでキャラクター(青い四角形ですが)を動かすことができるようになりました。
今後はここからもっとゲームっぽい機能を付け加えていきたいです。

また、マップの作成に関しても、タイルマップでポチポチ作るのではなくスクリプトで作ることはできないかなと考えています。
最終的には、ローグライクの自動生成ダンジョンみたいな形を目指したい気持ち。
ただ、そもそもタイルマップ自体まだ触っていない機能が山ほどあるので、そのあたりも触って慣れていかないといけないですね。

初めからいろいろやろうとせず、少しずつ進めていきましょう。

おわり。

参考

docs.godotengine.org

docs.godotengine.org

2dgames.jp