2020/10/25(日) [n年前の日記]
#1 [godot] Godot Engineでプレイヤーキャラ用のシーンを作成
Godot Engine は2D/3Dゲームが作れる、無料で利用できるゲームエンジン。作ったゲームは、Windows/Mac/Linux/Android上で動かせるらしい。HTML5で出力することもできるからWebブラウザ上でも動かせる。
_Godot Engine - Free and open source 2D and 3D game engine
_最初のゲーム - Godot Engine (stable)の日本語のドキュメント
Windows10 x64 2004 + Godot Engine 3.2.3 x64 で、2D表示の Apple Catcher タイプのゲームを ―― 上から林檎が落ちてくるので受け止めると点数が入る感じのゲームを作ってみようとしているのだけど。せっかく触っていることだし、操作手順を一通りメモしていこうかなと。
ひとまず今回は、プレイヤーキャラ相当を作成する手順をメモ。
_Godot Engine - Free and open source 2D and 3D game engine
_最初のゲーム - Godot Engine (stable)の日本語のドキュメント
Windows10 x64 2004 + Godot Engine 3.2.3 x64 で、2D表示の Apple Catcher タイプのゲームを ―― 上から林檎が落ちてくるので受け止めると点数が入る感じのゲームを作ってみようとしているのだけど。せっかく触っていることだし、操作手順を一通りメモしていこうかなと。
ひとまず今回は、プレイヤーキャラ相当を作成する手順をメモ。
◎ プロジェクトを新規作成。 :
まずはプロジェクトを新規作成。Godot Engine を起動するとプロジェクトマネージャーが開くので「新規プロジェクト」をクリック。
プロジェクト名と、プロジェクトの保存場所を指定。レンダラーは、OpenGL ES 3.0 と OpenGL ES 2.0 のどちらかを選べるけれど、Webブラウザ上でも動作するゲームを作ってみたいので、OpenGL ES 2.0 のほうを選ぶ。
プロジェクトが新規作成された。Godot のウインドウが開く。
プロジェクト名と、プロジェクトの保存場所を指定。レンダラーは、OpenGL ES 3.0 と OpenGL ES 2.0 のどちらかを選べるけれど、Webブラウザ上でも動作するゲームを作ってみたいので、OpenGL ES 2.0 のほうを選ぶ。
プロジェクトが新規作成された。Godot のウインドウが開く。
◎ プロジェクトのゲームウインドウサイズを設定。 :
プロジェクトのゲームウインドウサイズを設定しておく。
プロジェクト → プロジェクト設定、を選択。
Display の中の Window を選択して、Width と Height を指定。今回は 1280 x 720 のウインドウサイズを指定しておくことにした。数値を入力したら「閉じる」をクリックして設定を終える。
プロジェクト → プロジェクト設定、を選択。
Display の中の Window を選択して、Width と Height を指定。今回は 1280 x 720 のウインドウサイズを指定しておくことにした。数値を入力したら「閉じる」をクリックして設定を終える。
◎ テクスチャ画像をインポート。 :
プロジェクトに、テクスチャ画像をインポートする。
今回は、以下の画像を使うことにする。複数キャラが1枚の画像に収められている、スプライトシートと呼ばれる画像。1キャラは96x96ドット。
_newtototone_image_24bit.png
ところで、プロジェクトフォルダ直下に雑多なファイルを置くとファイル管理がごちゃごちゃしてしまうので、画像ファイルやサウンドファイルは resources というフォルダの中に入れておきたい。imports でも images でも名前は何でもいいけど。
プロジェクトフォルダ内でフォルダを新規作成する。ファイルシステムウインドウ内の「res://」を右クリック。「新規フォルダ」を選択。
新規フォルダ名を入力。「resources」と打ち込む。
res:// の下に、resources というフォルダが作成された。エクスプローラ等から使いたいテクスチャ画像を resources の上までドラッグアンドドロップ。これでresourcesフォルダの中にテクスチャ画像がコピーされて、Godot Engine が自動でインポート処理をしてくれる。
注意点。Godot Engine上で2Dゲームを作る場合はテクスチャ画像の Filter と Mipmaps を無効にしておきたい。そうしておかないと、表示した時に画像の境界がちょっとおかしな見た目になってしまうので…。
画像ファイルを選択してから、上のほうの「インポート」タブをクリック。デフォルトでは「Filter」にチェックが入っているので、クリックしてチェックを外す。ついでに、Mipmaps のチェックも外れてることを確認。チェックを外したら「再インポート」をクリック。
これで、Godot Engine のプロジェクトからテクスチャ画像を利用できる状態になった。
今回は、以下の画像を使うことにする。複数キャラが1枚の画像に収められている、スプライトシートと呼ばれる画像。1キャラは96x96ドット。
ところで、プロジェクトフォルダ直下に雑多なファイルを置くとファイル管理がごちゃごちゃしてしまうので、画像ファイルやサウンドファイルは resources というフォルダの中に入れておきたい。imports でも images でも名前は何でもいいけど。
プロジェクトフォルダ内でフォルダを新規作成する。ファイルシステムウインドウ内の「res://」を右クリック。「新規フォルダ」を選択。
新規フォルダ名を入力。「resources」と打ち込む。
res:// の下に、resources というフォルダが作成された。エクスプローラ等から使いたいテクスチャ画像を resources の上までドラッグアンドドロップ。これでresourcesフォルダの中にテクスチャ画像がコピーされて、Godot Engine が自動でインポート処理をしてくれる。
注意点。Godot Engine上で2Dゲームを作る場合はテクスチャ画像の Filter と Mipmaps を無効にしておきたい。そうしておかないと、表示した時に画像の境界がちょっとおかしな見た目になってしまうので…。
画像ファイルを選択してから、上のほうの「インポート」タブをクリック。デフォルトでは「Filter」にチェックが入っているので、クリックしてチェックを外す。ついでに、Mipmaps のチェックも外れてることを確認。チェックを外したら「再インポート」をクリック。
これで、Godot Engine のプロジェクトからテクスチャ画像を利用できる状態になった。
◎ プレイヤーキャラ相当のシーンを新規作成。 :
プレイヤーキャラ相当をゲームウインドウに表示したい。
プレイヤーキャラは、画像表示をするし、アタリ範囲も持つので、今回は Area2D というノードを作って処理する。
ちなみに、アタリ判定を必要とするノードは、Area2D、StaticBody2D、RigidBody2D、KinematicBody2D の4種類がある。詳しくは以下を参考に。
_物理の紹介 - Godot Engine (stable)の日本語のドキュメント
一番上位となる Area2Dノードをシーンに追加していく。「シーン」タブをクリックすると、ウインドウの左上のほうに「何のノードを追加するか?」的なノリで4つほどノードの選択肢が出ているので、「その他のノード」をクリック。
ノード新規作成ウインドウが開くので、「area2d」と打ち込んで絞り込み検索。リストアップされた中から「Area2D」を選んで「作成」をクリック。
Area2Dノードが一番上位のノード(ルートノード?)としてシーンに追加された。
ノードの名前を「Player」に変更しておく。右クリックして「名前の変更」。
「Player」を入力。これでノード名が「Player」になった。
ちなみに、ノードが選択されてる状態でノード名部分をクリックしても名前の変更はできる。
プレイヤーキャラは、画像表示をするし、アタリ範囲も持つので、今回は Area2D というノードを作って処理する。
Player (Area2D) │ ├─ Sprite (画像表示を担当するノード) │ └─ CollisionShape2D (アタリ範囲を担当するノード)
ちなみに、アタリ判定を必要とするノードは、Area2D、StaticBody2D、RigidBody2D、KinematicBody2D の4種類がある。詳しくは以下を参考に。
_物理の紹介 - Godot Engine (stable)の日本語のドキュメント
一番上位となる Area2Dノードをシーンに追加していく。「シーン」タブをクリックすると、ウインドウの左上のほうに「何のノードを追加するか?」的なノリで4つほどノードの選択肢が出ているので、「その他のノード」をクリック。
ノード新規作成ウインドウが開くので、「area2d」と打ち込んで絞り込み検索。リストアップされた中から「Area2D」を選んで「作成」をクリック。
Area2Dノードが一番上位のノード(ルートノード?)としてシーンに追加された。
ノードの名前を「Player」に変更しておく。右クリックして「名前の変更」。
「Player」を入力。これでノード名が「Player」になった。
ちなみに、ノードが選択されてる状態でノード名部分をクリックしても名前の変更はできる。
◎ プレイヤーノードに必要なノードを追加。 :
Playerノードに、画像表示をする Spriteノードと、アタリ範囲を指定する CollisionShape2Dノードを追加したい。
Playerノードを選択した状態で、左上のプラスマークをクリックしてノードを追加していく。
「sprite」と打って絞り込み検索。「Sprite」を選んで「作成」。
Spriteノードが追加された。
Playerノード(一番上のノード)を選択してから、またプラスアイコンをクリック。
CollisionShape2Dノードを選択して作成。
CollisionShape2Dノードが追加された。
Playerノードを選択した状態で、左上のプラスマークをクリックしてノードを追加していく。
「sprite」と打って絞り込み検索。「Sprite」を選んで「作成」。
Spriteノードが追加された。
Playerノード(一番上のノード)を選択してから、またプラスアイコンをクリック。
CollisionShape2Dノードを選択して作成。
CollisionShape2Dノードが追加された。
◎ Spriteにテクスチャ画像を指定。 :
画像表示を担当するSpriteノードにテクスチャ画像を指定する。
Spriteノードを選択。
ウインドウの右側に、Spriteノードのプロパティ一覧が表示されているので、ファイル一覧からテクスチャ画像を、「Texture」の欄までドラッグアンドドロップ。
画像が表示された。しかし、スプライトシート画像の全体が表示されてしまっている。この中の一部分だけを表示するように指定したい。
Spriteのプロパティの、Vframes、Hframes、Frameを変更して、スプライトシート内の1つだけを表示するように設定する。
Spriteノードを選択。
ウインドウの右側に、Spriteノードのプロパティ一覧が表示されているので、ファイル一覧からテクスチャ画像を、「Texture」の欄までドラッグアンドドロップ。
画像が表示された。しかし、スプライトシート画像の全体が表示されてしまっている。この中の一部分だけを表示するように指定したい。
Spriteのプロパティの、Vframes、Hframes、Frameを変更して、スプライトシート内の1つだけを表示するように設定する。
- Vframes : 縦に何個キャラが並んでるか。
- Hframes : 横に何個キャラが並んでるか。
- Frame : 何番目のキャラを表示するか。
◎ キャンバス操作について。 :
念のためにメモしておくけど…。
- キャンバスのスクロールは、マウスのホイールボタン(中ボタン)ドラッグ。
- キャンバスのズームは、マウスホイール回転。
- 等倍表示(100%表示)は、Ctrl + 0 キー。
◎ プレイヤーの基準点とアタリ範囲を設定。 :
今後のことを考えて、プレイヤーキャラの基準点を足元にしておきたい。Sprite と CollisionShape2D の位置をちょっとずらすことにする。
Spriteノードを選択。
Sprite の Transform → Position → y を、-48 に変更。Sprite の表示位置が変更されて、(0,0) がプレイヤーキャラの足元にあるような感じになった。
アタリ範囲も設定しておく。まずはアタリの形を指定しないといけない。CollisionShape2D を選択して、プロパティの Shape をクリック。設定できる種類がリストアップされるので、円の大きさでアタリ範囲を指定できる CircleShape2D を選ぶ。。
小さい赤丸をドラッグして、円の大きさを変更。
Transform → Position → y を -48 にする。
これで、足元を基準点にしつつ、アタリ範囲も設定できた。
Spriteノードを選択。
Sprite の Transform → Position → y を、-48 に変更。Sprite の表示位置が変更されて、(0,0) がプレイヤーキャラの足元にあるような感じになった。
アタリ範囲も設定しておく。まずはアタリの形を指定しないといけない。CollisionShape2D を選択して、プロパティの Shape をクリック。設定できる種類がリストアップされるので、円の大きさでアタリ範囲を指定できる CircleShape2D を選ぶ。。
小さい赤丸をドラッグして、円の大きさを変更。
Transform → Position → y を -48 にする。
これで、足元を基準点にしつつ、アタリ範囲も設定できた。
◎ 子ノードの位置をうっかり変えないように指定。 :
作業中に、せっかく設定した子ノードの位置をうっかり変えてしまわないようにしたい。
Playerノードを選択して、ツールバー上の「オブジェクトの子を選択不可にする」をクリック。これで、子ノードの位置を間違って変えてしまう状態を防げる。
Playerノードを選択して、ツールバー上の「オブジェクトの子を選択不可にする」をクリック。これで、子ノードの位置を間違って変えてしまう状態を防げる。
◎ プレイヤーの表示位置を変更。 :
プレイヤーキャラの表示位置を、ウインドウの下のあたりに変更しておきたい。
Playerノードを選択して、Transform → Position → x,y に、640, 672 を指定。これで、ウインドウの下のあたりにプレイヤーキャラが表示される状態になった。
Playerノードを選択して、Transform → Position → x,y に、640, 672 を指定。これで、ウインドウの下のあたりにプレイヤーキャラが表示される状態になった。
◎ プレイヤーのシーンを保存。 :
プレイヤーのシーンを保存する。シーン → 名前を付けてシーンを保存。
プロジェクト内に「assets」というフォルダを新規作成して、各シーンはその中に入れていくことにする。「フォルダを作成」をクリック。
「assets」と入力。
Player.tscn として保存。
assetsフォルダの中に、Player.tscn が保存された。
プロジェクト内に「assets」というフォルダを新規作成して、各シーンはその中に入れていくことにする。「フォルダを作成」をクリック。
「assets」と入力。
Player.tscn として保存。
assetsフォルダの中に、Player.tscn が保存された。
◎ ゲームウインドウを表示して確認。 :
[ ツッコむ ]
#2 [godot] Godot Engineでプレイヤーシーンにスクリプトを追加
Godot Engine 3.2.3 x64でプレイヤーキャラを表示するところまではできたので、この後、キー入力で左右に動かしたり、アニメーションをつけたりしたい。手順をメモ。
◎ プレイヤーキャラをキー入力で動かす。 :
プレイヤーキャラをキー入力で左右に動かしたいのだけど、そのためには若干のスクリプトを書かないといけない。
まずはスクリプトファイルを作成する。Playerノードを選択して、ちょっと右上のほうにある、スクリプトをアタッチするボタンをクリック。
ノードにスクリプトをアタッチするウインドウが開くけれど、今後のことも考えて、スクリプトファイルは「scripts」というフォルダの中にまとめて入れておきたい。「パス」の右端のパス参照ボタンをクリック。
scriptsフォルダを新規作成。
scriptsフォルダ内で、Player.gd というファイル名を指定。デフォルトでは「(ノード名).gd」がファイル名の入力欄に入っているので、今回ファイル名は打ち込み直さなくていいはず。
「作成」をクリック。これでスクリプトファイルが作成・保存される。
Playerノードにスクリプトが割り当てられた。ノード名の横にファイルっぽいアイコンが表示されて、スクリプトが割り当てられていることを示している。また、スクリプトを記述するためのエディタ画面も表示された。
スクリプトを書く。
スクリプトの内容は以下。
_Player.gd
このスクリプトがやってることは…。
Ctrl + S キーを押してスクリプトを上書き保存してから、F6キーを押して実行してみる。カーソルキーの左右を押すと、プレイヤーキャラが左右に動いてくれた。
少し補足。スクリプト中で、$Sprite.flip_h を弄ってるけど、これは Sprite の左右反転表示フラグ。右キーを押したら向かって右向きに、左キーを押したら向かって左向きになるように指定している。
まずはスクリプトファイルを作成する。Playerノードを選択して、ちょっと右上のほうにある、スクリプトをアタッチするボタンをクリック。
ノードにスクリプトをアタッチするウインドウが開くけれど、今後のことも考えて、スクリプトファイルは「scripts」というフォルダの中にまとめて入れておきたい。「パス」の右端のパス参照ボタンをクリック。
scriptsフォルダを新規作成。
scriptsフォルダ内で、Player.gd というファイル名を指定。デフォルトでは「(ノード名).gd」がファイル名の入力欄に入っているので、今回ファイル名は打ち込み直さなくていいはず。
「作成」をクリック。これでスクリプトファイルが作成・保存される。
Playerノードにスクリプトが割り当てられた。ノード名の横にファイルっぽいアイコンが表示されて、スクリプトが割り当てられていることを示している。また、スクリプトを記述するためのエディタ画面も表示された。
スクリプトを書く。
スクリプトの内容は以下。
_Player.gd
extends Area2D export var speed = 600 export var w = 96 var screen_size func _ready(): screen_size = get_viewport_rect().size func _process(delta): var velocity = Vector2() if Input.is_action_pressed("ui_right"): velocity.x += 1 $Sprite.flip_h = true if Input.is_action_pressed("ui_left"): velocity.x -= 1 $Sprite.flip_h = false if velocity.length() > 0: velocity = velocity.normalized() * speed position += velocity * delta position.x = clamp(position.x, w/2, screen_size.x - (w/2))
このスクリプトがやってることは…。
- 「var 変数名」で変数を用意できる。
- 「export var 変数名」で、GUIから値を変更できる変数を用意できる。
- 変数として、以下の3つを ―― 速度の大きさを指定する speed、画像の横幅を示す w、ゲームウインドウサイズを覚えておく screen_size を用意する。
- ノードが発生すると、_ready() が呼ばれるので、そこに初期化処理を書く。ここでは、ビューポート(ゲームウインドウ?)の大きさを取得してる。screen_size.x に画面横幅が、screen_size.y に画面縦幅が入る。
- _process(delta) は、一定の時間間隔で呼ばれる処理を書く。
- delta は、_process(delta) が前回呼ばれてから今回呼ばれるまでの時間(単位は秒?)が入っている。例えば、もし60FPSで動いているなら、1秒 / 60 = 0.0166前後の値が入ってくるはず。
- キー入力で速度を決定。座標(Position)に速度を加算して変更。
- clamp() を使って、キャラのx座標が画面の左端と右端を超えないように補正。
Ctrl + S キーを押してスクリプトを上書き保存してから、F6キーを押して実行してみる。カーソルキーの左右を押すと、プレイヤーキャラが左右に動いてくれた。
少し補足。スクリプト中で、$Sprite.flip_h を弄ってるけど、これは Sprite の左右反転表示フラグ。右キーを押したら向かって右向きに、左キーを押したら向かって左向きになるように指定している。
◎ プレイヤーにアニメーションをつける。 :
プレイヤーキャラに、2枚の画像をパタパタと切り替えるだけの簡単なアニメーションをつけたい。
Godot Engine は、各ノードに AnimationPlayer というノードを追加するとアニメをつけることができる。
Playerノードを選択して、ノードを追加。「anima」まで打って絞り込み検索。「AnimationPlayer」を選択して「作成」。
AnimationPlayerノードが追加された。AnimationPlayer ノードを選択すると、画面の下のほうにアニメーション設定用のウインドウが表示される。「アニメーション」をクリック。
アニメの種類を新規作成する。「新規」をクリック。
待ちアニメーションとして、「idle」というアニメ種類を作る。「idle」と打って「OK」。
「idle」用のアニメーショントラックを追加していける状態になった。
今回は、Spriteノードで表示している Frame を変化させることでパタパタアニメを作りたい。Spriteノードを選択して、Frame値を2にする。その右側にある鍵っぽいボタンをクリックすることで、アニメーション用のトラックにその値を登録する。
「トラックを作っていいか?」と尋ねてくるので「作成」。
0秒目のところに、Sprite の Frame値が登録された。
0.5秒目のあたりをマウスクリックして指定する。時間軸の横幅が狭過ぎて指定しづらい場合は、右下のスライドバー(?)で時間軸の幅を変更できる。
Sprite の Frame値を3に変更して、右側の鍵ボタンをクリック。これで、0.5秒目のところにも、Sprite の frame値を登録できた。
アニメをループ再生したいので、右端のほうにあるループ再生アイコンをクリックして設定。また、このノードが発生した時から idleアニメを再生したいので、少し上のほうにある自動再生?アイコンもクリックして設定。
再生ボタンっぽいボタンをクリックすると、アニメを再生して確認することができる。
これで、Frame値が 2 → 3 → 2 → 3…と変わり続けるアニメ種類を作ることができた。
同じ要領で、歩いてる時のアニメ種類、「walk」を新規作成する。
更に同じ要領で、プレイヤーがダメージを受けた時のアニメ種類、「dead」を新規作成する。
アニメの種類を用意できたので、スクリプトからアニメを再生するように指定していく。
Playerノードの横にあるスクリプトファイルアイコンをクリックして、スクリプトの編集画面を開く。
スクリプトの内容は以下。
_Player.gd
前回のスクリプトに対して以下の変更をした。
F6キーを押して実行。
これで、プレイヤーキャラがアニメをしながら動くようになった。
Godot Engine は、各ノードに AnimationPlayer というノードを追加するとアニメをつけることができる。
Playerノードを選択して、ノードを追加。「anima」まで打って絞り込み検索。「AnimationPlayer」を選択して「作成」。
AnimationPlayerノードが追加された。AnimationPlayer ノードを選択すると、画面の下のほうにアニメーション設定用のウインドウが表示される。「アニメーション」をクリック。
アニメの種類を新規作成する。「新規」をクリック。
待ちアニメーションとして、「idle」というアニメ種類を作る。「idle」と打って「OK」。
「idle」用のアニメーショントラックを追加していける状態になった。
今回は、Spriteノードで表示している Frame を変化させることでパタパタアニメを作りたい。Spriteノードを選択して、Frame値を2にする。その右側にある鍵っぽいボタンをクリックすることで、アニメーション用のトラックにその値を登録する。
「トラックを作っていいか?」と尋ねてくるので「作成」。
0秒目のところに、Sprite の Frame値が登録された。
0.5秒目のあたりをマウスクリックして指定する。時間軸の横幅が狭過ぎて指定しづらい場合は、右下のスライドバー(?)で時間軸の幅を変更できる。
Sprite の Frame値を3に変更して、右側の鍵ボタンをクリック。これで、0.5秒目のところにも、Sprite の frame値を登録できた。
アニメをループ再生したいので、右端のほうにあるループ再生アイコンをクリックして設定。また、このノードが発生した時から idleアニメを再生したいので、少し上のほうにある自動再生?アイコンもクリックして設定。
再生ボタンっぽいボタンをクリックすると、アニメを再生して確認することができる。
これで、Frame値が 2 → 3 → 2 → 3…と変わり続けるアニメ種類を作ることができた。
同じ要領で、歩いてる時のアニメ種類、「walk」を新規作成する。
- Frame値は 6 と 7 で切り替わるように指定。
- 「idle」は再生時間が1秒だったけど、「walk」は再生時間を 0.2秒にしたいので、再生時間の入力欄を、1 から 0.2 に変更。
- ループ再生も有効にしておく。
更に同じ要領で、プレイヤーがダメージを受けた時のアニメ種類、「dead」を新規作成する。
- 再生時間は 0.4秒。
- Sprite の Frame値は4のみの1種類。
- Sprite の Flip H を変更して、左→右→左→右、とアニメさせる。
アニメの種類を用意できたので、スクリプトからアニメを再生するように指定していく。
Playerノードの横にあるスクリプトファイルアイコンをクリックして、スクリプトの編集画面を開く。
スクリプトの内容は以下。
_Player.gd
extends Area2D export var speed = 600 export var w = 96 var screen_size func _ready(): screen_size = get_viewport_rect().size $AnimationPlayer.play("idle") func _process(delta): var velocity = Vector2() if Input.is_action_pressed("ui_right"): velocity.x += 1 $Sprite.flip_h = true if Input.is_action_pressed("ui_left"): velocity.x -= 1 $Sprite.flip_h = false if velocity.length() > 0: velocity = velocity.normalized() * speed $AnimationPlayer.play("walk") else: $AnimationPlayer.play("idle") position += velocity * delta position.x = clamp(position.x, w/2, screen_size.x - (w/2))
前回のスクリプトに対して以下の変更をした。
- _ready() の中に、$AnimationPlayer.play("idle") を追加。
- 速度がある時は、$AnimationPlayer.play("walk") を呼ぶ。
- 速度が0の時は、$AnimationPlayer.play("idle") を呼ぶ。
F6キーを押して実行。
これで、プレイヤーキャラがアニメをしながら動くようになった。
[ ツッコむ ]
以上、1 日分です。