diff --git a/scenes/test_scene_haze.tscn b/scenes/test_scene_haze.tscn index 9a4d7de..cf636f8 100644 --- a/scenes/test_scene_haze.tscn +++ b/scenes/test_scene_haze.tscn @@ -1,74 +1,47 @@ -[gd_scene load_steps=23 format=3 uid="uid://dxsp66qpvm65b"] +[gd_scene load_steps=15 format=3 uid="uid://dxsp66qpvm65b"] [ext_resource type="Texture2D" uid="uid://c50bfqprpitev" path="res://icon.svg" id="1_g7g4h"] [ext_resource type="PackedScene" uid="uid://c714s5d7d5765" path="res://objects/player/player.tscn" id="2_j8ivh"] [ext_resource type="Script" uid="uid://cj2fj7snls8aa" path="res://systems/bullets/bullet_set.gd" id="3_cf1so"] -[ext_resource type="Script" uid="uid://mivkgn34ox41" path="res://systems/bullets/actions/bullet_action.gd" id="4_1xo0o"] -[ext_resource type="Script" uid="uid://pn143vuxc7wp" path="res://systems/bullets/actions/despawn_action.gd" id="4_4oowd"] +[ext_resource type="Script" uid="uid://pn143vuxc7wp" path="res://systems/bullets/bullet_actions/despawn_action.gd" id="4_4oowd"] [ext_resource type="Texture2D" uid="uid://du7gh3nk66mpo" path="res://graphics/bullets/normal_bullet/bullet_1.png" id="4_hlyn7"] -[ext_resource type="Script" uid="uid://dntp60my5f65m" path="res://systems/bullets/behaviors/simple_linear_behavior.gd" id="4_t1bs8"] -[ext_resource type="Script" uid="uid://d238qii8i2byl" path="res://systems/bullets/spawn_patterns/line_pattern.gd" id="5_cf1so"] +[ext_resource type="Script" uid="uid://dntp60my5f65m" path="res://systems/bullets/bullet_behaviors/simple_linear_behavior.gd" id="4_t1bs8"] [ext_resource type="Script" uid="uid://vus1a0flwtnm" path="res://systems/bullets/bullet_preset.gd" id="6_sle1e"] [ext_resource type="Script" uid="uid://dtuc6qerbfset" path="res://systems/bullets/spawn_patterns/ring_pattern.gd" id="6_uu3sg"] -[ext_resource type="Script" uid="uid://oug6n1t6tnor" path="res://systems/bullets/actions/spawn_set_action.gd" id="8_377ep"] -[ext_resource type="Texture2D" uid="uid://bqn0smy2jio3y" path="res://graphics/bullets/normal_bullet/bullet_3.png" id="8_uu3sg"] -[ext_resource type="Script" uid="uid://mair8nsxn7lp" path="res://systems/bullets/actions/multi_action.gd" id="10_etmxr"] +[ext_resource type="Script" uid="uid://5scjonwmg8tw" path="res://systems/bullets/set_behaviors/rotation_set_behavior.gd" id="7_t1bs8"] -[sub_resource type="Resource" id="Resource_rbgfd"] -script = ExtResource("4_t1bs8") -acceleration = 64.0 -metadata/_custom_type_script = "uid://dntp60my5f65m" - -[sub_resource type="Resource" id="Resource_xksnv"] -script = ExtResource("6_uu3sg") -bullet_count = 9 -metadata/_custom_type_script = "uid://dtuc6qerbfset" - -[sub_resource type="Resource" id="Resource_i8wif"] -script = ExtResource("6_sle1e") -behavior = SubResource("Resource_rbgfd") -pattern = SubResource("Resource_xksnv") -textures = Array[Texture2D]([ExtResource("8_uu3sg")]) -hitbox_size = Vector2i(6, 6) -metadata/_custom_type_script = "uid://vus1a0flwtnm" - -[sub_resource type="Resource" id="Resource_g0u1t"] -script = ExtResource("8_377ep") -preset = SubResource("Resource_i8wif") -metadata/_custom_type_script = "uid://oug6n1t6tnor" - -[sub_resource type="Resource" id="Resource_2fp3d"] +[sub_resource type="Resource" id="Resource_sle1e"] script = ExtResource("4_4oowd") metadata/_custom_type_script = "uid://pn143vuxc7wp" -[sub_resource type="Resource" id="Resource_ufsqg"] -script = ExtResource("10_etmxr") -actions = Array[ExtResource("4_1xo0o")]([SubResource("Resource_g0u1t"), SubResource("Resource_2fp3d")]) -metadata/_custom_type_script = "uid://mair8nsxn7lp" - [sub_resource type="Resource" id="Resource_c0i5a"] script = ExtResource("4_t1bs8") initial_speed = 128.0 acceleration = -64.0 min_speed = 0.0 -action_speed_clamped = SubResource("Resource_ufsqg") +action_speed_clamped = SubResource("Resource_sle1e") metadata/_custom_type_script = "uid://dntp60my5f65m" -[sub_resource type="Resource" id="Resource_t1bs8"] -script = ExtResource("5_cf1so") -bullet_count = 1 -line_width = 128.0 -line_normal = Vector2(0.70710677, -0.70710677) -metadata/_custom_type_script = "uid://d238qii8i2byl" +[sub_resource type="Resource" id="Resource_cf1so"] +script = ExtResource("6_uu3sg") +bullet_count = 5 +metadata/_custom_type_script = "uid://dtuc6qerbfset" + +[sub_resource type="Resource" id="Resource_4oowd"] +script = ExtResource("7_t1bs8") +rotation_speed = -1.5707963267948966 +spawn_rotation_speed = 6.283185307179586 +metadata/_custom_type_script = "uid://5scjonwmg8tw" [sub_resource type="Resource" id="Resource_uu3sg"] script = ExtResource("6_sle1e") behavior = SubResource("Resource_c0i5a") -pattern = SubResource("Resource_t1bs8") textures = Array[Texture2D]([ExtResource("4_hlyn7")]) hitbox_size = Vector2i(6, 6) +pattern = SubResource("Resource_cf1so") rounds = 100000 -round_delay = 1.0 +round_delay = 0.5 +set_behavior = SubResource("Resource_4oowd") metadata/_custom_type_script = "uid://vus1a0flwtnm" [node name="TestScene" type="Node"] diff --git a/systems/bullets/behaviors/bullet_behavior.gd b/systems/bullets/behaviors/bullet_behavior.gd deleted file mode 100644 index 1caf3b2..0000000 --- a/systems/bullets/behaviors/bullet_behavior.gd +++ /dev/null @@ -1,32 +0,0 @@ -@abstract -class_name BulletBehavior -extends Resource - - -## Performs behavior-specific initialization for a [Bullet]. -func init_bullet(bullet: Bullet) -> void: - bullet.recycled.connect(deinit_bullet.bind(bullet), CONNECT_ONE_SHOT) - _init_bullet(bullet) - - -## Cleans up behavior-specific state for a [Bullet]. -func deinit_bullet(bullet: Bullet) -> void: - _deinit_bullet(bullet) - - -## Processes one tick of a [Bullet]'s movement. -func process_bullet(bullet: Bullet, delta: float) -> void: - _process_bullet(bullet, delta) - - -## Called when a [Bullet] is spawned with this behavior in order to set up -## behavior-specific state. -@abstract func _init_bullet(bullet: Bullet) -> void - - -## Called when a [Bullet] is recycled in order to clean up behavior-specific state. -@abstract func _deinit_bullet(bullet: Bullet) -> void - - -## Called to process a tick of a [Bullet]'s movement. -@abstract func _process_bullet(bullet: Bullet, delta: float) -> void diff --git a/systems/bullets/bullet.gd b/systems/bullets/bullet.gd index f22dcd3..cbf0c5c 100644 --- a/systems/bullets/bullet.gd +++ b/systems/bullets/bullet.gd @@ -97,8 +97,6 @@ func _enter_tree() -> void: func _physics_process(delta: float) -> void: if not Engine.is_editor_hint(): - time_elapsed += delta - if face_direction: rotation = direction.angle() diff --git a/systems/bullets/actions/bullet_action.gd b/systems/bullets/bullet_actions/bullet_action.gd similarity index 100% rename from systems/bullets/actions/bullet_action.gd rename to systems/bullets/bullet_actions/bullet_action.gd diff --git a/systems/bullets/actions/bullet_action.gd.uid b/systems/bullets/bullet_actions/bullet_action.gd.uid similarity index 100% rename from systems/bullets/actions/bullet_action.gd.uid rename to systems/bullets/bullet_actions/bullet_action.gd.uid diff --git a/systems/bullets/actions/despawn_action.gd b/systems/bullets/bullet_actions/despawn_action.gd similarity index 100% rename from systems/bullets/actions/despawn_action.gd rename to systems/bullets/bullet_actions/despawn_action.gd diff --git a/systems/bullets/actions/despawn_action.gd.uid b/systems/bullets/bullet_actions/despawn_action.gd.uid similarity index 100% rename from systems/bullets/actions/despawn_action.gd.uid rename to systems/bullets/bullet_actions/despawn_action.gd.uid diff --git a/systems/bullets/actions/multi_action.gd b/systems/bullets/bullet_actions/multi_action.gd similarity index 84% rename from systems/bullets/actions/multi_action.gd rename to systems/bullets/bullet_actions/multi_action.gd index 0dbaa69..68d7a58 100644 --- a/systems/bullets/actions/multi_action.gd +++ b/systems/bullets/bullet_actions/multi_action.gd @@ -4,7 +4,7 @@ extends BulletAction ## [BulletAction]s to perform when triggered. -@export var actions: Array[BulletAction] +@export var actions: Array[BulletAction] = [] func _perform(bullet: Bullet) -> void: diff --git a/systems/bullets/actions/multi_action.gd.uid b/systems/bullets/bullet_actions/multi_action.gd.uid similarity index 100% rename from systems/bullets/actions/multi_action.gd.uid rename to systems/bullets/bullet_actions/multi_action.gd.uid diff --git a/systems/bullets/actions/spawn_set_action.gd b/systems/bullets/bullet_actions/spawn_set_action.gd similarity index 86% rename from systems/bullets/actions/spawn_set_action.gd rename to systems/bullets/bullet_actions/spawn_set_action.gd index ade6efc..b51cf5e 100644 --- a/systems/bullets/actions/spawn_set_action.gd +++ b/systems/bullets/bullet_actions/spawn_set_action.gd @@ -21,6 +21,10 @@ func _perform(bullet: Bullet) -> void: bullet_set.preset = preset bullet_set.global_position = bullet.global_position if local_coords: + if match_direction: + bullet_set.rotation = bullet.rotation bullet.get_parent().add_child(bullet_set) else: + if match_direction: + bullet_set.global_rotation = bullet.global_rotation bullet.get_parent().get_parent().add_child(bullet_set) diff --git a/systems/bullets/actions/spawn_set_action.gd.uid b/systems/bullets/bullet_actions/spawn_set_action.gd.uid similarity index 100% rename from systems/bullets/actions/spawn_set_action.gd.uid rename to systems/bullets/bullet_actions/spawn_set_action.gd.uid diff --git a/systems/bullets/bullet_behaviors/bullet_behavior.gd b/systems/bullets/bullet_behaviors/bullet_behavior.gd new file mode 100644 index 0000000..73f5a7b --- /dev/null +++ b/systems/bullets/bullet_behaviors/bullet_behavior.gd @@ -0,0 +1,57 @@ +@abstract +class_name BulletBehavior +extends Resource + + +@export_group("Actions", "action_") +## Delay in seconds before performing [member action_on_delay]. +@export_range(0.0, 1.0, 0.01, "or_greater", "suffix:s") var action_delay: float = 0.0 +## Performed once the bullet has existed for [member action_delay] seconds. +@export var action_on_delay: BulletAction +## Interval in seconds at which [member action_on_interval] is performed. +@export_range(0.0, 1.0, 0.01, "or_greater", "suffix:s") var action_interval: float = 0.0 +## Performed every [member action_interval] seconds. +@export var action_on_interval: BulletAction + + +var _bullet_interval_cooldowns: Dictionary[Bullet, float] = {} + + +## Performs behavior-specific initialization for a [Bullet]. +func init_bullet(bullet: Bullet) -> void: + if action_on_interval: + _bullet_interval_cooldowns[bullet] = action_interval + bullet.recycled.connect(deinit_bullet.bind(bullet), CONNECT_ONE_SHOT) + _init_bullet(bullet) + + +## Cleans up behavior-specific state for a [Bullet]. +func deinit_bullet(bullet: Bullet) -> void: + _bullet_interval_cooldowns.erase(bullet) + _deinit_bullet(bullet) + + +## Processes one tick of a [Bullet]'s movement. +func process_bullet(bullet: Bullet, delta: float) -> void: + var last_time = bullet.time_elapsed + bullet.time_elapsed += delta + if last_time < action_delay and bullet.time_elapsed >= action_delay and action_on_delay: + action_on_delay.perform(bullet) + if action_on_interval: + _bullet_interval_cooldowns[bullet] -= delta + if _bullet_interval_cooldowns[bullet] <= 0.0: + _bullet_interval_cooldowns[bullet] += action_interval + _process_bullet(bullet, delta) + + +## Called when a [Bullet] is spawned with this behavior in order to set up +## behavior-specific state. +@abstract func _init_bullet(bullet: Bullet) -> void + + +## Called when a [Bullet] is recycled in order to clean up behavior-specific state. +@abstract func _deinit_bullet(bullet: Bullet) -> void + + +## Called to process a tick of a [Bullet]'s movement. +@abstract func _process_bullet(bullet: Bullet, delta: float) -> void diff --git a/systems/bullets/behaviors/bullet_behavior.gd.uid b/systems/bullets/bullet_behaviors/bullet_behavior.gd.uid similarity index 100% rename from systems/bullets/behaviors/bullet_behavior.gd.uid rename to systems/bullets/bullet_behaviors/bullet_behavior.gd.uid diff --git a/systems/bullets/behaviors/simple_linear_behavior.gd b/systems/bullets/bullet_behaviors/simple_linear_behavior.gd similarity index 93% rename from systems/bullets/behaviors/simple_linear_behavior.gd rename to systems/bullets/bullet_behaviors/simple_linear_behavior.gd index 9a0f9d4..df4ec44 100644 --- a/systems/bullets/behaviors/simple_linear_behavior.gd +++ b/systems/bullets/bullet_behaviors/simple_linear_behavior.gd @@ -15,6 +15,8 @@ extends BulletBehavior @export_custom(0, "suffix:px/s") var max_speed: float = INF @export_group("Actions", "action_") +## Performed when the bullet reaches either [member min_speed] or +## [member max_speed] for the first time. @export var action_speed_clamped: BulletAction diff --git a/systems/bullets/behaviors/simple_linear_behavior.gd.uid b/systems/bullets/bullet_behaviors/simple_linear_behavior.gd.uid similarity index 100% rename from systems/bullets/behaviors/simple_linear_behavior.gd.uid rename to systems/bullets/bullet_behaviors/simple_linear_behavior.gd.uid diff --git a/systems/bullets/bullet_preset.gd b/systems/bullets/bullet_preset.gd index 8ff6541..5a4ccd5 100644 --- a/systems/bullets/bullet_preset.gd +++ b/systems/bullets/bullet_preset.gd @@ -1,16 +1,17 @@ class_name BulletPreset extends Resource + +@export_group("Bullets") @export var behavior: BulletBehavior = null - -@export var pattern: BulletSpawnPattern = null - @export var textures: Array[Texture2D] = [] - @export var hitbox_size: Vector2i = Vector2i.ZERO - @export var face_direction: bool = false +@export_group("Spawning") +@export var pattern: BulletSpawnPattern = null @export var rounds: int = 1 - @export var round_delay: float = 0.0 + +@export_group("Bullet Set") +@export var set_behavior: BulletSetBehavior = null diff --git a/systems/bullets/bullet_set.gd b/systems/bullets/bullet_set.gd index bf2b59a..aa8fe4a 100644 --- a/systems/bullets/bullet_set.gd +++ b/systems/bullets/bullet_set.gd @@ -5,6 +5,10 @@ extends Node2D @export var preset: BulletPreset +var spawn_offset: Vector2 = Vector2.ZERO +var spawn_rotation: float = 0.0 + + func _ready() -> void: for _n in preset.rounds: preset.pattern.spawn_bullets(self, preset) @@ -14,6 +18,10 @@ func _ready() -> void: func _physics_process(delta: float) -> void: if get_child_count() == 0: queue_free() + + if preset.set_behavior: + preset.set_behavior.process_set(self, delta) + for bullet in get_children(): if bullet is Bullet: preset.behavior.process_bullet(bullet, delta) diff --git a/systems/bullets/set_behaviors/bullet_set_behavior.gd b/systems/bullets/set_behaviors/bullet_set_behavior.gd new file mode 100644 index 0000000..aba36b1 --- /dev/null +++ b/systems/bullets/set_behaviors/bullet_set_behavior.gd @@ -0,0 +1,12 @@ +@abstract +class_name BulletSetBehavior +extends Resource + + +## Process one physics tick for a [BulletSet]. +func process_set(bullet_set: BulletSet, delta: float) -> void: + _process_set(bullet_set, delta) + + +## Called once ever physics tick for the [BulletSet]. +@abstract func _process_set(bullet_set: BulletSet, delta: float) -> void diff --git a/systems/bullets/set_behaviors/bullet_set_behavior.gd.uid b/systems/bullets/set_behaviors/bullet_set_behavior.gd.uid new file mode 100644 index 0000000..5fa6440 --- /dev/null +++ b/systems/bullets/set_behaviors/bullet_set_behavior.gd.uid @@ -0,0 +1 @@ +uid://cu4iq25sb3y5f diff --git a/systems/bullets/set_behaviors/multi_set_behavior.gd b/systems/bullets/set_behaviors/multi_set_behavior.gd new file mode 100644 index 0000000..2a9cdcf --- /dev/null +++ b/systems/bullets/set_behaviors/multi_set_behavior.gd @@ -0,0 +1,11 @@ +class_name MultiSetBehavior +extends BulletSetBehavior +## Processes multiple [BulletSetBehavior]s in order for the [BulletSet]. + + +@export var behaviors: Array[BulletSetBehavior] = [] + + +func _process_set(bullet_set: BulletSet, delta: float) -> void: + for behavior in behaviors: + behavior.process_set(bullet_set, delta) diff --git a/systems/bullets/set_behaviors/multi_set_behavior.gd.uid b/systems/bullets/set_behaviors/multi_set_behavior.gd.uid new file mode 100644 index 0000000..0a3bdd6 --- /dev/null +++ b/systems/bullets/set_behaviors/multi_set_behavior.gd.uid @@ -0,0 +1 @@ +uid://cijy4yedxklfd diff --git a/systems/bullets/set_behaviors/rotation_set_behavior.gd b/systems/bullets/set_behaviors/rotation_set_behavior.gd new file mode 100644 index 0000000..b798556 --- /dev/null +++ b/systems/bullets/set_behaviors/rotation_set_behavior.gd @@ -0,0 +1,11 @@ +class_name RotationSetBehavior +extends BulletSetBehavior + + +@export_custom(0, "radians_as_degrees,suffix:°/s") var rotation_speed: float = 0.0 +@export_custom(0, "radians_as_degrees,suffix:°/s") var spawn_rotation_speed: float = 0.0 + + +func _process_set(bullet_set: BulletSet, delta: float) -> void: + bullet_set.rotation += rotation_speed * delta + bullet_set.spawn_rotation += spawn_rotation_speed * delta diff --git a/systems/bullets/set_behaviors/rotation_set_behavior.gd.uid b/systems/bullets/set_behaviors/rotation_set_behavior.gd.uid new file mode 100644 index 0000000..df31c6a --- /dev/null +++ b/systems/bullets/set_behaviors/rotation_set_behavior.gd.uid @@ -0,0 +1 @@ +uid://5scjonwmg8tw diff --git a/systems/bullets/spawn_patterns/line_pattern.gd b/systems/bullets/spawn_patterns/line_pattern.gd index 7227df8..b45b4a3 100644 --- a/systems/bullets/spawn_patterns/line_pattern.gd +++ b/systems/bullets/spawn_patterns/line_pattern.gd @@ -16,11 +16,11 @@ func spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void: preset.face_direction ) - var line = line_normal.orthogonal() + var line = line_normal.orthogonal().rotated(bullet_set.spawn_rotation) var weight = float(i) / float(bullet_count - 1) weight -= 0.5 if bullet_count == 1: weight = 0.0 - bullet.position = line * weight * line_width + bullet.position = bullet_set.spawn_offset + line * weight * line_width bullet_set.add_bullet(bullet) diff --git a/systems/bullets/spawn_patterns/ring_pattern.gd b/systems/bullets/spawn_patterns/ring_pattern.gd index da695ee..4377ff0 100644 --- a/systems/bullets/spawn_patterns/ring_pattern.gd +++ b/systems/bullets/spawn_patterns/ring_pattern.gd @@ -10,12 +10,12 @@ extends BulletSpawnPattern func spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void: for i in bullet_count: - var angle = (float(i) / float(bullet_count)) * TAU + angle_offset + var angle = (float(i) / float(bullet_count)) * TAU + angle_offset + bullet_set.spawn_rotation var bullet = Bullet.create( preset.textures.pick_random(), preset.hitbox_size, Vector2.from_angle(angle + direction_rotation), preset.face_direction ) - bullet.position = Vector2.from_angle(angle) * distance_offset + bullet.position = bullet_set.spawn_offset + Vector2.from_angle(angle) * distance_offset bullet_set.add_bullet(bullet)