プレイヤーの入力に対応する
前回のレッスンの 初めてのスクリプト作成 を踏まえて、どのゲームでも重要となるもうひとつの機能である、プレイヤーにコントロールを与えることについて見ていきましょう。これを追加するには、 sprite_2d.gd コードを修正する必要があります。
Godotでは、プレイヤーの入力を処理するために、主に2つのツールが用意されています。
組み込みの入力コールバック。主に
_unhandled_input()です。これは、_process()のように、プレーヤーがキーを押すたびに Godot が呼び出す組み込みの仮想関数です。例えば Space を押してジャンプするような、毎フレームで発生しないイベントに反応するために使用するツールです。入力コールバックについて詳しくは、 InputEvent (入力イベント) を参照してください。Inputシングルトン。シングルトンは、グローバルにアクセス可能なオブジェクトです。Godotはスクリプトでいくつかへのアクセスを提供しています。これは、毎フレーム入力があるかどうかを確認するのに適したツールです。
ここでは、Inputシングルトンを使用します。これは、プレイヤーがフレームごとに回転または移動したいかを知る必要があるからです。
回転させるために、新しい変数を使用する必要があります。これをdirectionとします。_process()関数の rotation += angular_speed * delta行を以下のコードに置き換えてください。
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
rotation += angular_speed * direction * delta
var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)delta;
ローカル変数directionは、プレイヤーが曲がりたい方向を表す乗数です。値が0なら、プレーヤーが左または右矢印キーを押していないことを意味します。値1なら、プレイヤーが右に曲がりたい、-1なら左に曲がりたいことを意味します。
To produce these values, we introduce conditional statements and the use of Input.
A conditional statement starts with the if keyword in GDScript and ends with a colon. The
condition is specifically the expression between the keyword and the colon at
the end of the line.
このフレームでキーが押されたかどうかを確認するために、Input.is_action_pressed()を呼び出します。このメソッドは入力アクションを表す文字列を受け取り、アクションが押された場合はtrueを、それ以外の場合はfalseを返すようになっています。
上記で使用した2つのアクション、"ui_left" と "ui_right" は、すべてのGodotプロジェクトであらかじめ定義されています。それぞれ、プレイヤーがキーボードの左矢印と右矢印、またはゲームパッドの十字キーの左と右を押したときに起動します。
注釈
You can see and edit input actions in your project by going to and clicking on the Input Map tab.
最後に、directionをノードのrotationの更新時の乗数として使用します。rotation += angular_speed * direction * deltaとします。
次のように、 var Velocity = Vector2.UP.rotated(rotation) * Speed と position += Velocity * delta の行をコメントアウトします。
#var velocity = Vector2.UP.rotated(rotation) * speed
#position += velocity * delta
//var velocity = Vector2.Up.Rotated(Rotation) * _speed;
//Position += velocity * (float)delta;
コメントアウトによって、前回の例題でユーザーの入力なしでアイコンを円運動させていたコードが実行されなくなります。
このコードでシーンを実行すると、 Left と Right を押したときにアイコンが回転します。
「上」ボタンを押すと動く
キーを押した時だけ動くようにするには、速度を計算するコードを修正する必要があります。コードのコメントを解除し、 var velocity で始まる行を以下のコードに置き換えます。
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
velocityをVector2.ZEROという値で初期化します。これはVector型の組み込み定数の一つで、長さ0の2次元ベクトルを表します。
プレイヤーが"ui_up"アクションを押すと、velocityの値が更新され、スプライトが前に移動するようになります。
完全なスクリプト
参考までに、sprite_2d.gdファイル全体は次のようになります。
extends Sprite2D
var speed = 400
var angular_speed = PI
func _process(delta):
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
rotation += angular_speed * direction * delta
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
using Godot;
public partial class MySprite2D : Sprite2D
{
private float _speed = 400;
private float _angularSpeed = Mathf.Pi;
public override void _Process(double delta)
{
var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)delta;
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
Position += velocity * (float)delta;
}
}
シーンを実行すると、左右の矢印キーで回転し、 Up を押して前進することができるはずです。
要約
要約すると、Godotのすべてのスクリプトはクラスを表し、エンジンの組み込みクラスの 1 つを拡張します。クラスが継承するノードタイプにより、スプライトの場合は rotation や position などのプロパティにアクセスできるようになります。また、この例では使用できなかった多くの関数も継承します。
GDScript では、ファイルの先頭に置いた変数は、クラスのプロパティで、メンバー変数とも呼ばれます。また、変数以外にも関数を定義することができますが、これはほとんどの場合、クラスのメソッドになります。
Godotは、クラスとエンジンを接続するために定義可能ないくつかの仮想関数を提供します。例えば、_process()はフレームごとにノードに変更を適用し、_unhandled_input()はユーザからキーやボタンを押すなどの入力イベントを受け取ります。他にもたくさんの仮装関数があります。
The Input singleton allows you to react to the player's input anywhere in
your code. In particular, you'll get to use it in the _process() loop.
次のレッスン シグナルの使用 では、スクリプトの中でノードにトリガーコードを持たせることで、スクリプトとノードの関係を構築します。