diff --git a/DebugManager.gd b/DebugManager.gd new file mode 100644 index 0000000..3e155f8 --- /dev/null +++ b/DebugManager.gd @@ -0,0 +1,70 @@ +extends CanvasLayer + +@onready var debug_console = get_node("/root/Main/DebugConsole") +@export var update_interval: float = 0.5 # Time between global debug info updates +var update_timer: float = 0.0 +var global_debug_visible: bool = false +var instance_debug_visible: bool = false +var debug_label: Label # Declare as a class-level variable + +signal toggle_instance_debug_signal(visible: bool) + +func _ready(): + # Check for duplicate DebugManager instances + var existing_debug_managers = get_tree().get_nodes_in_group("DebugManager") + #if existing_debug_managers.size() > 0 and existing_debug_managers[0] != self: + #print("Warning: Duplicate DebugManager detected. Removing:", self) + #queue_free() + # return + add_to_group("DebugManager") + + debug_label = Label.new() + debug_label.name = "GlobalDebugLabel" + debug_label.set_custom_minimum_size(Vector2(300, 0)) + debug_label.position = Vector2(10, 10) # Position in the top-left corner + debug_label.autowrap_mode = TextServer.AUTOWRAP_WORD # Enable word wrapping + debug_label.horizontal_alignment = HorizontalAlignment.HORIZONTAL_ALIGNMENT_LEFT + debug_label.vertical_alignment = VerticalAlignment.VERTICAL_ALIGNMENT_TOP + debug_label.visible = global_debug_visible # Initially hidden + add_child(debug_label) + print("Global debug label initialized:", debug_label) + +func _input(event: InputEvent) -> void: + # Toggle global debug + if event.is_action_pressed("toggle_global_debug"): + toggle_global_debug() + + # Toggle instance debug + if event.is_action_pressed("toggle_instance_debug"): + toggle_instance_debug() + +func _process(delta: float): + if global_debug_visible: + update_timer += delta + if update_timer >= update_interval: + update_timer = 0.0 + update_global_debug_info() + +func toggle_global_debug(): + global_debug_visible = not global_debug_visible + debug_label.visible = global_debug_visible + if global_debug_visible: + update_global_debug_info() + print("Toggled global debug to:", global_debug_visible) + if debug_console: + debug_console.log_message("Toggled global debug to: %s" %[global_debug_visible], Color(1, 0, 0)) + +func toggle_instance_debug(): + instance_debug_visible = not instance_debug_visible + emit_signal("toggle_instance_debug_signal", instance_debug_visible) + print("Toggling instance debug to:", instance_debug_visible) + +func update_global_debug_info(): + var info = [] + info.append("=== GLOBAL DEBUG ===") + info.append("FPS: %s" % Engine.get_frames_per_second()) + info.append("Node Count: %s" % get_tree().get_node_count()) + info.append("Collectibles: %s" % get_tree().get_nodes_in_group("collectibles").size()) + info.append("Spaceships: %s" % get_tree().get_nodes_in_group("spaceships").size()) + info.append("Asteroids: %s" % get_tree().get_nodes_in_group("asteroids").size()) + debug_label.text = String("\n").join(info) diff --git a/DebugOverlay.gd b/DebugOverlay.gd new file mode 100644 index 0000000..8f31c09 --- /dev/null +++ b/DebugOverlay.gd @@ -0,0 +1,74 @@ +extends CanvasLayer + +@export var debug_spacing: int = 10 # Spacing between debug labels +var debug_labels: Dictionary = {} +var instance_debug_visible: bool = false + +func _ready(): + # Connect the signal from DebugManager + var debug_manager = get_node("/root/Main/DebugManager") + if debug_manager: + debug_manager.connect("toggle_instance_debug_signal", Callable(self, "_on_toggle_instance_debug")) + print("Connected to toggle_instance_debug_signal from DebugManager.") + else: + print("Error: DebugManager not found!") + + # Connect existing debuggable nodes + for node in get_tree().get_nodes_in_group("debuggable"): + _connect_debuggable_node(node) + + # Listen for new debuggable nodes + get_tree().connect("node_added", Callable(self, "_on_node_added")) + +func _process(delta: float): + # Update label positions to match their nodes + for node_path in debug_labels.keys(): + var label = debug_labels[node_path] + var node = null + + if get_node_or_null(node_path): + node = get_node(node_path) + + # Update the label's position if the node exists + if label and node: + label.global_position = node.global_position + Vector2(100, -70) # Position the label + + +func _on_toggle_instance_debug(debug_visible: bool): + instance_debug_visible = debug_visible + print("Received toggle_instance_debug_signal. Setting instance debug visibility to:", instance_debug_visible) + for label in debug_labels.values(): + if label: + label.visible = instance_debug_visible + +func _on_node_added(node: Node): + if node.is_in_group("debuggable"): + _connect_debuggable_node(node) + +func _connect_debuggable_node(node: Node): + var node_path = str(node.get_path()) + + if not debug_labels.has(node_path): + var label = Label.new() + label.visible = instance_debug_visible + label.autowrap_mode = TextServer.AUTOWRAP_OFF + label.horizontal_alignment = HorizontalAlignment.HORIZONTAL_ALIGNMENT_LEFT + label.vertical_alignment = VerticalAlignment.VERTICAL_ALIGNMENT_TOP + label.size_flags_horizontal = Control.SIZE_EXPAND_FILL + label.custom_minimum_size = Vector2(400, 0) + add_child(label) + debug_labels[node_path] = label + print("Created label for node:", node_path) + + # Connect the debug update signal + if not node.is_connected("debug_updated", Callable(self, "_on_debug_updated")): + node.connect("debug_updated", Callable(self, "_on_debug_updated")) + print("Connected debug_updated signal for:", node_path) + +func _on_debug_updated(node: Node, debug_text: String): + var node_path = str(node.get_path()) + if debug_labels.has(node_path): + var label = debug_labels[node_path] + if label: + label.text = debug_text + label.visible = instance_debug_visible diff --git a/Debuggable.gd b/Debuggable.gd new file mode 100644 index 0000000..a090e2c --- /dev/null +++ b/Debuggable.gd @@ -0,0 +1,43 @@ +extends Node2D + +signal debug_updated(node: Node, debug_text: String) + +@export var update_interval: float = 1.0 # Throttle debug updates +@export var default_debug_text: String = "No debug info available." # Default text +var update_timer: float = 0.0 + +# Store debug data providers +var debug_providers: Array = [] + +func _ready(): + if not is_in_group("debuggable"): + add_to_group("debuggable") + emit_debug_info() + +# Register a system or component as a debug provider +func register_debug_provider(provider: Callable): + if provider not in debug_providers: + debug_providers.append(provider) + print("Registered debug provider:", provider) + +# Update debug information from all providers +func update_debug(): + var debug_info = [] + debug_info.append("=== Node Debug Info ===") + + for provider in debug_providers: + if provider.is_valid(): + var data = provider.call() + for key in data.keys(): + debug_info.append("%s: %s" % [key.capitalize(), data[key]]) + + emit_signal("debug_updated", self, String("\n").join(debug_info)) + +func _process(delta: float): + update_timer += delta + if update_timer >= update_interval: + update_timer = 0.0 + update_debug() + +func emit_debug_info(): + emit_signal("debug_updated", self, default_debug_text) diff --git a/collectible.gd b/collectible.gd new file mode 100644 index 0000000..ef744bb --- /dev/null +++ b/collectible.gd @@ -0,0 +1,11 @@ +class_name Collectible +extends Area2D + +@export var item_type: String = "default_item" +@export var value: int = 1 + +signal collected(item_type: String, value: int, collector: Node, collectible: Node) + +func _on_body_entered(body): + if body.is_in_group("spaceships"): + emit_signal("collected", item_type, value, body, self) # Include a reference to itself diff --git a/debug_console.gd b/debug_console.gd new file mode 100644 index 0000000..07311ba --- /dev/null +++ b/debug_console.gd @@ -0,0 +1,22 @@ +extends RichTextLabel + +@export var max_lines: int = 10 + +func log_message(message: String, color: Color = Color(1, 1)): + bbcode_enabled = true + + var color_code = "[color=%s]" % color.to_html() + var formatted_message = "%s%s[/color]" % [color_code, message] + + append_text(formatted_message + "\n") + + scroll_to_line(get_line_count()) + + if get_line_count() > max_lines: + trim_console() + +func trim_console(): + var lines = get_text().split("\n") + while lines.size() > max_lines: + lines.pop_front() + text = "\n".join(lines) diff --git a/main.gd b/main.gd index 11a3036..420aa58 100644 --- a/main.gd +++ b/main.gd @@ -1,36 +1,38 @@ extends Node +signal collectible_spawned(collectible: Node) + +@export var debug_spawn_distance: float = 500.0 + func _init() -> void: + # Initialize subsystems var node = WeaponsSystem.new() node.set_name("WeaponsSystem") add_child(node) - + node = DefaultEventBus.new() node.set_name("MainEventBus") add_child(node) - + node = EventScope.new() node.set_name("InputEventScope") add_child(node) - + node = EventScope.new() node.set_name("DamageEventScope") add_child(node) - + node = EventScope.new() node.set_name("DestroyedEventScope") add_child(node) - - # Instantiate and add the RewardSpawner + node = RewardSpawner.new() node.set_name("RewardSpawner") add_child(node) -# Called when the node enters the scene tree for the first time. func _ready() -> void: - pass # Replace with function body. + print("Main node ready.") -# Called every frame. 'delta' is the elapsed time since the previous frame. func _process(_delta: float) -> void: var actions = [ "ui_fire", @@ -38,43 +40,34 @@ func _process(_delta: float) -> void: "ui_down", "ui_left", "ui_right", - ] + ] for action in actions: if Input.is_action_pressed(action): - get_node("/root/Main/MainEventBus").publish(get_node("/root/Main/InputEventScope"), KeyboardInputEvent.new(action, true)) + get_node("/root/Main/MainEventBus").publish( + get_node("/root/Main/InputEventScope"), + KeyboardInputEvent.new(action, true) + ) elif Input.is_action_just_released(action): - get_node("/root/Main/MainEventBus").publish(get_node("/root/Main/InputEventScope"), KeyboardInputEvent.new(action, false)) - pass + get_node("/root/Main/MainEventBus").publish( + get_node("/root/Main/InputEventScope"), + KeyboardInputEvent.new(action, false) + ) -# Spawn function and random position logic are placed here -func spawn_asteroid(): - var asteroid_scene = preload("res://asteroid.tscn") - var asteroid_instance = asteroid_scene.instantiate() +func get_debug_spawn_position() -> Vector2: + var player = get_node_or_null("spaceship") + if player: + var screen_size = get_viewport().size + var spawn_position = player.global_position + Vector2( + randf_range(-debug_spawn_distance, debug_spawn_distance), + randf_range(-debug_spawn_distance, debug_spawn_distance) + ) - # Generate random positions within a defined area - var spawn_position = get_random_position() - - # Check that it's not too close to the player or other asteroids - while !is_valid_position(spawn_position): - spawn_position = get_random_position() - - asteroid_instance.global_position = spawn_position - add_child(asteroid_instance) - -func get_random_position() -> Vector2: - var screen_size = get_viewport().size - return Vector2(randf_range(0, screen_size.x), randf_range(0, screen_size.y)) - -func is_valid_position(spawn_position: Vector2) -> bool: - var player = get_node("spaceship") # Adjust the path to your player node - var player_distance = player.global_position.distance_to(spawn_position) - - if player_distance < 200: - return false - - var asteroids = get_tree().get_nodes_in_group("asteroids") - for asteroid in asteroids: - if asteroid.global_position.distance_to(spawn_position) < 150: - return false - - return true + spawn_position.x = clamp(spawn_position.x, 0, screen_size.x) + spawn_position.y = clamp(spawn_position.y, 0, screen_size.y) + return spawn_position + else: + print("Warning: Player node not found. Using random position.") + return Vector2( + randf_range(0, get_viewport().size.x), + randf_range(0, get_viewport().size.y) + ) diff --git a/main.tscn b/main.tscn index 1bb12c9..b81f5a7 100644 --- a/main.tscn +++ b/main.tscn @@ -1,8 +1,13 @@ -[gd_scene load_steps=5 format=3 uid="uid://8ocp10j32f62"] +[gd_scene load_steps=10 format=3 uid="uid://8ocp10j32f62"] [ext_resource type="Script" path="res://main.gd" id="1_eedai"] [ext_resource type="Texture2D" uid="uid://y6phkg4twpdm" path="res://images/bg_space_seamless.png" id="1_rpyi5"] [ext_resource type="PackedScene" uid="uid://dej58eek7fudd" path="res://spaceship.tscn" id="3_h8rrl"] +[ext_resource type="Script" path="res://spawn_button.gd" id="4_ixico"] +[ext_resource type="Script" path="res://DebugOverlay.gd" id="5_h77fc"] +[ext_resource type="Script" path="res://DebugManager.gd" id="6_2knji"] +[ext_resource type="Script" path="res://remove_cheese_button.gd" id="8_qgjgg"] +[ext_resource type="Script" path="res://debug_console.gd" id="9_13jbc"] [ext_resource type="Script" path="res://spawn_asteroid_button.gd" id="9_21dg0"] [node name="Main" type="Node2D"] @@ -14,8 +19,6 @@ scale = Vector2(2, 2) texture = ExtResource("1_rpyi5") metadata/_edit_lock_ = true -[node name="spaceship" parent="." instance=ExtResource("3_h8rrl")] - [node name="SpawnAsteroidButton" type="Button" parent="."] offset_left = 72.0 offset_top = 993.0 @@ -23,3 +26,38 @@ offset_right = 249.0 offset_bottom = 1049.0 text = "SPAWN ASTEROID" script = ExtResource("9_21dg0") + +[node name="SpawnCheeseButton" type="Button" parent="."] +offset_left = 264.0 +offset_top = 992.0 +offset_right = 445.0 +offset_bottom = 1049.0 +text = "SPAWN CHEESE" +script = ExtResource("4_ixico") + +[node name="Remove1CheeseButton" type="Button" parent="."] +offset_left = 461.0 +offset_top = 992.0 +offset_right = 808.0 +offset_bottom = 1050.0 +text = "REMOVE 1 CHEESE FROM CARGO" +script = ExtResource("8_qgjgg") + +[node name="spaceship" parent="." instance=ExtResource("3_h8rrl")] + +[node name="DebugManager" type="CanvasLayer" parent="."] +script = ExtResource("6_2knji") + +[node name="DebugOverlay" type="CanvasLayer" parent="."] +script = ExtResource("5_h77fc") + +[node name="DebugConsole" type="RichTextLabel" parent="."] +offset_left = 1015.0 +offset_top = 834.0 +offset_right = 1719.0 +offset_bottom = 1051.0 +focus_mode = 2 +bbcode_enabled = true +scroll_following = true +selection_enabled = true +script = ExtResource("9_13jbc") diff --git a/project.godot b/project.godot index 06caccc..28c28e7 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,10 @@ run/main_scene="res://main.tscn" config/features=PackedStringArray("4.3", "Forward Plus") config/icon="res://icon.svg" +[autoload] + +DebugManager="*res://DebugManager.gd" + [display] window/size/viewport_width=1920 @@ -32,6 +36,36 @@ fire_weapon={ "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(133, 15),"global_position":Vector2(142, 61),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) ] } +toggle_global_debug={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194333,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +toggle_instance_debug={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194334,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +thrust_forward={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +] +} +thrust_reverse={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +] +} +thrust_left={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +] +} +thrust_right={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +] +} [layer_names] diff --git a/remove_cheese_button.gd b/remove_cheese_button.gd new file mode 100644 index 0000000..2daf3e2 --- /dev/null +++ b/remove_cheese_button.gd @@ -0,0 +1,21 @@ +extends Button + +@onready var cargo_system = get_node("/root/Main/spaceship/CargoSystem") +@onready var debug_console = get_node("/root/Main/DebugConsole") + +@export var item_to_remove: String = "cheese" +@export var quantity_to_remove: int = 1 + +func _ready() -> void: + connect("pressed", Callable(self, "_on_button_pressed")) + +func _on_button_pressed(): + if cargo_system: + if (cargo_system.remove_item(item_to_remove, quantity_to_remove)): + if debug_console: + debug_console.log_message("Removed: %d x %s from cargo." %[quantity_to_remove, item_to_remove], Color(1, 0, 0)) + print("Removed: ", quantity_to_remove,"x ", item_to_remove, " from cargo.") + else: + print("Failed to remove item. Item not found or insufficient quantity.") + else: + print("Error: Cargo System not found.") diff --git a/reward_spawner.gd b/reward_spawner.gd index 57c3e3c..89b2bc7 100644 --- a/reward_spawner.gd +++ b/reward_spawner.gd @@ -1,20 +1,48 @@ class_name RewardSpawner extends Node +@onready var debug_console = get_node("/root/Main/DebugConsole") +@export var reward_table: Dictionary = { + "asteroid": preload("res://src/collectibles/cheese.tscn"), + "debug_asteroid": preload("res://asteroid.tscn") +} +signal collectible_spawned(collectible: Node) var event_bus: EventBus func _ready(): event_bus = get_node("/root/Main/MainEventBus") - event_bus.subscribe_to(get_node("/root/Main/DestroyedEventScope"), "DestroyedEvent", Callable(self, "on_destroyed")) + event_bus.subscribe_to( + get_node("/root/Main/DestroyedEventScope"), + "DestroyedEvent", + Callable(self, "on_destroyed") + ) func on_destroyed(event: DestroyedEvent): - if event.object_type == "asteroid": - spawn_cheese(event.position) + if event.object_type in reward_table: + spawn_reward(event.position, reward_table[event.object_type]) -func spawn_cheese(position: Vector2): - var cheese_scene = load("res://cheese.tscn") - var cheese_instance = cheese_scene.instantiate() - - cheese_instance.global_position = position + Vector2(randf() * 50 - 25, randf() * 50 - 25) - - get_parent().add_child(cheese_instance) +func spawn_reward(position: Vector2, reward_scene: PackedScene): + var reward_instance = reward_scene.instantiate() + reward_instance.global_position = position + Vector2( + randf() * 50 - 25, + randf() * 50 - 25 + ) + + if reward_scene == reward_table.get("debug_asteroid"): + get_parent().add_child(reward_instance) + print("Debug asteroid detected.") + if debug_console: + debug_console.log_message("1x Debug asteroid was spawned...", Color(1, 0, 0)) + return + + reward_instance.add_to_group("collectibles") + get_parent().add_child(reward_instance) + emit_signal("collectible_spawned", reward_instance) + if debug_console: + debug_console.log_message("1x Debug cheese was spawned...", Color(1, 0, 0)) + +func spawn_reward_directly(object_type: String, position: Vector2): + if object_type in reward_table: + spawn_reward(position, reward_table[object_type]) + else: + print("Error: Object type not in reward table:", object_type) diff --git a/spaceship.tscn b/spaceship.tscn index 3196e41..59f4d95 100644 --- a/spaceship.tscn +++ b/spaceship.tscn @@ -1,9 +1,11 @@ -[gd_scene load_steps=6 format=3 uid="uid://dej58eek7fudd"] +[gd_scene load_steps=8 format=3 uid="uid://dej58eek7fudd"] -[ext_resource type="Script" path="res://spaceship.gd" id="1_bwnho"] +[ext_resource type="Script" path="res://src/vessels/hulls/base_hull.gd" id="1_1b1aj"] [ext_resource type="PackedScene" uid="uid://kke1bgv1bvht" path="res://src/vessels/weapons/beams/mining/mining_beam_turret.tscn" id="2_4ub4i"] +[ext_resource type="Script" path="res://src/vessels/components/cargo/cargo_system.gd" id="2_yptue"] [ext_resource type="Texture2D" uid="uid://cran7fr1i2qou" path="res://images/spaceship-placeholder.png" id="3_xxo2y"] [ext_resource type="Script" path="res://src/vessels/systems/weapons_system.gd" id="4_w4ss2"] +[ext_resource type="Script" path="res://Debuggable.gd" id="6_01fr8"] [sub_resource type="CapsuleShape2D" id="CapsuleShape2D_3vtwu"] radius = 48.0 @@ -13,7 +15,10 @@ height = 102.0 position = Vector2(956, 623) collision_layer = 2 motion_mode = 1 -script = ExtResource("1_bwnho") +script = ExtResource("1_1b1aj") + +[node name="CargoSystem" type="Node" parent="."] +script = ExtResource("2_yptue") [node name="WeaponsSystem" type="Node" parent="."] script = ExtResource("4_w4ss2") @@ -28,3 +33,6 @@ texture = ExtResource("3_xxo2y") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] shape = SubResource("CapsuleShape2D_3vtwu") + +[node name="Debuggable" type="Node2D" parent="."] +script = ExtResource("6_01fr8") diff --git a/spawn_asteroid_button.gd b/spawn_asteroid_button.gd index 5a489df..7ad90bb 100644 --- a/spawn_asteroid_button.gd +++ b/spawn_asteroid_button.gd @@ -1,29 +1,35 @@ extends Button -@onready var main_script = get_node("/root/Main") +@onready var reward_spawner = get_node("/root/Main/RewardSpawner") func _ready(): - # Connect the "pressed" signal to a custom function in this script - self.pressed.connect(self.on_button_pressed) + pressed.connect(on_button_pressed) -# Handle what happens when the button is pressed func on_button_pressed(): - # Call the main script's spawn_asteroid function - main_script.spawn_asteroid() + if reward_spawner: + var spawn_position = get_debug_spawn_position() + reward_spawner.spawn_reward_directly("debug_asteroid", spawn_position) + else: + print("Error: RewardSpawner not found.") - # Disable the button temporarily to prevent immediate re-trigger + disable_temporarily() + +func disable_temporarily(): self.disabled = true - self.release_focus() - - # Start a timer to re-enable the button after 0.2 seconds var timer = Timer.new() - timer.wait_time = 0.2 + timer.wait_time = 0.1 timer.one_shot = true timer.timeout.connect(self.on_timeout) add_child(timer) timer.start() -# Re-enable the button when the timer times out func on_timeout(): self.disabled = false + +func get_debug_spawn_position() -> Vector2: + var player = get_node_or_null("/root/Main/spaceship") + if player: + return player.global_position + Vector2(randf_range(-500, 500), randf_range(-500, 500)) + else: + return Vector2(randf_range(0, get_viewport().size.x), randf_range(0, get_viewport().size.y)) diff --git a/spawn_button.gd b/spawn_button.gd new file mode 100644 index 0000000..9ebe944 --- /dev/null +++ b/spawn_button.gd @@ -0,0 +1,35 @@ +extends Button + +@onready var reward_spawner = get_node("/root/Main/RewardSpawner") + +func _ready(): + pressed.connect(on_button_pressed) + +func on_button_pressed(): + if reward_spawner: + var spawn_position = get_debug_spawn_position() + reward_spawner.spawn_reward_directly("asteroid", spawn_position) + else: + print("Error: RewardSpawner not found.") + + disable_temporarily() + +func disable_temporarily(): + self.disabled = true + self.release_focus() + var timer = Timer.new() + timer.wait_time = 0.1 + timer.one_shot = true + timer.timeout.connect(self.on_timeout) + add_child(timer) + timer.start() + +func on_timeout(): + self.disabled = false + +func get_debug_spawn_position() -> Vector2: + var player = get_node_or_null("/root/Main/spaceship") + if player: + return player.global_position + Vector2(randf_range(-500, 500), randf_range(-500, 500)) + else: + return Vector2(randf_range(0, get_viewport().size.x), randf_range(0, get_viewport().size.y)) diff --git a/src/collectibles/cheese.tscn b/src/collectibles/cheese.tscn new file mode 100644 index 0000000..d13d3a2 --- /dev/null +++ b/src/collectibles/cheese.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://ceu0at4n3s1vm"] + +[ext_resource type="Script" path="res://collectible.gd" id="1_p4ybi"] +[ext_resource type="Texture2D" uid="uid://djwn5ruf1wln0" path="res://images/protocheese.png" id="2_7jmpr"] + +[node name="cheese" type="Area2D"] +position = Vector2(300, 337) +scale = Vector2(2, 2) +collision_mask = 3 +script = ExtResource("1_p4ybi") +item_type = "cheese" +value = 10 + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."] +polygon = PackedVector2Array(3, 17.5, 18.5, 0, 13.5, -20.5, -16.5, -7, -16, 13) + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("2_7jmpr") + +[connection signal="body_entered" from="." to="." method="_on_body_entered"] diff --git a/src/vessels/components/cargo/cargo_system.gd b/src/vessels/components/cargo/cargo_system.gd new file mode 100644 index 0000000..0ebf050 --- /dev/null +++ b/src/vessels/components/cargo/cargo_system.gd @@ -0,0 +1,62 @@ +class_name CargoSystem +extends Node + +@export var max_weight: float = 100.0 +var current_weight: float = 0.0 +var items: Dictionary = {} +var item_weights: Dictionary = {} + +@warning_ignore("unused_signal") +signal cargo_full +@warning_ignore("unused_signal") +signal item_added(item_type: String, quantity: int) +@warning_ignore("unused_signal") +signal item_removed(item_type: String, quantity: int) +@warning_ignore("unused_signal") +signal item_rejected(item_type: String, reason: String) + +@warning_ignore("unused_parameter") +func can_add_item(item_type: String, weight: float, quantity: int = 1) -> bool: + # Centralized logic for checking cargo capacity + return current_weight + weight * quantity <= max_weight + +func add_item(item_type: String, weight: float, quantity: int = 1) -> bool: + if not can_add_item(item_type, weight, quantity): + emit_signal("item_rejected", item_type, "cargo_full") + return false + + items[item_type] = items.get(item_type, 0) + quantity + item_weights[item_type] = weight + current_weight += weight * quantity + emit_signal("item_added", item_type, quantity) + print("Added: ", quantity, "x ", item_type, " to cargo") + return true + +func remove_item(item_type: String, quantity: int = 1) -> bool: + if not items.has(item_type) or items[item_type] < quantity: + return false # Fail early if the item doesn't exist or quantity is insufficient + + var weight = item_weights.get(item_type, 0) + items[item_type] -= quantity + if items[item_type] <= 0: + items.erase(item_type) + item_weights.erase(item_type) + + current_weight = max(current_weight - weight * quantity, 0) + emit_signal("item_removed", item_type, quantity) + return true + +func list_items() -> String: + var formatted_items = [] + for item in items.keys(): + formatted_items.append("%s: %d" % [item, items[item]]) + return ", ".join(formatted_items) + +func get_remaining_capacity() -> float: + return max_weight - current_weight + +func get_debug_data() -> Dictionary: + return { + "cargo": "%d/%d" % [current_weight, max_weight], + "items": list_items() + } diff --git a/src/vessels/hulls/base_hull.gd b/src/vessels/hulls/base_hull.gd index 076fa5f..70d30c5 100644 --- a/src/vessels/hulls/base_hull.gd +++ b/src/vessels/hulls/base_hull.gd @@ -4,33 +4,97 @@ extends CharacterBody2D @export var max_speed: float = 1500.0 @export var rotation_speed: float = 3.0 @export var friction: float = 0.99 +@onready var cargo_system = $CargoSystem +@onready var laser = $mining_beam_turret/mining_beam +@onready var debuggable = $Debuggable var weapons_system: WeaponsSystem var event_bus: EventBus + func _ready(): - weapons_system = get_node("/root/Main/WeaponsSystem") + weapons_system = get_node("/root/Main/WeaponsSystem") event_bus = get_node("/root/Main/MainEventBus") - event_bus.subscribe_to(get_node("/root/Main/InputEventScope"), "KeyboardInputEvent", Callable(self, "handle_keyboard_input")) - + event_bus.subscribe_to( + get_node("/root/Main/InputEventScope"), + "KeyboardInputEvent", + Callable(self, "handle_keyboard_input") + ) + add_to_group("spaceships") + print("Cargo system initialized with capacity:", cargo_system.max_weight) + if cargo_system: + debuggable.register_debug_provider(Callable(cargo_system, "get_debug_data")) + + if weapons_system: + debuggable.register_debug_provider(Callable(weapons_system, "get_debug_data")) + + # Connect to RewardSpawner for new collectibles + var reward_spawner = get_node("/root/Main/RewardSpawner") + if reward_spawner: + reward_spawner.connect("collectible_spawned", Callable(self, "_on_collectible_spawned")) + else: + print("Warning: RewardSpawner not found.") + + # Connect to existing collectibles + _connect_existing_collectibles() + +func _connect_existing_collectibles(): + # Connect to all existing collectibles in the scene + var collectibles = get_tree().get_nodes_in_group("collectibles") + for collectible in collectibles: + _connect_collectible(collectible) + +func _on_collectible_spawned(collectible: Node): + _connect_collectible(collectible) + +func _connect_collectible(collectible: Node) -> void: + if collectible.is_in_group("collectibles"): + collectible.connect("collected", Callable(self, "_on_collectible_collected")) + else: + print("Warning: Node is not in the 'collectibles' group") + +func _on_collectible_collected(item_type: String, value: int, collector: Node, collectible: Node): + if collector != self: + return + + if not cargo_system.add_item(item_type, float(value)): + show_feedback("Cargo full! Cannot collect " + item_type) + return + + collectible.queue_free() + +func show_feedback(message: String): + # Example: Show a floating message or play a sound + print("[Feedback]: ", message) + # UI feedback here (e.g., a floating label) + +func collect_item(item_type: String, weight: float, quantity: int = 1): + # Directly add items to cargo (used for debugging or special cases) + if not cargo_system: + print("Error: CargoSystem not initialized!") + return + + cargo_system.add_item(item_type, weight, quantity) + func get_spaceship_orientation_vector() -> Vector2: return -global_transform.y func handle_movement(delta: float) -> void: + var thrust = Vector2.ZERO - if Input.is_action_pressed("ui_up"): + if Input.is_action_pressed("thrust_forward"): thrust = Vector2(1, 0).rotated(rotation) * acceleration * delta velocity += thrust - if Input.is_action_pressed("ui_down"): + if Input.is_action_pressed("thrust_reverse"): thrust = Vector2(-1, 0).rotated(rotation) * acceleration * delta velocity += thrust - if Input.is_action_pressed("ui_left"): + if Input.is_action_pressed("thrust_left"): rotation -= rotation_speed * delta - if Input.is_action_pressed("ui_right"): + if Input.is_action_pressed("thrust_right"): rotation += rotation_speed * delta # Clamp velocity and apply friction @@ -40,25 +104,30 @@ func handle_movement(delta: float) -> void: var collision = move_and_collide(velocity * delta) if collision: - print("Collided with: ", collision.get_collider().name) - - var collision_normal = collision.get_normal() - velocity = velocity.slide(collision_normal) - -#func _unhandled_input(event: InputEvent) -> void: -# if not event.is_action("fire_weapon"): -# return - #laser.is_casting = event.is_action_pressed("fire_weapon") -# pass + handle_collision(collision) + +func handle_collision(collision): + # Handle collision response + # print("Collided with: ", collision.get_collider().name) + var collision_normal = collision.get_normal() + velocity = velocity.slide(collision_normal) + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action("fire_weapon"): + laser.is_casting = event.is_action_pressed("fire_weapon") func handle_keyboard_input(event: KeyboardInputEvent): - if( event.action == "ui_fire" ): - if( event.pressed ): - weapons_system.fire_all() - else: - weapons_system.cease_fire_all() - - pass - + if weapons_system: + if event.action == "ui_fire": + if event.pressed: + weapons_system.fire_all() + else: + weapons_system.cease_fire_all() + else: + print("Error: WeaponsSystem not initialized.") + func _process(delta: float) -> void: handle_movement(delta) + + if debuggable: + debuggable.update_debug() diff --git a/src/vessels/systems/weapons_system.gd b/src/vessels/systems/weapons_system.gd index 128519f..bd0b17c 100644 --- a/src/vessels/systems/weapons_system.gd +++ b/src/vessels/systems/weapons_system.gd @@ -6,3 +6,24 @@ func fire_all(): func cease_fire_all(): get_tree().call_group("turrets", "cease_fire") + +func get_debug_data() -> Dictionary: + var turrets = get_tree().get_nodes_in_group("turrets") + var turret_data = [] + + # Gather turret-specific data + for turret in turrets: + var turret_status = { + "name": turret.name, + #"status": turret.is_firing if "is_firing" in turret else "unknown", + #"ammo": turret.get_ammo() if "get_ammo" in turret else "N/A", + #"last_fired": turret.last_fired if "last_fired" in turret else "N/A" + } + turret_data.append(turret_status) + + # System-wide debug info + return { + "turret_count": turrets.size(), + "system_armed": true, # Placeholder for armed status + "turrets": turret_data + }