added achievement popup in game
parent
7c3d95aa9f
commit
b71ea39155
Binary file not shown.
|
|
@ -0,0 +1,24 @@
|
|||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://c7x1rtkae66k4"
|
||||
path="res://.godot/imported/achievement_unlock.wav-9a9f9e013cd33e691b8d6734dd2cf61a.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/music&sfx/sfx/achievement_unlock.wav"
|
||||
dest_files=["res://.godot/imported/achievement_unlock.wav-9a9f9e013cd33e691b8d6734dd2cf61a.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
extends Node
|
||||
|
||||
const SAVE_PATH = "user://achievements.json"
|
||||
const _POPUP_SCRIPT = preload("res://scripts/achievement_popup.gd")
|
||||
var achievements: Array = []
|
||||
|
||||
func _ready() -> void:
|
||||
|
|
@ -123,15 +124,22 @@ func _define() -> void:
|
|||
]
|
||||
|
||||
func check_all() -> void:
|
||||
var changed = false
|
||||
var newly_unlocked: Array = []
|
||||
for ach in achievements:
|
||||
if ach.unlocked:
|
||||
continue
|
||||
if _meets(ach):
|
||||
ach.unlocked = true
|
||||
changed = true
|
||||
if changed:
|
||||
newly_unlocked.append(ach)
|
||||
if not newly_unlocked.is_empty():
|
||||
_save()
|
||||
for ach in newly_unlocked:
|
||||
_show_popup(ach)
|
||||
|
||||
func _show_popup(ach: Dictionary) -> void:
|
||||
var popup = _POPUP_SCRIPT.new()
|
||||
get_tree().root.add_child(popup)
|
||||
popup.show_unlock(ach)
|
||||
|
||||
func _meets(ach: Dictionary) -> bool:
|
||||
var d = StatsManager.data
|
||||
|
|
|
|||
|
|
@ -0,0 +1,122 @@
|
|||
extends CanvasLayer
|
||||
|
||||
const _VP_W := 1280.0
|
||||
const _VP_H := 720.0
|
||||
const _MARGIN := 16.0
|
||||
const _SFX_PATH := "res://assets/music&sfx/sfx/achievement_unlock.wav"
|
||||
|
||||
var _font = preload("res://assets/fonts/slkscre.ttf")
|
||||
var _panel: PanelContainer
|
||||
|
||||
func _ready() -> void:
|
||||
layer = 100
|
||||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
|
||||
_panel = PanelContainer.new()
|
||||
_panel.custom_minimum_size = Vector2(310.0, 76.0)
|
||||
_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color(0.04, 0.04, 0.12, 0.96)
|
||||
style.border_width_left = 2
|
||||
style.border_width_top = 2
|
||||
style.border_width_right = 2
|
||||
style.border_width_bottom = 2
|
||||
style.border_color = Color(0.78, 0.62, 0.18, 1.0)
|
||||
style.corner_radius_top_left = 3
|
||||
style.corner_radius_top_right = 3
|
||||
style.corner_radius_bottom_right = 3
|
||||
style.corner_radius_bottom_left = 3
|
||||
style.content_margin_left = 8.0
|
||||
style.content_margin_top = 8.0
|
||||
style.content_margin_right = 12.0
|
||||
style.content_margin_bottom = 8.0
|
||||
_panel.add_theme_stylebox_override("panel", style)
|
||||
|
||||
_panel.position = Vector2(_VP_W + 8.0, _VP_H - 76.0 - _MARGIN)
|
||||
add_child(_panel)
|
||||
|
||||
|
||||
func show_unlock(ach: Dictionary) -> void:
|
||||
var hbox := HBoxContainer.new()
|
||||
hbox.add_theme_constant_override("separation", 10)
|
||||
hbox.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_panel.add_child(hbox)
|
||||
|
||||
# Icon square
|
||||
var icon_wrap := Control.new()
|
||||
icon_wrap.custom_minimum_size = Vector2(52, 52)
|
||||
icon_wrap.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
hbox.add_child(icon_wrap)
|
||||
|
||||
var icon_bg := ColorRect.new()
|
||||
icon_bg.color = ach.color
|
||||
icon_bg.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
icon_bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
icon_wrap.add_child(icon_bg)
|
||||
|
||||
var icon_lbl := Label.new()
|
||||
icon_lbl.text = ach.icon_char
|
||||
icon_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
icon_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
icon_lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
icon_lbl.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
icon_lbl.add_theme_font_override("font", _font)
|
||||
icon_lbl.add_theme_font_size_override("font_size", 22)
|
||||
icon_lbl.add_theme_color_override("font_color", Color(1.0, 1.0, 0.88))
|
||||
icon_lbl.add_theme_color_override("font_outline_color", Color(0.0, 0.0, 0.0, 0.8))
|
||||
icon_lbl.add_theme_constant_override("outline_size", 2)
|
||||
icon_wrap.add_child(icon_lbl)
|
||||
|
||||
# Text block
|
||||
var vbox := VBoxContainer.new()
|
||||
vbox.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
vbox.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
hbox.add_child(vbox)
|
||||
|
||||
var header := Label.new()
|
||||
header.text = "Achievement Unlocked!"
|
||||
header.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
header.add_theme_font_override("font", _font)
|
||||
header.add_theme_font_size_override("font_size", 13)
|
||||
header.add_theme_color_override("font_color", Color(0.78, 0.62, 0.18, 1.0))
|
||||
vbox.add_child(header)
|
||||
|
||||
var title_lbl := Label.new()
|
||||
title_lbl.text = ach.title
|
||||
title_lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
title_lbl.add_theme_font_override("font", _font)
|
||||
title_lbl.add_theme_font_size_override("font_size", 20)
|
||||
title_lbl.add_theme_color_override("font_color", Color(1.0, 0.95, 0.8, 1.0))
|
||||
vbox.add_child(title_lbl)
|
||||
|
||||
_play_sound()
|
||||
# Wait one frame so the panel has its final size before animating
|
||||
await get_tree().process_frame
|
||||
_animate()
|
||||
|
||||
|
||||
func _play_sound() -> void:
|
||||
if not ResourceLoader.exists(_SFX_PATH):
|
||||
return
|
||||
var sfx := AudioStreamPlayer.new()
|
||||
sfx.stream = load(_SFX_PATH)
|
||||
sfx.volume_db = -2.0
|
||||
sfx.process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
add_child(sfx)
|
||||
sfx.play()
|
||||
sfx.finished.connect(sfx.queue_free)
|
||||
|
||||
func _animate() -> void:
|
||||
var pw := _panel.size.x
|
||||
var target_x := _VP_W - pw - _MARGIN
|
||||
_panel.position.x = _VP_W + 8.0
|
||||
|
||||
var tween := create_tween()
|
||||
tween.set_pause_mode(Tween.TWEEN_PAUSE_PROCESS)
|
||||
tween.tween_property(_panel, "position:x", target_x, 0.4)\
|
||||
.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_QUART)
|
||||
tween.tween_interval(3.5)
|
||||
tween.tween_property(_panel, "position:x", _VP_W + 8.0, 0.3)\
|
||||
.set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_QUART)
|
||||
tween.tween_callback(queue_free)
|
||||
|
|
@ -0,0 +1 @@
|
|||
uid://dsitid33q7lcx
|
||||
|
|
@ -50,10 +50,12 @@ func end_run(died: bool) -> void:
|
|||
func on_kill(enemy_type: String) -> void:
|
||||
if data["kills"].has(enemy_type):
|
||||
data["kills"][enemy_type] += 1
|
||||
AchievementManager.call_deferred("check_all")
|
||||
|
||||
func on_spell_cast(spell_type: String) -> void:
|
||||
if data["spells_cast"].has(spell_type):
|
||||
data["spells_cast"][spell_type] += 1
|
||||
AchievementManager.call_deferred("check_all")
|
||||
|
||||
func _save() -> void:
|
||||
var file = FileAccess.open(SAVE_PATH, FileAccess.WRITE)
|
||||
|
|
|
|||
Loading…
Reference in New Issue