본문 바로가기
Godot

[GodotDocs][Your First 2D Game] 7. 게임 씬 코딩(C#)

by 채식금지 2024. 3. 10.
728x90

본 게시글은 고도엔진 공식문서에 작성된 Your first 2D game를 정리하였습니다.

 

스크립트 추가

  • res://Main.tscn 파일을 열어 Main 노드를 선택한다.
  • Attach Script... 를 선택하여 res://Main.cs 스크립트를 추가한다.

 

스크립트 코딩

  • res://Main.cs 파일을 열어 아래와 같이 필드를 추가한다.
[Export]
public PackedScene MobScene
{
    get;
    private set;
}

public int Score
{
    get;
    private set;
}
  • 스크립트를 저장하고, 빌드하면 Export 어트리뷰트와 함께 선언된 MobScene 프로퍼티는 Main 노드에 Mob Scene 속성으로 추가된다.
  • Main 노드에 추가된 Mob Scene 속성과 res://Mob.tscn 씬을 연결한다.

 

  • 게임을 시작할 때 호출할 NewGame() 메소드와 게임이 끝날 때 호출할 GameOver() 함수를 추가한다.
void NewGame()
{
    Score = 0;

    var player = GetNode<Player>("Player");
    var startPosition = GetNode<Marker2D>("StartPosition");

    player.Start(startPosition.Position);
    GetNode<Timer>("StartTimer").Start();
}

void GameOver()
{
    GetNode<Timer>("ScoreTimer").Stop();
    GetNode<Timer>("MobTimer").Stop();
}
  • GameOver() 메소드가 호출되면 ScoreTimer 노드와 MobTimer 노드를 정지시킨다.
  • NewGame() 메소드가 호출되면 점수와 플레이어의 위치가 초기화되고, StartTimer 노드를 작동시킨다.

 

  • StartTimer, ScoreTimer, MobTimer 노드의 timeout 시그널을 Main 노드와 연결한다.
  • 문법규칙을 맞추기 위해 연결할 메소드들의 이름은 각각 OnStartTimerTimeout, OnScoreTimerTimeout, OnMobTimerTimeout 으로 변경한다.


 

  • C#은 시그널과 연결된 메소드가 자동으로 추가되지 않기 때문에 직접 메소드를 입력하여 추가한다.
  • 추가한 메소드에 아래 내용을 추가한다.
void OnStartTimerTimeout()
{
    GetNode<Timer>("ScoreTimer").Start();
    GetNode<Timer>("MobTimer").Start();
}

void OnScoreTimerTimeout()
{
    ++Score;
}

void OnMobTimerTimeout()
{
    var mob = MobScene.Instantiate<Mob>();

    var spawnLocation = GetNode<PathFollow2D>("MobPath/MobSpawnLocation");
    spawnLocation.ProgressRatio = GD.Randf();

    var direction = spawnLocation.Rotation + Mathf.Pi / 2;
    direction += (float)GD.RandRange(-Mathf.Pi / 4, Mathf.Pi / 4);

    mob.Position = spawnLocation.Position;
    mob.Rotation = direction;

    var velocity = new Vector2((float)GD.RandRange(150.0, 250.0), 0f);
    mob.LinearVelocity = velocity.Rotated(direction);

    AddChild(mob);
}
  • StartTimer 노드의 timeout 시그널이 발생하면 ScoreTimer, MobTimer 노드를 작동시킨다.
  • ScoreTimer 노드의 timeout 시그널이 발생할 때마다 1점씩 점수가 증가한다.
  • MobTimer 노드의 timeout 시그널이 발생할 때마다 적(Mob)이 생성된다.
  • 생성된 적은 랜덤한 위치에 랜덤한 방향과 속도로 이동한다.

 

  • Ready() 메소드 안에 NewGame() 메소드를 추가한 후 프로젝트를 빌드한다.
public override void _Ready()
{
    NewGame();
}

 

플레이어 씬 추가

  • res://Player.tscn 씬을 Main 노드의 자식으로 추가한다.

 

  • Player 노드의 Hit 시그널을 res://main.cs 스크립트에 추가했던 GameOver 메소드와 연결한다.

 

게임 씬 테스트

  • 오른쪽 상단의 Run Project를 클릭하여 Main.tscn 씬을 메인 씬으로 설정하는 동시에 게임이 실행되도록 만든다.

 

완성된 스크립트

using Godot;
using System;

public partial class Main : Node
{
    [Export]
    public PackedScene MobScene
    {
        get;
        private set;
    }

    public int Score
    {
        get;
        private set;
    }

    public override void _Ready()
    {
        NewGame();
    }

    void NewGame()
    {
        Score = 0;

        var player = GetNode<Player>("Player");
        var startPosition = GetNode<Marker2D>("StartPosition");

        player.Start(startPosition.Position);
        GetNode<Timer>("StartTimer").Start();
    }

    void GameOver()
    {
        GetNode<Timer>("ScoreTimer").Stop();
        GetNode<Timer>("MobTimer").Stop();
    }

    void OnStartTimerTimeout()
    {
        GetNode<Timer>("ScoreTimer").Start();
        GetNode<Timer>("MobTimer").Start();
    }

    void OnScoreTimerTimeout()
    {
        ++Score;
    }

    void OnMobTimerTimeout()
    {
        var mob = MobScene.Instantiate<Mob>();

        var spawnLocation = GetNode<PathFollow2D>("MobPath/MobSpawnLocation");
        spawnLocation.ProgressRatio = GD.Randf();

        var direction = spawnLocation.Rotation + Mathf.Pi / 2;
        direction += (float)GD.RandRange(-Mathf.Pi / 4, Mathf.Pi / 4);

        mob.Position = spawnLocation.Position;
        mob.Rotation = direction;

        var velocity = new Vector2((float)GD.RandRange(150.0, 250.0), 0f);
        mob.LinearVelocity = velocity.Rotated(direction);

        AddChild(mob);
    }
}