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 を選択してください。

../../_images/instance_scene.webp

次に Main の子供として以下のノードを追加します(値は秒単位です)。

  • Timer( MobTimer という名前) - モブが出現する頻度を制御する

  • Timer ( ScoreTimer という名前) - 一秒ごとに得点を上げる

  • Timer ( StartTimer という名前) - 開始する前に遅延させる

  • Marker2D (StartPosition という名前) - プレイヤーの開始位置を示す

Timer ノードの Wait Time プロパティを次のように設定します:

  • MobTimer: 0.5

  • ScoreTimer: 1

  • StartTimer: 2

さらに、 StartTimerOne Shot プロパティを「On」に設定し、 StartPosition ノードの Position(240, 450) に設定します。

モブの生成

メインノードは新しいモブを生成し、画面の端のランダムな場所に表示するようにします。 Main の子として MobPath という名前のPath2Dノードを追加します。 Path2D を選択すると、エディタの上部にいくつかの新しいボタンが表示されます:

../../_images/path2d_buttons.webp

中央のアイコン([点を空きスペースに追加])を選択し、表示されているコーナーをクリックしてポイントを追加してパスを描画します。ポイントをグリッドにスナップするには、[グリッドスナップを使う]が選択されていることを確認します。このオプションは、[選択Nodeをロック]ボタンの左側にあり、「交差する線と磁石」のアイコンで表示されています。

../../_images/grid_snap_button.webp

重要

時計回りにパスを描画します。そうしないと、モブは内側ではなく外側を向いて発生します!

../../_images/draw_path2d.gif

画像にポイント 4 を配置した後、「カーブを閉じる」ボタンをクリックすると、カーブが完成します。

パスが定義されたので、 MobPath の子としてPathFollow2Dノードを追加し、 MobSpawnLocation という名前を付けます。このノードは自動的に回転し、パスの移動に従うので、パスに沿ってランダムな位置と方向を選択できます。

シーンは次のようになります:

../../_images/main_scene_nodes.webp

Mainスクリプト

スクリプトを Main に追加します。 スクリプトの上部に @export var mob_scene: PackedScene を追加して、インスタンス化するMobシーンを選択できるようにします。

extends Node

@export var mob_scene: PackedScene
var 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()

次に、各Timerノード (StartTimerScoreTimerMobTimer) の timeout() シグナルをMainスクリプトに接続します。 StartTimer は他の2つのタイマーを開始します。 ScoreTimer はスコアを1増やします。

func _on_score_timer_timeout():
    score += 1

func _on_start_timer_timeout():
    $MobTimer.start()
    $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)

重要

なぜ PI なのでしょうか?角度を必要とする関数では、Godot は度数ではなく、 ラジアン を使用します。円周率はラジアンの半回転を表し、約 3.1415 です ( 2 * PI に等しい TAU もあります) 。もし、度数を扱う方が好きであれば deg_to_rad()rad_to_deg() という関数を使って両者を変換する必要があります。

シーンのテスト

シーンをテストして、すべてが動作していることを確認してみましょう。これを _ready()に追加してください:

func _ready():
    new_game()

また、 Main を「メインシーン」として設定してみましょう。 (ゲームが起動したときに自動的に実行されるシーンです。) 「プロジェクトを実行」ボタンを押して、プロンプトが表示されたら main.tscn を選択してください。

ちなみに

すでに他のシーンをメインシーンに設定していた場合は、ファイルシステムドックの main.tscn を右クリックして「メインシーンとして設定」を選択してください。

プレイヤーを移動でき、モブが発生したり、モブに当たった時にプレイヤーが消えるようになっているはずです。

全て動作していることが確認できたら、 _ready() から new_game() の呼び出しを削除してください。

私たちのゲームには何が足りないのでしょう?それは、ユーザーインターフェイスです。次のレッスンでは、タイトル画面を追加して、プレイヤーのスコアを表示することにします。