본문 바로가기
Godot

[GodotDocs][Your First 2D Game] 9. HUD 씬 코딩(GDScript)

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

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

 

스크립트 추가

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

 

스크립트 코딩

  • res://hud.gd 파일을 열어 스크립트를 추가할 때 자동으로 생성된 _ready 함수와 _process 함수를 제거한다.
  • start_game 시그너을 추가한다.
  • start_game 시그널은 나중에 게임 씬(Main 씬)과 연결한다.
extends CanvasLayer

signal start_game

 

  • show_message 함수를 추가한다.
  • show_message 함수는 게임에서 원하는 메시지를 2초동안 출력하는 용도로 사용한다.
func show_message(text):
    $Message.text = text
    $Message.show()
    $MessageTimer.start()

 

  • show_game_over 함수를 추가한다.
  • show_game_over 함수는 플레이어가 사망하였을 경우 2초동안 Game Over 메시지를 출력한 후 Dodge the Creeps! 메시지와 시작버튼을 출력하는 용도로 사용한다.
func show_game_over():
    show_message("Game Over")
    await $MessageTimer.timeout

    $Message.text = "Dodge the Creeps!"
    $Message.show()
    await get_tree().create_timer(1.0).timeout

    $StartButton.show()
  • await 키워드를 사용하면 따로 timeout 시그널과 연결된 함수를 만들지 않고, show_game_over 함수 내부에서 2초동안 대기할 수 있다.
  • get_tree().create_timer() 함수를 사용하여 스크립트에서 바로 타이머를 만들 수도 있다.

 

  • update_score 함수를 추가한다.
  • update_score 함수는 게임 중 현재 점수를 출력할 때 사용한다.
func update_score(score):
    $ScoreLabel.text = str(score)
  • str 함수는 변수를 문자열로 바꿔주는 함수이다.

 

  • StartButton 노드의 pressed 시그널을 HUD 노드와 연결한다.
  • pressed 시그널을 연결할 때 추가된 _on_start_button_pressed 함수에 아래 내용을 추가한다.
  • 시작버튼을 누르면 시작버튼을 화면에서 감춘 후 start_game 시그널을 발생시키도록 구현한다.
func _on_start_button_pressed():
    $StartButton.hide()
    start_game.emit()

 

  • MessageTimer 노드의 timeout 시그널을 HUD 노드와 연결한다.
  • timeout 시그널을 연결할 때 추가된 _on_message_timer_timeout 함수에 아래 내용을 추가한다.
  • 메시지를 출력하고 2초후에 메시지를 감추도록 구현한다.
func _on_message_timer_timeout():
    $Message.hide()

 

  • res://HUD.tscn, res://hud.gd 파일들을 저장한다.

 

게임 씬과 연결

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

 

  • HUD 노드의 start_game 시그널을 res://main.gd 스크립트에 추가했던 new_game 함수와 연결한다.
  • new_game 함수는 이미 추가되어 있기 때문에 시그널과 연결해도 함수가 자동으로 추가되지 않는다.

 

  • res://main.gd 스크립트를 아래 내용에 맞춰 수정한다.
  • new_game 함수에 아래 내용을 추가한다.
  • new_game 함수에 해당 내용을 추가하면 아래 내용이 적용된다.
    • 게임이 시작될 때 초기화된 점수를 화면에 출력한다.
    • 게임이 시작되면 Get Ready 메시지를 2초동안 출력한다.
$HUD.update_score(score)
$HUD.show_message("Get Ready")

 

  • game_over 함수에 아래 내용을 추가한다.
  • 게임이 끝나면 Game Over 메시지를 출력한 후 시작버튼을 출력한다.
$HUD.show_game_over()

 

  • _on_score_timer_timeout 함수에 아래 내용을 추가한다.
  • 점수가 증가할 때 마다 화면에 증가한 점수가 출력되도록 구현한다.
$HUD.update_score(score)

 

  • _ready 함수를 지우거나 주석처리하여 시작버튼을 누르지 않으면 게임이 시작되지 않도록 수정한다.
#func _ready():
#    new_game()

 

  • res://Main.tscn, res://main.gd 파일을 저장한다.

 

게임 씬 테스트

  • 오른쪽 상단의 Run Project를 클릭하여 게임을 테스트한다.

 

완성된 스크립트

hud.gd
extends CanvasLayer

signal start_game

func show_message(text):
    $Message.text = text
    $Message.show()
    $MessageTimer.start()

func show_game_over():
    show_message("Game Over")
    await $MessageTimer.timeout

    $Message.text = "Dodge the Creeps!"
    $Message.show()
    await get_tree().create_timer(1.0).timeout

    $StartButton.show()

func update_score(score):
    $ScoreLabel.text = str(score)

func _on_start_button_pressed():
    $StartButton.hide()
    start_game.emit()

func _on_message_timer_timeout():
    $Message.hide()
main.gd
extends Node

@export var mob_scene: PackedScene
var score

#func _ready():
#    new_game()

func game_over():
    $ScoreTimer.stop()
    $MobTimer.stop()
    $HUD.show_game_over()

func new_game():
    score = 0
    $Player.start($StartPosition.position)
    $StartTimer.start()
    $HUD.update_score(score)
    $HUD.show_message("Get Ready")

func _on_start_timer_timeout():
    $ScoreTimer.start()
    $MobTimer.start()

func _on_score_timer_timeout():
    score += 1
    $HUD.update_score(score)

func _on_mob_timer_timeout():
    var mob = mob_scene.instantiate()

    var spawn_location = $MobPath/MobSpawnLocation
    spawn_location.progress_ratio = randf()

    var direction = spawn_location.rotation + PI / 2
    direction += randf_range(-PI / 4, PI / 4)

    mob.position = spawn_location.position
    mob.rotation = direction

    var velocity = Vector2(randf_range(150.0, 250.0), 0.0)
    mob.linear_velocity = velocity.rotated(direction)

    add_child(mob)