Up to date
This page is up to date for Godot 4.2
.
If you still find outdated information, please open an issue.
メインシーン¶
今まで作成したすべてをまとめ、遊べるゲームにするときが来ました。
新しいシーンを作成し、 Main
という名前の Node を追加します。 (Node2D ではなく、Nodeを使用する理由は、これはゲームロジックを扱うノードであり、これ自体に2D機能が不要であるためです。)
インスタンス ボタン(チェーンリンクアイコン)をクリックし、保存した player.tscn
を選択してください。
次に Main
の子供として以下のノードを追加します(値は秒単位です)。
Timer(
MobTimer
という名前) - モブが出現する頻度を制御するTimer (
ScoreTimer
という名前) - 一秒ごとに得点を上げるTimer (
StartTimer
という名前) - 開始する前に遅延させるMarker2D (
StartPosition
という名前) - プレイヤーの開始位置を示す
各 Timer
ノードの Wait Time
プロパティを次のように設定します:
MobTimer
:0.5
ScoreTimer
:1
StartTimer
:2
さらに、 StartTimer
の One Shot
プロパティを「On」に設定し、 StartPosition
ノードの Position
を (240, 450)
に設定します。
モブの生成¶
メインノードは新しいモブを生成し、画面の端のランダムな場所に表示するようにします。 Main
の子として MobPath
という名前のPath2Dノードを追加します。 Path2D
を選択すると、エディタの上部にいくつかの新しいボタンが表示されます:
中央のアイコン([点を空きスペースに追加])を選択し、表示されているコーナーをクリックしてポイントを追加してパスを描画します。ポイントをグリッドにスナップするには、[グリッドスナップを使う]が選択されていることを確認します。このオプションは、[選択Nodeをロック]ボタンの左側にあり、「交差する線と磁石」のアイコンで表示されています。
重要
時計回りにパスを描画します。そうしないと、モブは内側ではなく外側を向いて発生します!
画像にポイント 4
を配置した後、「カーブを閉じる」ボタンをクリックすると、カーブが完成します。
パスが定義されたので、 MobPath
の子としてPathFollow2Dノードを追加し、 MobSpawnLocation
という名前を付けます。このノードは自動的に回転し、パスの移動に従うので、パスに沿ってランダムな位置と方向を選択できます。
シーンは次のようになります:
Mainスクリプト¶
スクリプトを Main
に追加します。 スクリプトの上部に @export var mob_scene: PackedScene
を追加して、インスタンス化するMobシーンを選択できるようにします。
extends Node
@export var mob_scene: PackedScene
var score
using Godot;
public partial class Main : Node
{
// Don't forget to rebuild the project so the editor knows about the new export variable.
[Export]
public PackedScene MobScene { get; set; }
private int _score;
}
Main
ノードをクリックすると、インスペクタの「Script Variables(スクリプト変数)」の下にMob Scene
プロパティがあります。
このプロパティの値は、ふたつの方法で指定できます:
「ファイルシステム」パネルから
mob.tscn
をドラッグし、 Mob Scene プロパティにドロップします。<空> の隣にある下矢印をクリックして「読み込み」を選び、
mob.tscn
を選択します。
次に、シーンドックの Player
ノードを選択し、サイドバーのノードドックにアクセスします。ノードドックでは、シグナルタブが選択されていることを確認してください。
Player
ノードのシグナルのリストが表示されます。リストの中から hit
のシグナルを見つけてダブルクリックしてください (または、右クリックして "接続..." を選択)。これでシグナルの接続ダイアログが開きます。ゲームが終了したときに必要な処理を行う game_over
という名前の新しい関数をこれから作ります。シグナル接続ダイアログの下部にある「受信側メソッド」ボックスに「game_over」と入力し、「接続」をクリックしてください。 Player
から hit
シグナルが発火されたとき、 Main
スクリプト側で処理できるようになります。新しい関数に以下のコードを追加し、新しいゲームのセットアップを行う new_game
関数も追加します:
func game_over():
$ScoreTimer.stop()
$MobTimer.stop()
func new_game():
score = 0
$Player.start($StartPosition.position)
$StartTimer.start()
public void GameOver()
{
GetNode<Timer>("MobTimer").Stop();
GetNode<Timer>("ScoreTimer").Stop();
}
public void NewGame()
{
_score = 0;
var player = GetNode<Player>("Player");
var startPosition = GetNode<Marker2D>("StartPosition");
player.Start(startPosition.Position);
GetNode<Timer>("StartTimer").Start();
}
次に、各Timerノード (StartTimer
、 ScoreTimer
、 MobTimer
) の timeout()
シグナルをMainスクリプトに接続します。 StartTimer
は他の2つのタイマーを開始します。 ScoreTimer
はスコアを1増やします。
func _on_score_timer_timeout():
score += 1
func _on_start_timer_timeout():
$MobTimer.start()
$ScoreTimer.start()
private void OnScoreTimerTimeout()
{
_score++;
}
private void OnStartTimerTimeout()
{
GetNode<Timer>("MobTimer").Start();
GetNode<Timer>("ScoreTimer").Start();
}
_on_mob_timer_timeout()
では、モブのインスタンスを作成し、 Path2D
に沿ってランダムに開始位置を選び、モブを動かすようにします。PathFollow2D
ノードはパスに沿って自動的に回転するので、これを使ってモブの方向と位置を選択します。移動速度は 150.0
から 250.0
の間でランダムに値を選びます(すべて同じ速度で動くとつまらなくなってしまいます)。
注意点として、新しいインスタンスは add_child()
を使ってシーンに追加しなければなりません。
func _on_mob_timer_timeout():
# Create a new instance of the Mob scene.
var mob = mob_scene.instantiate()
# Choose a random location on Path2D.
var mob_spawn_location = get_node("MobPath/MobSpawnLocation")
mob_spawn_location.progress_ratio = randf()
# Set the mob's direction perpendicular to the path direction.
var direction = mob_spawn_location.rotation + PI / 2
# Set the mob's position to a random location.
mob.position = mob_spawn_location.position
# Add some randomness to the direction.
direction += randf_range(-PI / 4, PI / 4)
mob.rotation = direction
# Choose the velocity for the mob.
var velocity = Vector2(randf_range(150.0, 250.0), 0.0)
mob.linear_velocity = velocity.rotated(direction)
# Spawn the mob by adding it to the Main scene.
add_child(mob)
private void OnMobTimerTimeout()
{
// Note: Normally it is best to use explicit types rather than the `var`
// keyword. However, var is acceptable to use here because the types are
// obviously Mob and PathFollow2D, since they appear later on the line.
// Create a new instance of the Mob scene.
Mob mob = MobScene.Instantiate<Mob>();
// Choose a random location on Path2D.
var mobSpawnLocation = GetNode<PathFollow2D>("MobPath/MobSpawnLocation");
mobSpawnLocation.ProgressRatio = GD.Randf();
// Set the mob's direction perpendicular to the path direction.
float direction = mobSpawnLocation.Rotation + Mathf.Pi / 2;
// Set the mob's position to a random location.
mob.Position = mobSpawnLocation.Position;
// Add some randomness to the direction.
direction += (float)GD.RandRange(-Mathf.Pi / 4, Mathf.Pi / 4);
mob.Rotation = direction;
// Choose the velocity.
var velocity = new Vector2((float)GD.RandRange(150.0, 250.0), 0);
mob.LinearVelocity = velocity.Rotated(direction);
// Spawn the mob by adding it to the Main scene.
AddChild(mob);
}
重要
なぜ PI
なのでしょうか?角度を必要とする関数では、Godot は度数ではなく、 ラジアン を使用します。円周率はラジアンの半回転を表し、約 3.1415
です ( 2 * PI
に等しい TAU
もあります) 。もし、度数を扱う方が好きであれば deg_to_rad()
と rad_to_deg()
という関数を使って両者を変換する必要があります。
シーンのテスト¶
シーンをテストして、すべてが動作していることを確認してみましょう。これを _ready()
に追加してください:
func _ready():
new_game()
public override void _Ready()
{
NewGame();
}
また、 Main
を「メインシーン」として設定してみましょう。 (ゲームが起動したときに自動的に実行されるシーンです。) 「プロジェクトを実行」ボタンを押して、プロンプトが表示されたら main.tscn
を選択してください。
ちなみに
すでに他のシーンをメインシーンに設定していた場合は、ファイルシステムドックの main.tscn
を右クリックして「メインシーンとして設定」を選択してください。
プレイヤーを移動でき、モブが発生したり、モブに当たった時にプレイヤーが消えるようになっているはずです。
全て動作していることが確認できたら、 _ready()
から new_game()
の呼び出しを削除してください。
私たちのゲームには何が足りないのでしょう?それは、ユーザーインターフェイスです。次のレッスンでは、タイトル画面を追加して、プレイヤーのスコアを表示することにします。