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
|
extends Node
|
||||||
|
|
||||||
const SAVE_PATH = "user://achievements.json"
|
const SAVE_PATH = "user://achievements.json"
|
||||||
|
const _POPUP_SCRIPT = preload("res://scripts/achievement_popup.gd")
|
||||||
var achievements: Array = []
|
var achievements: Array = []
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
|
@ -123,15 +124,22 @@ func _define() -> void:
|
||||||
]
|
]
|
||||||
|
|
||||||
func check_all() -> void:
|
func check_all() -> void:
|
||||||
var changed = false
|
var newly_unlocked: Array = []
|
||||||
for ach in achievements:
|
for ach in achievements:
|
||||||
if ach.unlocked:
|
if ach.unlocked:
|
||||||
continue
|
continue
|
||||||
if _meets(ach):
|
if _meets(ach):
|
||||||
ach.unlocked = true
|
ach.unlocked = true
|
||||||
changed = true
|
newly_unlocked.append(ach)
|
||||||
if changed:
|
if not newly_unlocked.is_empty():
|
||||||
_save()
|
_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:
|
func _meets(ach: Dictionary) -> bool:
|
||||||
var d = StatsManager.data
|
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:
|
func on_kill(enemy_type: String) -> void:
|
||||||
if data["kills"].has(enemy_type):
|
if data["kills"].has(enemy_type):
|
||||||
data["kills"][enemy_type] += 1
|
data["kills"][enemy_type] += 1
|
||||||
|
AchievementManager.call_deferred("check_all")
|
||||||
|
|
||||||
func on_spell_cast(spell_type: String) -> void:
|
func on_spell_cast(spell_type: String) -> void:
|
||||||
if data["spells_cast"].has(spell_type):
|
if data["spells_cast"].has(spell_type):
|
||||||
data["spells_cast"][spell_type] += 1
|
data["spells_cast"][spell_type] += 1
|
||||||
|
AchievementManager.call_deferred("check_all")
|
||||||
|
|
||||||
func _save() -> void:
|
func _save() -> void:
|
||||||
var file = FileAccess.open(SAVE_PATH, FileAccess.WRITE)
|
var file = FileAccess.open(SAVE_PATH, FileAccess.WRITE)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue