728x90
본 게시글은 고도엔진 공식문서에 작성된 Your first 2D game를 정리하였습니다.
스크립트 추가
res://HUD.tscn
파일을 열어 HUD 노드를 선택한다.- Attach Script... 를 선택하여
res://HUD.cs
스크립트를 추가한다.
스크립트 코딩
res://HUD.cs
파일을 열어 스크립트를 추가할 때 자동으로 생성된_Ready
메소드와_Process
메소드를 제거한다.StartGameEventHandler
시그널을 추가한다.- C#에서 시그널을 추가할 때는 반드시 시그널 이름 뒤에 EventHandler까지 표기해줘야 된다.
[Signal]
public delegate void StartGameEventHandler();
ShowMessage
메소드를 추가한다.ShowMessage
메소드는 게임에서 원하는 메시지를 2초동안 출력하는 용도로 사용한다.
public void ShowMessage(string text)
{
var messageLabel = GetNode<Label>("Message");
messageLabel.Text = text;
messageLabel.Show();
GetNode<Timer>("MessageTimer").Start();
}
ShowGameOver
함수를 추가한다.ShowGameOver
함수는 플레이어가 사망하였을 경우 2초동안 Game Over 메시지를 출력한 후 Dodge the Creeps! 메시지와 시작버튼을 출력하는 용도로 사용한다.
public async void ShowGameOver()
{
ShowMessage("Game Over");
await ToSignal(GetNode<Timer>("MessageTimer"), Timer.SignalName.Timeout);
var messageLabel = GetNode<Label>("Message");
messageLabel.Text = "Dodge the Creeps!";
messageLabel.Show();
await ToSignal(GetTree().CreateTimer(1), Timer.SignalName.Timeout);
GetNode<Button>("StartButton").Show();
}
- C#에서
await
키워드를 사용하려면 메소드에async
를 선언해야 된다. await ToSignal([Timer 노드], Timer.SignalName.Timeout)
를 입력하면 Timeout 시그널이 호출될 때까지 대기하게 된다.GetTree().CreateTimer()
메소드를 사용하여 스크립에서 바로 타이머를 만들 수도 있다.
UpdateScore
메소드를 추가한다.UpdateScore
메소드는 게임 중 현재 점수를 출력할 때 사용한다.
public void UpdateScore(int score)
{
GetNode<Label>("ScoreLabel").Text = score.ToString();
}
- StartButton 노드의 pressed 시그널을 HUD 노드와 연결한다.
- 문법규칙을 맞추기 위해 연결할 메소드 이름은
OnStartButtonPressed
로 변경한다.
- C#은 시그널을 연결해도 메소드가 자동추가되지 않기 때문에 HUD 클래스에 직접
OnStartButtonPressed
메소드를 추가한다. OnStartButtonPressed
메소드 안에 아래 내용을 추가한다.- 시작버튼을 누르면 시작버튼을 화면에서 감춘 후
StartGame
시그널을 발생시키도록 구현한다.
public void OnStartButtonPressed()
{
GetNode<Button>("StartButton").Hide();
EmitSignal(SignalName.StartGame);
}
- MessageTimer 노드의 timeout 시그널을 HUD 노드와 연결한다.
- 문법규칙을 맞추기 위해 연결할 메소드 이름은
OnMessageTimerTimeout
로 변경한다.
- C#은 시그널을 연결해도 메소드가 자동추가되지 않기 때문에 HUD 클래스에 직접
OnMessageTimerTimeout
메소드를 추가한다. OnMessageTimerTimeout
메소드 안에 아래 내용을 추가한다.- 메시지를 출력하고 2초후에 메시지를 감추도록 구현한다.
public void OnMessageTimerTimeout()
{
GetNode<Label>("Message").Hide();
}
res://HUD.cs
파일들을 저장한 후 오론쪽 상단의 Build Project를 클릭하여 스크립트 내용을 적용한다.res://HUD.tscn
파일들을 저장한다.
게임 씬과 연결
res://Main.tscn
씬을 열고,res://HUD.tscn
씬을 Main 노드의 자식으로 추가한다.
- HUD 노드의 StartGame 시그널을 Main 클래스에 추가했던
NewGame
메소드와 연결한다.
- Main 클래스를 아래 내용에 맞춰 수정한다.
NewGame
메소드에 아래 내용을 추가한다.NewGame
메소드에 내용을 추가하면 아래 내용이 적용된다.- 게임이 시작될 때 초기화된 점수를 화면에 출력한다.
- 게임이 시작되면 Get Ready 메시지를 2초동안 출력한다.
var hud = GetNode<HUD>("HUD");
hud.UpdateScore(Score);
hud.ShowMessage("Get Ready");
GameOver
메소드에 아래 내용을 추가한다.- 게임이 끝나면 Game Over 메시지를 출력한 후 시작버튼을 출력한다.
GetNode<HUD>("HUD").ShowGameOver();
OnScoreTimerTimeout
메소드에 아래 내용을 추가한다.- 점수가 증가할 때 마다 화면에 증가한 점수가 출력되도록 구현한다.
GetNode<HUD>("HUD").UpdateScore(Score);
_Ready
메소드를 지우거나 주석처리하여 시작버튼을 누르지 않으면 게임이 시작되지 않도록 수정한다.
/*public override void _Ready()
{
NewGame();
}*/
res://Main.cs
파일들을 저장한 후 오론쪽 상단의 Build Project를 클릭하여 스크립트 내용을 적용한다.res://Main.tscn
파일을 저장한다.
게임 씬 테스트
- 오른쪽 상단의 Run Project를 클릭하여 게임을 테스트한다.
완성된 스크립트
HUD.cs
using Godot;
using System;
public partial class HUD : CanvasLayer
{
[Signal]
public delegate void StartGameEventHandler();
public void ShowMessage(string text)
{
var messageLabel = GetNode<Label>("Message");
messageLabel.Text = text;
messageLabel.Show();
GetNode<Timer>("MessageTimer").Start();
}
public async void ShowGameOver()
{
ShowMessage("Game Over");
await ToSignal(GetNode<Timer>("MessageTimer"), Timer.SignalName.Timeout);
var messageLabel = GetNode<Label>("Message");
messageLabel.Text = "Dodge the Creeps!";
messageLabel.Show();
await ToSignal(GetTree().CreateTimer(1), Timer.SignalName.Timeout);
GetNode<Button>("StartButton").Show();
}
public void UpdateScore(int score)
{
GetNode<Label>("ScoreLabel").Text = score.ToString();
}
public void OnStartButtonPressed()
{
GetNode<Button>("StartButton").Hide();
EmitSignal(SignalName.StartGame);
}
public void OnMessageTimerTimeout()
{
GetNode<Label>("Message").Hide();
}
}
Main.cs
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");
var hud = GetNode<HUD>("HUD");
player.Start(startPosition.Position);
GetNode<Timer>("StartTimer").Start();
hud.UpdateScore(Score);
hud.ShowMessage("Get Ready");
}
void GameOver()
{
GetNode<Timer>("ScoreTimer").Stop();
GetNode<Timer>("MobTimer").Stop();
GetNode<HUD>("HUD").ShowGameOver();
}
void OnStartTimerTimeout()
{
GetNode<Timer>("ScoreTimer").Start();
GetNode<Timer>("MobTimer").Start();
}
void OnScoreTimerTimeout()
{
++Score;
GetNode<HUD>("HUD").UpdateScore(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);
}
}
'Godot' 카테고리의 다른 글
[GodotDocs][Your First 2D Game] 10. 마무리 작업(C#) (0) | 2024.04.07 |
---|---|
[GodotDocs][Your First 2D Game] 10. 마무리 작업(GDScript) (0) | 2024.04.07 |
[GodotDocs][Your First 2D Game] 9. HUD 씬 코딩(GDScript) (0) | 2024.03.24 |
[공지][GodotDocs][Your First 2D Game] "7. 게임 씬 코딩" 수정 (0) | 2024.03.24 |
[GodotDocs][Your First 2D Game] 8. HUD 씬 제작 (2) | 2024.03.17 |