더 많은 스프라이트, GameManager 및 리팩토링
Source: Dev.to
More Sprites
우리는 지금 실제로 큰 진전을 이루고 있습니다. 지난 글에서는 물고기와 보트를 보여드렸죠. 하지만 그게 전부가 아니라—구름과 물, 정확히는 파도도 추가했습니다.
보트를 약간 아래로 내렸습니다. 이제 보트가 물 위에 어색하게 떠 있는 것이 아니라 실제로 물에 앉아 있는 것처럼 보입니다.
Boat bobbing animation
좀 더 살아있는 느낌을 주기 위해 배에 미세한 흔들림 효과를 넣었습니다. AnimationPlayer를 Player 씬에 추가하고, 새로운 애니메이션을 만든 뒤 Y 위치를 0 → -2 → 0으로 애니메이션했습니다. 그리고 루프하도록 설정했습니다.
# Get the animation reference
@onready var animation = $AnimationPlayer
func _ready() -> void:
animation.play("bopp") # Note: the animation is intentionally named "bopp"
작은 움직임이지만 큰 차이를 만들어 줍니다. 배가 더 이상 정적인 느낌이 아니라, 마치 물 위에 실제로 떠 있는 듯 부드럽게 움직입니다.
Waves
파도를 위해 TileMapLayer를 Main 씬의 자식 노드로 추가했습니다. 이것을 별도의 씬으로 만들고 인스턴스화했어야 했는지는 아직 확신이 서지 않지만, 나중에 정리해 보겠습니다.
파도 타일용으로 전용 스프라이트시트를 만들었습니다. 앞으로는 프로젝트에 흩어져 있는 단일 이미지 대신 모든 것을 스프라이트시트로 옮길 계획입니다.
(Spritesheet preview omitted)
GameManager Refactoring
코드에 큰 변화를 주었습니다. 중요한 로직이 여러 곳에 흩어져 있던 것을 GameManager라는 하나의 스크립트로 집중시켰습니다. 이 스크립트는 점수, 목숨, 게임 오버 로직 등 공유 데이터와 전역 행동을 담당합니다.
extends Node
signal lives_changed(new_lives)
signal score_changed(new_score)
var lives = 3
var current_score = 0
# ---- Score handling ----
func _update_score(fish_score):
current_score += fish_score
score_changed.emit(current_score)
# ---- Health handling ----
func _decrease_life():
if lives > 0:
lives -= 1
lives_changed.emit(lives)
if lives == 0:
_game_over()
# ---- Game over UI ----
func _game_over():
var game_over_scene = preload("uid://behejrhw6wlo7")
var game_over_instance = game_over_scene.instantiate()
var GameOverCanvas = get_node("/root/MainScene/GameOverCanvas")
GameOverCanvas.add_child(game_over_instance)
get_tree().paused = true
헬스와 게임 오버 시스템은 아직 진행 중이지만, 점수 시스템은 정상적으로 동작합니다.
Fish script interaction
@export var fish_score = 1
func _on_body_entered(body):
if body.is_in_group("Player"):
GameManager._update_score(fish_score)
queue_free()
물고기가 플레이어와 충돌하면 GameManager 싱글톤의 _update_score를 호출합니다. 이 함수는 총 점수를 업데이트하고 신호를 발생시키며, UI는 이 신호를 받아 점수 카운터를 갱신합니다.
Flow:
플레이어가 물고기를 잡는다 → GameManager의 _update_score 호출 → 현재 점수(초기값 0)가 물고기 값만큼 증가 → score_changed 신호 발생 → UI가 업데이트된다.
Godot에서 싱글톤을 사용해 본 적이 없어서 이해하는 데 시간이 좀 걸렸습니다. 짧은 영상을 보고 실험해 보니 감이 잡혔습니다.
What’s next?
다음 글에서는 GameManager를 더 깊게 파고들어 UI와 어떻게 연결되는지 보여주고, 헬스 시스템을 완성하며, 폭탄 메커니즘을 소개할 예정입니다.
댓글이나 피드백을 자유롭게 남겨 주세요. 아직 배우는 중이라 실수가 있을 수 있습니다.