diff --git a/project.godot b/project.godot index 9247ee8..a5e37ae 100644 --- a/project.godot +++ b/project.godot @@ -28,7 +28,6 @@ Hud="*res://gui/hud.tscn" window/size/viewport_width=240 window/size/viewport_height=320 -window/vsync/vsync_mode=0 [editor_plugins] diff --git a/scenes/test_scene_haze.tscn b/scenes/test_scene_haze.tscn index 9c5d781..9a4d7de 100644 --- a/scenes/test_scene_haze.tscn +++ b/scenes/test_scene_haze.tscn @@ -1,32 +1,73 @@ -[gd_scene load_steps=11 format=3 uid="uid://dxsp66qpvm65b"] +[gd_scene load_steps=23 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="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://dtuc6qerbfset" path="res://systems/bullets/spawn_patterns/ring_pattern.gd" id="5_4oowd"] +[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://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"] -[sub_resource type="Resource" id="Resource_c0i5a"] +[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_1xo0o"] -script = ExtResource("5_4oowd") -bullet_count = 5 -distance_offset = 16.0 -direction_rotation = 3.9269908169872414 +[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"] +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") +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_uu3sg"] script = ExtResource("6_sle1e") behavior = SubResource("Resource_c0i5a") -pattern = SubResource("Resource_1xo0o") +pattern = SubResource("Resource_t1bs8") textures = Array[Texture2D]([ExtResource("4_hlyn7")]) hitbox_size = Vector2i(6, 6) -rounds = 5 +rounds = 100000 round_delay = 1.0 metadata/_custom_type_script = "uid://vus1a0flwtnm" @@ -40,7 +81,7 @@ texture = ExtResource("1_g7g4h") position = Vector2(100, 99) [node name="BulletSet" type="Node2D" parent="."] -position = Vector2(110, 192) +position = Vector2(111, 152) script = ExtResource("3_cf1so") preset = SubResource("Resource_uu3sg") metadata/_custom_type_script = "uid://cj2fj7snls8aa" diff --git a/systems/bullets/actions/bullet_action.gd b/systems/bullets/actions/bullet_action.gd new file mode 100644 index 0000000..842d34c --- /dev/null +++ b/systems/bullets/actions/bullet_action.gd @@ -0,0 +1,12 @@ +@abstract +class_name BulletAction +extends Resource + + +## Performs the action on a given [Bullet]. +func perform(bullet: Bullet) -> void: + _perform(bullet) + + +## Called to perform the action on a given [Bullet]. +@abstract func _perform(bullet: Bullet) -> void diff --git a/systems/bullets/actions/bullet_action.gd.uid b/systems/bullets/actions/bullet_action.gd.uid new file mode 100644 index 0000000..53514a1 --- /dev/null +++ b/systems/bullets/actions/bullet_action.gd.uid @@ -0,0 +1 @@ +uid://mivkgn34ox41 diff --git a/systems/bullets/actions/despawn_action.gd b/systems/bullets/actions/despawn_action.gd new file mode 100644 index 0000000..e266659 --- /dev/null +++ b/systems/bullets/actions/despawn_action.gd @@ -0,0 +1,7 @@ +class_name DespawnAction +extends BulletAction +## Removes and recycles the [Bullet] when triggered. + + +func _perform(bullet: Bullet) -> void: + bullet.recycle() diff --git a/systems/bullets/actions/despawn_action.gd.uid b/systems/bullets/actions/despawn_action.gd.uid new file mode 100644 index 0000000..ef3edac --- /dev/null +++ b/systems/bullets/actions/despawn_action.gd.uid @@ -0,0 +1 @@ +uid://pn143vuxc7wp diff --git a/systems/bullets/actions/multi_action.gd b/systems/bullets/actions/multi_action.gd new file mode 100644 index 0000000..0dbaa69 --- /dev/null +++ b/systems/bullets/actions/multi_action.gd @@ -0,0 +1,12 @@ +class_name MultiAction +extends BulletAction +## Performs a set of [BulletAction]s in order when triggered. + + +## [BulletAction]s to perform when triggered. +@export var actions: Array[BulletAction] + + +func _perform(bullet: Bullet) -> void: + for action in actions: + action.perform(bullet) diff --git a/systems/bullets/actions/multi_action.gd.uid b/systems/bullets/actions/multi_action.gd.uid new file mode 100644 index 0000000..36284fd --- /dev/null +++ b/systems/bullets/actions/multi_action.gd.uid @@ -0,0 +1 @@ +uid://mair8nsxn7lp diff --git a/systems/bullets/actions/spawn_set_action.gd b/systems/bullets/actions/spawn_set_action.gd new file mode 100644 index 0000000..ade6efc --- /dev/null +++ b/systems/bullets/actions/spawn_set_action.gd @@ -0,0 +1,26 @@ +class_name SpawnSetAction +extends BulletAction +## Spawns a new [BulletSet] at the [Bullet]'s position when triggered. + + +## The [BulletPreset] to use for the spawned [BulletSet]. +@export var preset: BulletPreset + +## If [code]true[/code], the spawned [BulletSet] will be rotated to face the +## [Bullet]'s direction. +@export var match_direction: bool = false + +## If [code]true[/code], the spawned [BulletSet] will be added as a child of +## the [Bullet]'s parent [BulletSet]. If [code]false[/code], it will be added +## as a child of that [BulletSet]'s parent [Node]. +@export var local_coords: bool = false + + +func _perform(bullet: Bullet) -> void: + var bullet_set = BulletSet.new() + bullet_set.preset = preset + bullet_set.global_position = bullet.global_position + if local_coords: + bullet.get_parent().add_child(bullet_set) + else: + bullet.get_parent().get_parent().add_child(bullet_set) diff --git a/systems/bullets/actions/spawn_set_action.gd.uid b/systems/bullets/actions/spawn_set_action.gd.uid new file mode 100644 index 0000000..f0ebab1 --- /dev/null +++ b/systems/bullets/actions/spawn_set_action.gd.uid @@ -0,0 +1 @@ +uid://oug6n1t6tnor diff --git a/systems/bullets/behaviors/bullet_behavior.gd b/systems/bullets/behaviors/bullet_behavior.gd index 1c38dc8..1caf3b2 100644 --- a/systems/bullets/behaviors/bullet_behavior.gd +++ b/systems/bullets/behaviors/bullet_behavior.gd @@ -3,10 +3,30 @@ class_name BulletBehavior extends Resource -## Called when a bullet is spawned with this behavior in order to set up -## behavior-specific state. -@warning_ignore("unused_parameter") -func init_bullet(bullet: Bullet) -> void: pass +## 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) -## Called to process a tick of a bullet's movement. -@abstract func process_bullet(bullet: Bullet, delta: float) -> void + +## 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/behaviors/simple_linear_behavior.gd b/systems/bullets/behaviors/simple_linear_behavior.gd index c050f56..9a0f9d4 100644 --- a/systems/bullets/behaviors/simple_linear_behavior.gd +++ b/systems/bullets/behaviors/simple_linear_behavior.gd @@ -9,7 +9,41 @@ extends BulletBehavior ## Rate at which the bullet will speed up. @export_custom(0, "suffix:px/s²") var acceleration: float = 0.0 +## Speed will be clamped between [member min_speed] and [member max_speed]. +@export_custom(0, "suffix:px/s") var min_speed: float = -INF +## Speed will be clamped between [member min_speed] and [member max_speed]. +@export_custom(0, "suffix:px/s") var max_speed: float = INF -func process_bullet(bullet: Bullet, delta: float) -> void: - var speed = initial_speed + acceleration * bullet.time_elapsed - bullet.position += bullet.direction * speed * delta +@export_group("Actions", "action_") +@export var action_speed_clamped: BulletAction + + +var _bullet_data: Dictionary[Bullet, Data] = {} + + +func _init_bullet(bullet: Bullet) -> void: + var data = Data.new() + data.speed = initial_speed + _bullet_data[bullet] = data + + +func _deinit_bullet(bullet: Bullet) -> void: + _bullet_data.erase(bullet) + + +func _process_bullet(bullet: Bullet, delta: float) -> void: + if not _bullet_data.has(bullet): + return + var data = _bullet_data[bullet] + data.speed += acceleration * delta + if not data.already_clamped and (data.speed <= min_speed or data.speed >= max_speed): + data.already_clamped = true + if action_speed_clamped: + action_speed_clamped.perform(bullet) + data.speed = clampf(data.speed, min_speed, max_speed) + bullet.position += bullet.direction * data.speed * delta + + +class Data: + var speed: float + var already_clamped: bool = false diff --git a/systems/bullets/bullet.gd b/systems/bullets/bullet.gd index 20f51b7..f22dcd3 100644 --- a/systems/bullets/bullet.gd +++ b/systems/bullets/bullet.gd @@ -4,6 +4,10 @@ class_name Bullet extends Area2D +## Emitted whenever a bullet is recycled. +signal recycled() + + ## The number of bullets to allocate at startup. const INITIAL_ALLOCATED_BULLETS: int = 2000 @@ -51,9 +55,10 @@ static func create( direction: Vector2 = Vector2.RIGHT, face_direction: bool = false, ) -> Bullet: - var bullet: Bullet = _cached_bullets.pop_back() - if not bullet: - bullet = Bullet.new() + #var bullet: Bullet = _cached_bullets.pop_back() + #if not bullet: + #bullet = Bullet.new() + var bullet := Bullet.new() bullet.texture = texture bullet.hitbox_size = hitbox_size @@ -67,8 +72,11 @@ static func create( ## Removes the bullet from the scene tree and returns it to the bullet cache to be ## re-used later. func recycle() -> void: - get_parent().remove_child(self) - _cached_bullets.append(self) + #if is_inside_tree(): + #get_parent().remove_child(self) + #_cached_bullets.append(self) + queue_free() + recycled.emit() static func _static_init() -> void: diff --git a/systems/bullets/bullet_set.gd b/systems/bullets/bullet_set.gd index d98573a..bf2b59a 100644 --- a/systems/bullets/bullet_set.gd +++ b/systems/bullets/bullet_set.gd @@ -12,12 +12,11 @@ func _ready() -> void: func _physics_process(delta: float) -> void: + if get_child_count() == 0: + queue_free() for bullet in get_children(): if bullet is Bullet: preset.behavior.process_bullet(bullet, delta) - else: - push_error("BulletSet does not support having non-bullet children. Removing child: ", bullet) - bullet.queue_free() func add_bullet(bullet: Bullet) -> void: diff --git a/systems/bullets/spawn_patterns/line_pattern.gd b/systems/bullets/spawn_patterns/line_pattern.gd new file mode 100644 index 0000000..7227df8 --- /dev/null +++ b/systems/bullets/spawn_patterns/line_pattern.gd @@ -0,0 +1,26 @@ +class_name LinePattern +extends BulletSpawnPattern + + +@export var bullet_count: int +@export var line_width: float +@export_custom(0, "direction") var line_normal: Vector2 = Vector2.RIGHT + + +func spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void: + for i in bullet_count: + var bullet = Bullet.create( + preset.textures.pick_random(), + preset.hitbox_size, + line_normal, + preset.face_direction + ) + + var line = line_normal.orthogonal() + 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_set.add_bullet(bullet) diff --git a/systems/bullets/spawn_patterns/line_pattern.gd.uid b/systems/bullets/spawn_patterns/line_pattern.gd.uid new file mode 100644 index 0000000..f1dd4ce --- /dev/null +++ b/systems/bullets/spawn_patterns/line_pattern.gd.uid @@ -0,0 +1 @@ +uid://d238qii8i2byl