Add collectable types and implement level unlocking mechanics; enhance player state management
This commit is contained in:
@@ -7,7 +7,7 @@ var has_fade_away: bool = false
|
||||
@export var area2d: Area2D
|
||||
@export var collectable_data: CollectableResource
|
||||
@export var sfx: AudioStreamPlayer2D
|
||||
signal collected(amount: int)
|
||||
signal collected(amount: int, type: CollectableResource.CollectableType)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -24,7 +24,7 @@ func _ready() -> void:
|
||||
|
||||
func _on_area2d_body_entered(body: Node2D) -> void:
|
||||
if body.has_node("CanPickUpComponent"):
|
||||
collected.emit(collectable_data.amount)
|
||||
collected.emit(collectable_data.amount, collectable_data.type)
|
||||
if sfx:
|
||||
sfx.play()
|
||||
if not has_fade_away:
|
||||
|
34
scripts/components/exit_door_component.gd
Normal file
34
scripts/components/exit_door_component.gd
Normal file
@@ -0,0 +1,34 @@
|
||||
class_name ExitDoorComponent
|
||||
extends Node
|
||||
|
||||
@export var locked: bool = true
|
||||
@export var exit_area: Area2D
|
||||
@export var door_sprite: Sprite2D
|
||||
@export var opened_door_sfx: AudioStreamPlayer2D
|
||||
@export var opened_door_frame: int = 0
|
||||
signal exit_triggered
|
||||
@onready var gm: GM = $"/root/GameManager"
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not exit_area:
|
||||
printerr("ExitDoorComponent: exit_area is not set.")
|
||||
return
|
||||
|
||||
exit_area.body_entered.connect(on_exit_area_body_entered)
|
||||
|
||||
|
||||
func unlock() -> void:
|
||||
locked = false
|
||||
if door_sprite:
|
||||
door_sprite.frame = opened_door_frame
|
||||
if opened_door_sfx:
|
||||
opened_door_sfx.play()
|
||||
|
||||
|
||||
func on_exit_area_body_entered(_body: Node2D) -> void:
|
||||
if locked:
|
||||
return
|
||||
|
||||
exit_triggered.emit()
|
||||
gm.try_to_go_to_next_level()
|
1
scripts/components/exit_door_component.gd.uid
Normal file
1
scripts/components/exit_door_component.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bwamqffvpa452
|
@@ -24,5 +24,6 @@ func _on_health_component_on_death() -> void:
|
||||
gm.reset_player_state()
|
||||
else:
|
||||
gm.remove_lives(1)
|
||||
gm.set_coins(0)
|
||||
|
||||
call_deferred("reset_scene")
|
||||
|
32
scripts/components/requirement_component.gd
Normal file
32
scripts/components/requirement_component.gd
Normal file
@@ -0,0 +1,32 @@
|
||||
class_name RequirementComponent
|
||||
extends Node
|
||||
|
||||
@export var requirement_type: CollectableResource.CollectableType
|
||||
@export var required_amount: int = 1
|
||||
|
||||
var current_amount: int = 0
|
||||
signal requirement_met(requirement_type: CollectableResource.CollectableType)
|
||||
@onready var gm: GM = $"/root/GameManager"
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not gm:
|
||||
printerr("RequirementComponent: GameManager not found.")
|
||||
return
|
||||
|
||||
var collectables: Array[CollectableComponent] = gm.get_colllectable_nodes()
|
||||
for collectable in collectables:
|
||||
collectable.collected.connect(on_collected)
|
||||
|
||||
|
||||
func on_collected(amount: int, type: CollectableResource.CollectableType) -> void:
|
||||
print("Collected: ", amount, " of type: ", str(type))
|
||||
if type != requirement_type:
|
||||
return
|
||||
add_progress(amount)
|
||||
|
||||
|
||||
func add_progress(amount: int = 1) -> void:
|
||||
current_amount += amount
|
||||
if current_amount >= required_amount:
|
||||
requirement_met.emit(requirement_type)
|
1
scripts/components/requirement_component.gd.uid
Normal file
1
scripts/components/requirement_component.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cmh8k0rdsyh7j
|
@@ -3,17 +3,18 @@ extends Node
|
||||
|
||||
@onready var game_manager: GM = $"/root/GameManager"
|
||||
|
||||
|
||||
func _ready():
|
||||
await get_tree().process_frame
|
||||
var coins = get_tree().get_nodes_in_group("coins")
|
||||
|
||||
|
||||
for coin in coins:
|
||||
coin.connect("collected", on_collected)
|
||||
|
||||
func on_collected(amount: int) -> void:
|
||||
|
||||
func on_collected(amount: int, type: CollectableResource.CollectableType) -> void:
|
||||
if not game_manager:
|
||||
return
|
||||
|
||||
if type != CollectableResource.CollectableType.COIN:
|
||||
return
|
||||
game_manager.add_coins(amount)
|
||||
# todo: play sound
|
||||
# todo: update ui
|
||||
|
26
scripts/components/unlock_on_requirement_component.gd
Normal file
26
scripts/components/unlock_on_requirement_component.gd
Normal file
@@ -0,0 +1,26 @@
|
||||
class_name UnlockOnRequirementComponent
|
||||
extends Node
|
||||
|
||||
@export var requirement_component: RequirementComponent
|
||||
@export var unlock_target: Node
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not requirement_component:
|
||||
printerr("UnlockOnRequirementComponent: requirement_component is not set.")
|
||||
return
|
||||
|
||||
if not unlock_target:
|
||||
printerr("UnlockOnRequirementComponent: unlock_target is not set.")
|
||||
return
|
||||
|
||||
requirement_component.requirement_met.connect(on_requirement_met)
|
||||
|
||||
|
||||
func on_requirement_met(requirement_type: CollectableResource.CollectableType) -> void:
|
||||
if requirement_type == requirement_component.requirement_type:
|
||||
if unlock_target.has_method("unlock"):
|
||||
unlock_target.unlock()
|
||||
else:
|
||||
printerr("UnlockOnRequirementComponent: unlock_target does not have an unlock method.")
|
||||
|
@@ -0,0 +1 @@
|
||||
uid://c8xhgkg8gcqu6
|
@@ -1,11 +1,68 @@
|
||||
class_name GM
|
||||
extends Node
|
||||
|
||||
var player_state = {
|
||||
"coins": 0,
|
||||
"lives": 3,
|
||||
"unlocked_skills": [],
|
||||
}
|
||||
@export var level_scenes: Array[PackedScene]
|
||||
|
||||
@export var player_state := {
|
||||
"coins": 0,
|
||||
"lives": 3,
|
||||
"unlocked_skills": [],
|
||||
"current_level": 0,
|
||||
"unlocked_levels": [],
|
||||
}
|
||||
|
||||
var nodes_in_scene := []
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
get_tree().node_added.connect(on_node_added)
|
||||
get_tree().node_removed.connect(on_node_removed)
|
||||
|
||||
|
||||
func on_node_added(node: Node) -> void:
|
||||
nodes_in_scene.append(node)
|
||||
|
||||
|
||||
func on_node_removed(node: Node) -> void:
|
||||
if node in nodes_in_scene:
|
||||
nodes_in_scene.erase(node)
|
||||
|
||||
|
||||
func get_colllectable_nodes() -> Array[CollectableComponent]:
|
||||
var collectable_nodes: Array[CollectableComponent] = []
|
||||
for node in nodes_in_scene:
|
||||
var collectable_component: CollectableComponent = node.get_node_or_null("Collectable")
|
||||
if not collectable_component:
|
||||
collectable_component = node.get_node_or_null("CollectableComponent")
|
||||
if not collectable_component:
|
||||
continue
|
||||
if collectable_component.collectable_data.type == CollectableResource.CollectableType.KID:
|
||||
print("Kid collectable found: ", collectable_component.get_parent().name)
|
||||
|
||||
collectable_nodes.append(collectable_component)
|
||||
return collectable_nodes
|
||||
|
||||
|
||||
func get_coin_nodes() -> Array[CollectableComponent]:
|
||||
var coin_nodes := []
|
||||
for node in nodes_in_scene:
|
||||
var collectable_component: CollectableComponent = node.get_node_or_null("Collectable")
|
||||
if not collectable_component:
|
||||
continue
|
||||
if collectable_component.collectable_data.type == CollectableResource.CollectableType.COIN:
|
||||
coin_nodes.append(collectable_component)
|
||||
return coin_nodes
|
||||
|
||||
|
||||
func get_kid_nodes() -> Array[CollectableComponent]:
|
||||
var kid_nodes := []
|
||||
for node in nodes_in_scene:
|
||||
var collectable_component: CollectableComponent = node.get_node_or_null("Collectable")
|
||||
if not collectable_component:
|
||||
continue
|
||||
if collectable_component.collectable_data.type == CollectableResource.CollectableType.KID:
|
||||
kid_nodes.append(collectable_component)
|
||||
return kid_nodes
|
||||
|
||||
|
||||
func add_coins(amount: int) -> void:
|
||||
@@ -59,4 +116,16 @@ func reset_player_state() -> void:
|
||||
"coins": 0,
|
||||
"lives": 3,
|
||||
"unlocked_skills": [],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func unlock_level(level_index: int) -> void:
|
||||
if level_index not in player_state["unlocked_levels"]: player_state["unlocked_levels"].append(level_index)
|
||||
|
||||
|
||||
func try_to_go_to_next_level() -> void:
|
||||
if player_state["current_level"] + 1 < level_scenes.size() and player_state["current_level"] + 1 in player_state["unlocked_levels"]:
|
||||
player_state["current_level"] += 1
|
||||
print("Going to next level: ", player_state["current_level"])
|
||||
else:
|
||||
print("No more levels to go to.")
|
||||
|
@@ -1,4 +1,10 @@
|
||||
class_name CollectableResource
|
||||
extends Resource
|
||||
|
||||
@export var amount: int = 0
|
||||
enum CollectableType {
|
||||
COIN,
|
||||
KID,
|
||||
HEALTH,
|
||||
}
|
||||
@export var amount: int = 0
|
||||
@export var type: CollectableType = CollectableType.COIN
|
Reference in New Issue
Block a user