120 lines
3.8 KiB
GDScript
120 lines
3.8 KiB
GDScript
extends Node
|
|
var _sound: Script = load("res://scripts/sound_manager.gd")
|
|
## GameManager (автоматически запускается как Autoload).
|
|
## Этап 4: централизованное состояние игры — счёт, жизни, таймер,
|
|
## победы/поражение, save/load рекорда, звуковое сопровождение.
|
|
|
|
# Счёт игрока
|
|
var score: int = 0
|
|
# Оставшиеся жизни
|
|
var lives: int = 3
|
|
# Прошедшее время в секундах (таймер уровня)
|
|
var time_elapsed: float = 0.0
|
|
# Лучшее время прохождения (в секундах), сохраняется в user://save.cfg
|
|
var best_time: float = -1.0
|
|
|
|
# Состояние игры: "playing" | "won" | "lost"
|
|
var state: String = "playing"
|
|
|
|
# Сумма очков для победы на текущем уровне (задается уровнем)
|
|
var win_score_threshold: int = 500
|
|
|
|
# Ссылки на звуковые проигрыватели для win/lose экранов
|
|
var _bgm_win: AudioStreamPlayer2D
|
|
var _bgm_over: AudioStreamPlayer2D
|
|
|
|
func _ready() -> void:
|
|
# Загружаем сохранённый рекорд (если есть)
|
|
_load_best_time()
|
|
print("[GameManager] Проект инициализирован. Состояние: playing. Лучшее время: ", _fmt_time(best_time))
|
|
|
|
# Фонки для экранов победы/поражения
|
|
_bgm_win = AudioStreamPlayer2D.new()
|
|
_bgm_win.bus = "Master"
|
|
_bgm_over = AudioStreamPlayer2D.new()
|
|
_bgm_over.bus = "Master"
|
|
add_child(_bgm_win)
|
|
add_child(_bgm_over)
|
|
|
|
func _process(delta: float) -> void:
|
|
if state == "playing":
|
|
time_elapsed += delta
|
|
|
|
func _fmt_time(t: float) -> String:
|
|
if t < 0.0:
|
|
return "--:--"
|
|
var minutes := int(t) / 60
|
|
var seconds := int(t) % 60
|
|
return "%02d:%02d" % [minutes, seconds]
|
|
|
|
# ==== Счёт ====
|
|
func add_score(points: int) -> void:
|
|
if state != "playing":
|
|
return
|
|
score += points
|
|
print("[GameManager] +", points, " очков. Итого: ", score)
|
|
if score >= win_score_threshold:
|
|
win()
|
|
|
|
# ==== Жизни ====
|
|
func lose_life() -> bool:
|
|
lives = maxi(0, lives - 1)
|
|
print("[GameManager] -1 жизнь. Осталось: ", lives)
|
|
if lives <= 0:
|
|
over()
|
|
return false
|
|
return true
|
|
|
|
func respawn() -> void:
|
|
print("[GameManager] Возрождение Fox.")
|
|
|
|
# ==== Состояния игры ====
|
|
signal state_changed(state: String)
|
|
|
|
func win() -> void:
|
|
if state != "playing":
|
|
return
|
|
state = "won"
|
|
_save_best_time()
|
|
print("[GameManager] ПОБЕДА! Счёт: ", score, " | Время: ", _fmt_time(time_elapsed))
|
|
if _bgm_win.stream == null:
|
|
_bgm_win.stream = load("res://audio/sound_win.ogg")
|
|
_bgm_win.play(0.0)
|
|
state_changed.emit("won")
|
|
|
|
func over() -> void:
|
|
if state != "playing":
|
|
return
|
|
state = "lost"
|
|
_save_best_time()
|
|
print("[GameManager] ИГРА ОКОНЧЕНА. Счёт: ", score)
|
|
if _bgm_over.stream == null:
|
|
_bgm_over.stream = load("res://audio/sound_over.ogg")
|
|
_bgm_over.play(0.0)
|
|
state_changed.emit("lost")
|
|
|
|
# ==== Save/Load ====
|
|
func save_best_time() -> void:
|
|
if best_time < 0.0 or time_elapsed < best_time:
|
|
best_time = time_elapsed
|
|
_save_best_time()
|
|
|
|
func _load_best_time() -> void:
|
|
var cfg := ConfigFile.new()
|
|
var err := cfg.load("user://save.cfg")
|
|
if err == OK and cfg.has_section("records"):
|
|
best_time = cfg.get_value("records", "best_time", -1.0)
|
|
|
|
func _save_best_time() -> void:
|
|
var cfg := ConfigFile.new()
|
|
if cfg.load("user://save.cfg") == OK and cfg.has_section("records"):
|
|
cfg.set_value("records", "best_time", best_time)
|
|
cfg.save("user://save.cfg")
|
|
|
|
# ==== Звук (через SoundManager) ====
|
|
func sfx(name: String) -> void:
|
|
var node := get_tree().root.get_node_or_null("SoundManager")
|
|
if node != null:
|
|
if node.has_method("play"):
|
|
node.call("play", name)
|