初めてのスクリプト作成¶
このレッスンでは、GDScript を使ってGodotアイコンを回転させるスクリプトをコーディングします。 in the introduction で触れたように、プログラミングの基礎知識があることを前提にしています。同等の C# コードは、便宜上、別のタブに含まれています。
参考
GDScript、そのキーワード、およびその構文の詳細については、 GDScript reference にアクセスしてください。
参考
C#の詳細については、C# basics を参照してください。
プロジェクトの設定¶
では 新規project を作成して下さい、白紙の状態から始めます。プロジェクトには1つの画像ファイルが含まれている必要があります。今回はコミュニティでのプロトタイピングによく使用されるGodotアイコンを使います。
ゲームに表示するには、Spriteノード を作成する必要があります。シーンドックで、[Other Node] ボタンをクリックします。
検索バーに「Sprite」と入力してノードをフィルタリングし、Spriteをダブルクリックしてノードを作成します。
これで、[シーン]タブにスプライトノードのみが追加されました。
スプライトノードを表示するにはテクスチャが必要です。右側のインスペクターで、Textureプロパティが「[空]」と表示されていることがわかります。 Godotアイコンを表示するには、ファイル icon.png
をFileSystemドックからTextureスロットにドラッグアンドドロップします。
注釈
また ビューポートに画像をドラッグアンドドロップすることで、スプライトノードを自動的に作成することもできます。
次に、ビューポートの Godotアイコン をドラッグし、ゲームビューの中央に配置します。
新規スクリプトの作成¶
新しいスクリプトを作成してノードにアタッチするには、シーンドックでスプライトを右クリックし、[スクリプトをアタッチ]を選択します。
「ノードにスクリプトをアタッチする」("Attach node Script")ウィンドウが表示されます。このウィンドウでは、スクリプトの言語やファイルパスなどのオプションを選択できます。
テンプレートを デフォルト から Empty に変更して、クリーンなファイルから始めます。デフォルトで他のオプションを変更せず、[作成]ボタンをクリックしてスクリプトを作成します。
スクリプトワークスペースに新しいSprite.gd
ファイルが開いて下記のコードが表示されます。
extends Sprite
public class Sprite : Godot.Sprite
// Declare member variables here. Examples:
// private int a = 2;
// private string b = "text";
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
}
// // Called every frame. 'delta' is the elapsed time since the previous frame.
// public override void _Process(float delta)
// {
//
// }
すべてのGDScriptファイルは暗黙的なクラスです。 extends
キーワードは、このスクリプトが継承または拡張クラスであることを定義します。この場合 スクリプトの Sprite
クラスは、 Node2D
、 CanvasItem
、 Node
など、拡張クラスを含む、Spriteノードのすべてのプロパティと関数にアクセスできます。
注釈
GDScriptでは、 extends
キーワードの行を省略した場合 Reference 、 Godotがアプリケーションのメモリを管理するために クラスは暗黙的に拡張されます。
継承されたプロパティには、ノードの texture
のように、インスペクタードックに表示されるプロパティも含まれます。
注釈
デフォルトでは、インスペクタータブ内ではノードのプロパティを「Title Case」(タイトルケース)で表示し、大文字の単語をスペースで区切ります。 GDScriptコード内では、これらのプロパティは「snake_case」(スネークケース)およびアンダースコアで区切られた小文字で表記します。
インスペクター内で任意のプロパティの名前にカーソルを合わせると、その説明とコード内での識別子が表示されます。
ハロー、ワールド!¶
現在、スクリプトは何もしません。 手始めに「Hello、world!」というテキストを下部[出力]パネルに表示させましょう。
スクリプトに次のコードを追加します。
func _init():
print("Hello, world!")
public Sprite()
{
GD.Print("Hello, world!");
}
こまかく見てみましょう。 func
キーワードは、 _init
という名前の新しい関数を定義します。これは、クラスのコンストラクターの特別な名前です。この関数を定義すると、エンジンがメモリ内にオブジェクトまたはノードを作成すると _init()
が初期化のため呼ばれます。
注釈
GDScriptはインデントベースの言語です。コードが機能するには、 print()
という行の先頭にあるタブが必要です。これを省略したり、行を正しくインデントしなかったりすると、エディターはそれを赤で強調表示し、"Unexpected indentation(予期しないインデント)" というエラーメッセージを表示します。
シーンをまだ保存していない場合は保存し、 F6 を(macOSでは Cmd + R )押して実行します。展開された下部の ** [Output]** パネルを確認します。 "Hello, world!"と表示されているはずです。
次に _init()
関数を削除して、 extends Sprite
という行だけを残します。
回転させるには¶
スプライトノードを移動および回転させるときが来ました。そのために、スクリプトに2つのメンバー変数を追加します。1秒あたりのピクセル数で表した移動速度と1秒あたりのラジアンで表した角速度です。
var speed = 400
var angular_speed = PI
private int Speed = 400;
private float AngularSpeed = Mathf.Pi;
メンバー変数は、スクリプトの先頭付近、"extends" 行の後、関数の前に置かれます。このスクリプトがアタッチされているすべてのノードインスタンスは、 speed
(速度)プロパティと angular_speed
(角速度)プロパティの独自のコピーを持つことになります。
注釈
Godotの角度はデフォルトではラジアン単位で計算されますが、度単位で角度を計算したい場合に使える組み込み関数やプロパティも用意されています。
アイコンを移動するには、ゲームループ内のフレームごとにアイコンの位置と回転を更新する必要があります。 Node
クラスの _process()
仮想関数を使用できます。 SpriteなどのNodeクラスの拡張クラスで定義すると、Godotはフレームごとに関数を呼び出し、最後のフレームからの経過時間である delta
という名前の引数を渡します。
注釈
ゲームは、1秒あたりに数多くの画像をレンダリングすることで機能します。各画像はフレームと呼ばれ、ループしてレンダリングされます。ゲームが画像を生成する速度をフレーム/秒(FPS)で測定します。ほとんどのゲームは60FPSを目指していますが、低速のモバイルデバイスでは30 FPS、バーチャルリアリティゲームでは90〜240のような数値が見られる場合があります。
エンジンとゲームの開発者は、一定の時間でゲームの世界を更新しレンダリングするために最善を尽くしますが、フレームのレンダリング時間には常に小さな変動があります。これはエンジンがフレームレートに依存しないモーションを作成するため提供するデルタタイムです。
スクリプトの最後に、関数を定義します。
func _process(delta):
rotation += angular_speed * delta
public override void _Process(float delta)
{
Rotation += AngularSpeed * delta;
}
func
キーワードは新しい関数を定義します。その後、関数名と引数を括弧で囲んで記述する必要があります。コロンで定義を終了し、それに続くインデントされたブロックが関数のコンテンツまたは命令になります。
注釈
_init()
や _process()
のように関数の先頭がアンダースコアで始まることに注意してください。慣例により、Godotの仮想関数、つまり、エンジンとやりとりするため オーバーライドされる組み込み関数は、アンダースコアから始まります。
関数内の行 rotation += angular_speed * delta
は、フレームごとにスプライトの回転角をインクリメントします。ここで、 rotation
は、 Sprite
が拡張する Node2D
クラスから継承されたプロパティです。ノードの回転を制御し、ラジアンで指定します。
ちなみに
コードエディタで、「position」、「rotation」、「_ process」などの組み込みプロパティまたは関数をCtrlキーを押しながらクリックすると対応する説明文が新しいタブで開きます。
シーンを実行して、Godotアイコンが指定した位置で回転することを確認します。
前進させるには¶
ノードを動かしてみましょう。次の2行を _process()
関数に追加し、前の行にそろえインデントします。
var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
var velocity = Vector2.Up.Rotated(Rotation) * Speed;
Position += velocity * delta;
すでに見たように、 var
キーワードは新しい変数を定義します。スクリプトの先頭に配置すると、クラスのプロパティとして定義されます。関数内で定義されたものはローカル変数となり、関数のスコープ内でのみ参照されます。
velocity
という名前のローカル変数を定義します、方向と速度の両方を表す2Dベクトルです。ノードを前進させるには、Vector2クラスの定数 Vector2.UP(上向きのベクトル)を用います、回転は Vector2.rotated()
メソッドを呼び出して実行します。この式 Vector2.UP.rotated(rotation)
は、アイコンに対して前方を指すベクトルです。 speed
プロパティを掛けることで、ノードを前方に移動するための速度が得られます。
ノードのposition
に velocity * delta
を追加して移動しています。このposition自体は Vector2 というタイプで、2次元ベクトルを表すGodotの組み込み型です。
シーンを実行してGodotの頭がぐるぐる回るのを確認してください。
注釈
このようなノードの移動では、壁や床との衝突は考慮されません。 ref:doc_your_first_2d_game では、衝突を検出しながらオブジェクトを移動させる別のアプローチを学びます。
このノードは現在、ノード自身で移動します。次のパート プレイヤーの入力を聞く では、プレイヤーの入力を使ってノードをコントロールします。
完全なスクリプト¶
参考までに、Sprite.gd
ファイル全体は次のようになります。
extends Sprite
var speed = 400
var angular_speed = PI
func _process(delta):
rotation += angular_speed * delta
var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
using Godot;
public class Sprite : Godot.Sprite
{
private int Speed = 400;
private float AngularSpeed = Mathf.Pi;
public override void _Process(float delta)
{
Rotation += AngularSpeed * delta;
var velocity = Vector2.Up.Rotated(Rotation) * Speed;
Position += velocity * delta;
}
}