forked from kanium/starcheese
Added event bus + a few events, for cheese!
This commit is contained in:
parent
c4c7aed6ed
commit
a791d80626
58
asteroid.gd
58
asteroid.gd
@ -1,43 +1,41 @@
|
||||
extends StaticBody2D
|
||||
|
||||
@export var max_health: float = 100.0 # Maximum health for the asteroid
|
||||
@export var max_health: float = 100.0
|
||||
var current_health: float
|
||||
var is_destroyed: bool = false # Track if the asteroid has already been destroyed
|
||||
var is_destroyed: bool = false
|
||||
var event_bus: EventBus
|
||||
|
||||
func _ready():
|
||||
current_health = max_health
|
||||
update_health_label() # Update the health display when the game starts
|
||||
event_bus = get_node("/root/Main/MainEventBus")
|
||||
event_bus.subscribe_to(get_node("/root/Main/DamageEventScope"), "DamageEvent", Callable(self, "on_damage_event"))
|
||||
add_to_group("asteroids")
|
||||
update_health_label()
|
||||
|
||||
# Function to handle taking damage
|
||||
func take_damage(damage: float):
|
||||
if is_destroyed: # Prevent taking damage if already destroyed
|
||||
return
|
||||
func on_damage_event(event: DamageEvent) -> EventResult.ResultType:
|
||||
if event.target != self or is_destroyed:
|
||||
return EventResult.ResultType.KEEP_SUBSCRIPTION
|
||||
|
||||
apply_damage(event.damage_value)
|
||||
|
||||
current_health -= damage # Subtract the damage from current health
|
||||
current_health = max(current_health, 0) # Ensure health doesn't drop below 0
|
||||
update_health_label() # Update the label to reflect new health value
|
||||
|
||||
if current_health <= 0.0:
|
||||
break_apart()
|
||||
|
||||
# Function to handle when the asteroid is destroyed
|
||||
func break_apart():
|
||||
is_destroyed = true # Mark the asteroid as destroyed
|
||||
queue_free() # Remove the asteroid from the scene
|
||||
print("Asteroid mined!")
|
||||
emit_asteroid_destroyed()
|
||||
return EventResult.ResultType.DISPOSE_SUBSCRIPTION
|
||||
|
||||
# Load the Cheese scene
|
||||
var cheese_scene = load("res://Cheese.tscn")
|
||||
|
||||
# Instance the cheese
|
||||
var cheese_instance = cheese_scene.instantiate()
|
||||
|
||||
# Set the position where the cheese should spawn (at the asteroid's position)
|
||||
cheese_instance.global_position = global_position + Vector2(randf() * 50 - 25, randf() * 50 - 25)
|
||||
return EventResult.ResultType.KEEP_SUBSCRIPTION
|
||||
|
||||
# Add the cheese instance to the scene
|
||||
get_parent().add_child(cheese_instance)
|
||||
func apply_damage(damage: float) -> void:
|
||||
current_health = max(current_health - damage, 0)
|
||||
update_health_label()
|
||||
|
||||
# Function to update the health label display
|
||||
func update_health_label():
|
||||
func emit_asteroid_destroyed() -> void:
|
||||
is_destroyed = true
|
||||
queue_free()
|
||||
publish_destroyed_event()
|
||||
|
||||
func publish_destroyed_event() -> void:
|
||||
var destroyed_event = DestroyedEvent.new(self, "asteroid", global_position, "laser")
|
||||
event_bus.publish(get_node("/root/Main/DestroyedEventScope"), destroyed_event)
|
||||
|
||||
func update_health_label() -> void:
|
||||
$AsteroidHealthLabel.text = str(round(current_health)) + " / " + str(max_health)
|
||||
|
||||
31
asteroid.tscn
Normal file
31
asteroid.tscn
Normal file
@ -0,0 +1,31 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://dcq5a8tewppk1"]
|
||||
|
||||
[ext_resource type="Script" path="res://asteroid.gd" id="1_spmxj"]
|
||||
[ext_resource type="Texture2D" uid="uid://buirp1h6onqai" path="res://images/AsteroidBrown.png" id="2_hb7w5"]
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_w58nc"]
|
||||
radius = 86.093
|
||||
|
||||
[node name="asteroid" type="StaticBody2D"]
|
||||
position = Vector2(564, 144)
|
||||
collision_mask = 2
|
||||
script = ExtResource("1_spmxj")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
position = Vector2(1.00006, -3.99998)
|
||||
scale = Vector2(1.2, 1.181)
|
||||
texture = ExtResource("2_hb7w5")
|
||||
|
||||
[node name="AsteroidCollisionPolygon2D" type="CollisionPolygon2D" parent="."]
|
||||
position = Vector2(-519, -164)
|
||||
polygon = PackedVector2Array(548, 101, 613, 169, 597, 210, 548, 240, 462, 221, 431, 184, 434, 133, 497, 90)
|
||||
|
||||
[node name="AsteroidHealthLabel" type="Label" parent="."]
|
||||
offset_left = 105.0
|
||||
offset_top = 38.0
|
||||
offset_right = 181.0
|
||||
offset_bottom = 80.0
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
position = Vector2(0, 2)
|
||||
shape = SubResource("CircleShape2D_w58nc")
|
||||
@ -1,18 +1,12 @@
|
||||
extends Area2D
|
||||
|
||||
|
||||
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
pass
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
pass
|
||||
|
||||
|
||||
func _on_body_entered(body):
|
||||
if body.name == "spaceship":
|
||||
queue_free() # This removes the cheese from the scene
|
||||
print("Cheese collected!") # Replace this with actual game logic
|
||||
|
||||
queue_free()
|
||||
print("Cheese collected!")
|
||||
|
||||
10
damage_event.gd
Normal file
10
damage_event.gd
Normal file
@ -0,0 +1,10 @@
|
||||
class_name DamageEvent
|
||||
extends Event
|
||||
|
||||
var damage_value: float
|
||||
var target: Node
|
||||
|
||||
func _init(_damage_value: float, _target: Node):
|
||||
damage_value = _damage_value
|
||||
target = _target
|
||||
type = "DamageEvent"
|
||||
22
destroyed_event.gd
Normal file
22
destroyed_event.gd
Normal file
@ -0,0 +1,22 @@
|
||||
class_name DestroyedEvent
|
||||
extends Event
|
||||
|
||||
var destroyed_object: Node
|
||||
var object_type: String
|
||||
var position: Vector2
|
||||
var destruction_cause: String
|
||||
|
||||
func _init(_destroyed_object: Node, _object_type: String, _position: Vector2, _destruction_cause: String = ""):
|
||||
destroyed_object = _destroyed_object
|
||||
object_type = _object_type
|
||||
position = _position
|
||||
destruction_cause = _destruction_cause
|
||||
type = "DestroyedEvent"
|
||||
|
||||
func get_event_details() -> Dictionary:
|
||||
return {
|
||||
"object": destroyed_object,
|
||||
"type": object_type,
|
||||
"position": position,
|
||||
"cause": destruction_cause
|
||||
}
|
||||
32
laser.gd
32
laser.gd
@ -7,12 +7,14 @@ extends Node2D
|
||||
var hardpoint = null # Reference to the attached hardpoint
|
||||
var is_firing = false # Track the laser's firing state
|
||||
var current_damage_output: float = 0.0 # Track the current damage output
|
||||
var event_bus: EventBus
|
||||
|
||||
func _ready():
|
||||
# Register the laser to the "weapons" group
|
||||
add_to_group("weapons")
|
||||
# Connect to the correct hardpoint when ready
|
||||
call_deferred("_connect_to_hardpoint")
|
||||
event_bus = get_node("/root/Main/MainEventBus")
|
||||
|
||||
# Initialize LaserLine2D with two points (origin and target)
|
||||
$LaserLine2D.clear_points()
|
||||
@ -32,16 +34,16 @@ func _connect_to_hardpoint():
|
||||
|
||||
func fire():
|
||||
is_firing = true
|
||||
current_damage_output = laser_damage
|
||||
$DamageOutputLabel.text = str(current_damage_output)
|
||||
_process_laser(true)
|
||||
current_damage_output = laser_damage
|
||||
$DamageOutputLabel.text = str(current_damage_output)
|
||||
|
||||
|
||||
func cease_fire():
|
||||
is_firing = false
|
||||
current_damage_output = 0.0
|
||||
$DamageOutputLabel.text = str(current_damage_output)
|
||||
_process_laser(false)
|
||||
current_damage_output = 0.0
|
||||
$DamageOutputLabel.text = str(current_damage_output)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if is_firing:
|
||||
@ -52,27 +54,21 @@ func _process_laser(active: bool):
|
||||
var raycast = $LaserBeam2D
|
||||
raycast.enabled = active
|
||||
|
||||
|
||||
if active:
|
||||
|
||||
raycast.force_raycast_update()
|
||||
|
||||
if raycast.is_colliding():
|
||||
|
||||
var collision_point = raycast.get_collision_point()
|
||||
$LaserLine2D.set_point_position(0, Vector2.ZERO)
|
||||
$LaserLine2D.set_point_position(1, to_local(collision_point))
|
||||
|
||||
$LaserLine2D.set_point_position(0, Vector2.ZERO)
|
||||
$LaserLine2D.set_point_position(1, to_local(collision_point))
|
||||
|
||||
var collider = raycast.get_collider()
|
||||
if collider.has_method("take_damage"):
|
||||
collider.take_damage(laser_damage)
|
||||
if collider:
|
||||
var damage_event = DamageEvent.new(laser_damage, collider)
|
||||
event_bus.publish(get_node("/root/Main/DamageEventScope"), damage_event)
|
||||
else:
|
||||
|
||||
$LaserLine2D.set_point_position(0, Vector2.ZERO)
|
||||
$LaserLine2D.set_point_position(1, Vector2(0, -laser_range))
|
||||
$LaserLine2D.set_point_position(1, Vector2(0, -laser_range))
|
||||
else:
|
||||
|
||||
$LaserLine2D.clear_points()
|
||||
$LaserLine2D.add_point(Vector2.ZERO) # Re-add the origin point
|
||||
$LaserLine2D.add_point(Vector2.ZERO) # Reset target point to origin
|
||||
$LaserLine2D.add_point(Vector2.ZERO)
|
||||
$LaserLine2D.add_point(Vector2.ZERO)
|
||||
|
||||
47
main.gd
47
main.gd
@ -12,12 +12,24 @@ func _init() -> void:
|
||||
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.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
var actions = [
|
||||
@ -33,3 +45,36 @@ func _process(delta: float) -> void:
|
||||
elif Input.is_action_just_released(action):
|
||||
get_node("/root/Main/MainEventBus").publish(get_node("/root/Main/InputEventScope"), KeyboardInputEvent.new(action, false))
|
||||
pass
|
||||
|
||||
# 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()
|
||||
|
||||
# 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
|
||||
|
||||
59
main.tscn
59
main.tscn
@ -1,14 +1,13 @@
|
||||
[gd_scene load_steps=13 format=3 uid="uid://8ocp10j32f62"]
|
||||
[gd_scene load_steps=11 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="Texture2D" uid="uid://cran7fr1i2qou" path="res://images/spaceship-placeholder.png" id="2_f2x66"]
|
||||
[ext_resource type="Script" path="res://spaceship.gd" id="3_ttkgl"]
|
||||
[ext_resource type="Script" path="res://laser.gd" id="4_uhf7q"]
|
||||
[ext_resource type="Script" path="res://asteroid.gd" id="6_n4dsl"]
|
||||
[ext_resource type="Texture2D" uid="uid://bxgw2u7j4b634" path="res://images/laser_turret.png" id="6_qxhyw"]
|
||||
[ext_resource type="Texture2D" uid="uid://buirp1h6onqai" path="res://images/AsteroidBrown.png" id="7_0tjls"]
|
||||
[ext_resource type="Script" path="res://hardpoint.gd" id="7_6cr6a"]
|
||||
[ext_resource type="Script" path="res://spawn_asteroid_button.gd" id="9_21dg0"]
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_3vtwu"]
|
||||
radius = 48.0
|
||||
@ -18,9 +17,6 @@ height = 102.0
|
||||
offsets = PackedFloat32Array(0.961735, 1)
|
||||
colors = PackedColorArray(1, 1, 0, 1, 1, 1, 1, 0.137255)
|
||||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_w58nc"]
|
||||
radius = 88.0057
|
||||
|
||||
[node name="Main" type="Node2D"]
|
||||
script = ExtResource("1_eedai")
|
||||
|
||||
@ -30,7 +26,7 @@ scale = Vector2(2, 2)
|
||||
texture = ExtResource("1_rpyi5")
|
||||
|
||||
[node name="spaceship" type="CharacterBody2D" parent="."]
|
||||
position = Vector2(908, 835)
|
||||
position = Vector2(956, 623)
|
||||
collision_layer = 2
|
||||
motion_mode = 1
|
||||
script = ExtResource("3_ttkgl")
|
||||
@ -75,45 +71,10 @@ offset_bottom = -20.0
|
||||
position = Vector2(0, -46)
|
||||
script = ExtResource("7_6cr6a")
|
||||
|
||||
[node name="asteroid" type="StaticBody2D" parent="."]
|
||||
position = Vector2(564, 144)
|
||||
collision_mask = 2
|
||||
script = ExtResource("6_n4dsl")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="asteroid"]
|
||||
position = Vector2(1.00006, -3.99998)
|
||||
scale = Vector2(1.2, 1.181)
|
||||
texture = ExtResource("7_0tjls")
|
||||
|
||||
[node name="AsteroidCollisionPolygon2D" type="CollisionPolygon2D" parent="asteroid"]
|
||||
position = Vector2(-519, -164)
|
||||
polygon = PackedVector2Array(548, 101, 613, 169, 597, 210, 548, 240, 462, 221, 431, 184, 434, 133, 497, 90)
|
||||
|
||||
[node name="AsteroidHealthLabel" type="Label" parent="asteroid"]
|
||||
offset_left = 105.0
|
||||
offset_top = 38.0
|
||||
offset_right = 181.0
|
||||
offset_bottom = 80.0
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="asteroid"]
|
||||
position = Vector2(-2, 1)
|
||||
shape = SubResource("CircleShape2D_w58nc")
|
||||
|
||||
[node name="asteroid2" type="StaticBody2D" parent="."]
|
||||
position = Vector2(1405, 413)
|
||||
script = ExtResource("6_n4dsl")
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="asteroid2"]
|
||||
position = Vector2(1.00006, -3.99998)
|
||||
scale = Vector2(1.2, 1.181)
|
||||
texture = ExtResource("7_0tjls")
|
||||
|
||||
[node name="AsteroidCollisionPolygon2D" type="CollisionPolygon2D" parent="asteroid2"]
|
||||
position = Vector2(-519, -164)
|
||||
polygon = PackedVector2Array(548, 101, 613, 169, 597, 210, 548, 240, 462, 221, 431, 184, 434, 133, 497, 90)
|
||||
|
||||
[node name="AsteroidHealthLabel" type="Label" parent="asteroid2"]
|
||||
offset_left = 105.0
|
||||
offset_top = 38.0
|
||||
offset_right = 181.0
|
||||
offset_bottom = 80.0
|
||||
[node name="SpawnAsteroidButton" type="Button" parent="."]
|
||||
offset_left = 72.0
|
||||
offset_top = 993.0
|
||||
offset_right = 249.0
|
||||
offset_bottom = 1049.0
|
||||
text = "SPAWN ASTEROID"
|
||||
script = ExtResource("9_21dg0")
|
||||
|
||||
@ -24,7 +24,7 @@ window/size/viewport_height=1080
|
||||
|
||||
ui_fire={
|
||||
"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":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
||||
"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":4194326,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
20
reward_spawner.gd
Normal file
20
reward_spawner.gd
Normal file
@ -0,0 +1,20 @@
|
||||
class_name RewardSpawner
|
||||
extends 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"))
|
||||
|
||||
func on_destroyed(event: DestroyedEvent):
|
||||
if event.object_type == "asteroid":
|
||||
spawn_cheese(event.position)
|
||||
|
||||
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)
|
||||
29
spawn_asteroid_button.gd
Normal file
29
spawn_asteroid_button.gd
Normal file
@ -0,0 +1,29 @@
|
||||
extends Button
|
||||
|
||||
@onready var main_script = get_node("/root/Main")
|
||||
|
||||
func _ready():
|
||||
# Connect the "pressed" signal to a custom function in this script
|
||||
self.pressed.connect(self.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()
|
||||
|
||||
# Disable the button temporarily to prevent immediate re-trigger
|
||||
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.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
|
||||
Loading…
x
Reference in New Issue
Block a user