diff --git a/project.godot b/project.godot index b06bb92..f374a69 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 cf636f8..b63db9d 100644 --- a/scenes/test_scene_haze.tscn +++ b/scenes/test_scene_haze.tscn @@ -1,60 +1,61 @@ -[gd_scene load_steps=15 format=3 uid="uid://dxsp66qpvm65b"] +[gd_scene load_steps=13 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://q2fys6o0jy6w" path="res://objects/starfield/starfield.tscn" id="1_4oowd"] [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://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/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://5scjonwmg8tw" path="res://systems/bullets/set_behaviors/rotation_set_behavior.gd" id="7_t1bs8"] +[ext_resource type="Script" uid="uid://ckedfcjjnv7dq" path="res://systems/bullets/spawn_patterns/spawn_pattern_randomizer.gd" id="7_4oowd"] -[sub_resource type="Resource" id="Resource_sle1e"] -script = ExtResource("4_4oowd") -metadata/_custom_type_script = "uid://pn143vuxc7wp" - -[sub_resource type="Resource" id="Resource_c0i5a"] +[sub_resource type="Resource" id="Resource_t1bs8"] script = ExtResource("4_t1bs8") -initial_speed = 128.0 -acceleration = -64.0 -min_speed = 0.0 -action_speed_clamped = SubResource("Resource_sle1e") +initial_speed = 120.0 metadata/_custom_type_script = "uid://dntp60my5f65m" -[sub_resource type="Resource" id="Resource_cf1so"] +[sub_resource type="Resource" id="Resource_4oowd"] script = ExtResource("6_uu3sg") -bullet_count = 5 +bullet_count = 1 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_sle1e"] +script = ExtResource("7_4oowd") +pattern = SubResource("Resource_4oowd") +property_min_values = Dictionary[StringName, float]({ +&"direction_rotation": -3.142 +}) +property_max_values = Dictionary[StringName, float]({ +&"direction_rotation": 3.142 +}) +iterations = 50 +metadata/_custom_type_script = "uid://ckedfcjjnv7dq" -[sub_resource type="Resource" id="Resource_uu3sg"] +[sub_resource type="Resource" id="Resource_hxqcc"] script = ExtResource("6_sle1e") -behavior = SubResource("Resource_c0i5a") +behavior = SubResource("Resource_t1bs8") textures = Array[Texture2D]([ExtResource("4_hlyn7")]) +colors = Array[Color]([Color(1, 0, 0, 1), Color(0, 0, 1, 1), Color(0, 1, 0, 1), Color(1, 1, 0, 1)]) hitbox_size = Vector2i(6, 6) -pattern = SubResource("Resource_cf1so") -rounds = 100000 +pattern = SubResource("Resource_sle1e") +rounds = 99999999 round_delay = 0.5 -set_behavior = SubResource("Resource_4oowd") metadata/_custom_type_script = "uid://vus1a0flwtnm" [node name="TestScene" type="Node"] -[node name="Icon" type="Sprite2D" parent="."] -position = Vector2(110, 187) -texture = ExtResource("1_g7g4h") +[node name="SubViewportContainer" type="SubViewportContainer" parent="."] +offset_right = 240.0 +offset_bottom = 320.0 + +[node name="SubViewport" parent="SubViewportContainer" instance=ExtResource("1_4oowd")] +size = Vector2i(240, 320) [node name="Player" parent="." instance=ExtResource("2_j8ivh")] -position = Vector2(100, 99) +position = Vector2(122, 283) [node name="BulletSet" type="Node2D" parent="."] -position = Vector2(111, 152) +position = Vector2(122, 92) script = ExtResource("3_cf1so") -preset = SubResource("Resource_uu3sg") +preset = SubResource("Resource_hxqcc") metadata/_custom_type_script = "uid://cj2fj7snls8aa" diff --git a/systems/bullets/bullet.gd b/systems/bullets/bullet.gd index dfb6092..18a6e70 100644 --- a/systems/bullets/bullet.gd +++ b/systems/bullets/bullet.gd @@ -52,20 +52,22 @@ var _hitbox: CollisionShape2D = CollisionShape2D.new() ## Returns a new [Bullet], which may be sourced from the cached bullets. @warning_ignore("shadowed_variable") static func create( - texture: Texture2D = null, - hitbox_size: Vector2i = Vector2i.ZERO, + preset: BulletPreset, 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.new() - bullet.texture = texture - bullet.hitbox_size = hitbox_size + if not preset.textures.is_empty(): + bullet.texture = preset.textures.pick_random() + if not preset.colors.is_empty(): + bullet.modulate = preset.colors.pick_random() + bullet.hitbox_size = preset.hitbox_size + bullet.face_direction = preset.face_direction + bullet.direction = direction - bullet.face_direction = face_direction bullet.time_elapsed = 0.0 bullet.grazed = false diff --git a/systems/bullets/bullet_preset.gd b/systems/bullets/bullet_preset.gd index 5a4ccd5..a7a3d86 100644 --- a/systems/bullets/bullet_preset.gd +++ b/systems/bullets/bullet_preset.gd @@ -5,6 +5,7 @@ extends Resource @export_group("Bullets") @export var behavior: BulletBehavior = null @export var textures: Array[Texture2D] = [] +@export var colors: Array[Color] = [Color.WHITE] @export var hitbox_size: Vector2i = Vector2i.ZERO @export var face_direction: bool = false diff --git a/systems/bullets/bullet_set.gd b/systems/bullets/bullet_set.gd index aa8fe4a..5e64bb9 100644 --- a/systems/bullets/bullet_set.gd +++ b/systems/bullets/bullet_set.gd @@ -10,9 +10,7 @@ var spawn_rotation: float = 0.0 func _ready() -> void: - for _n in preset.rounds: - preset.pattern.spawn_bullets(self, preset) - await get_tree().create_timer(preset.round_delay, false, true).timeout + _spawn_rounds() func _physics_process(delta: float) -> void: @@ -36,3 +34,9 @@ func add_bullets(new_bullets: Array[Bullet]) -> void: for bullet in new_bullets: preset.behavior.init_bullet(bullet) add_child(bullet) + + +func _spawn_rounds() -> void: + for _n in preset.rounds: + preset.pattern.spawn_bullets(self, preset) + await get_tree().create_timer(preset.round_delay, false, true).timeout diff --git a/systems/bullets/set_behaviors/random_spawn_set_behavior.gd b/systems/bullets/set_behaviors/random_spawn_set_behavior.gd new file mode 100644 index 0000000..18e1c7b --- /dev/null +++ b/systems/bullets/set_behaviors/random_spawn_set_behavior.gd @@ -0,0 +1,34 @@ +@tool +class_name RandomSpawnSetBehavior +extends BulletSetBehavior + + +@export var spawn_offset_min: Vector2: + set(value): + if spawn_offset_min != value: + spawn_offset_min = value + spawn_offset_max = spawn_offset_max.max(spawn_offset_min) +@export var spawn_offset_max: Vector2: + set(value): + if spawn_offset_max != value: + spawn_offset_max = value + spawn_offset_min = spawn_offset_min.min(spawn_offset_max) + +@export_custom(0, "radians_as_degrees") var spawn_rotation_min: float: + set(value): + spawn_rotation_min = value + if spawn_rotation_max < spawn_rotation_min: + spawn_rotation_max = maxf(spawn_rotation_min, spawn_rotation_max) +@export_custom(0, "radians_as_degrees") var spawn_rotation_max: float: + set(value): + spawn_rotation_max = value + if spawn_rotation_min > spawn_rotation_max: + spawn_rotation_min = minf(spawn_rotation_min, spawn_rotation_max) + + +func _process_set(bullet_set: BulletSet, delta: float) -> void: + bullet_set.spawn_offset = Vector2( + randf_range(spawn_offset_min.x, spawn_offset_max.x), + randf_range(spawn_offset_min.y, spawn_offset_max.y) + ) + bullet_set.spawn_rotation = randf_range(spawn_rotation_min, spawn_rotation_max) diff --git a/systems/bullets/set_behaviors/random_spawn_set_behavior.gd.uid b/systems/bullets/set_behaviors/random_spawn_set_behavior.gd.uid new file mode 100644 index 0000000..d52e081 --- /dev/null +++ b/systems/bullets/set_behaviors/random_spawn_set_behavior.gd.uid @@ -0,0 +1 @@ +uid://b02juhj57mrnj diff --git a/systems/bullets/spawn_patterns/bullet_spawn_pattern.gd b/systems/bullets/spawn_patterns/bullet_spawn_pattern.gd index be4e178..ff0a514 100644 --- a/systems/bullets/spawn_patterns/bullet_spawn_pattern.gd +++ b/systems/bullets/spawn_patterns/bullet_spawn_pattern.gd @@ -3,4 +3,15 @@ class_name BulletSpawnPattern extends Resource -@abstract func spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void +## The amount of times to spawning this pattern for one "round". +## This is mostly useful if the pattern or behavior introduces some +## form of randomness. +@export_range(1, 1, 1, "or_greater") var iterations: int = 1 + + +func spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void: + for _n in iterations: + _spawn_bullets(bullet_set, preset) + + +@abstract func _spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void diff --git a/systems/bullets/spawn_patterns/line_pattern.gd b/systems/bullets/spawn_patterns/line_pattern.gd index b45b4a3..79f834a 100644 --- a/systems/bullets/spawn_patterns/line_pattern.gd +++ b/systems/bullets/spawn_patterns/line_pattern.gd @@ -7,14 +7,9 @@ extends BulletSpawnPattern @export_custom(0, "direction") var line_normal: Vector2 = Vector2.RIGHT -func spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void: +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 bullet = Bullet.create(preset, line_normal) var line = line_normal.orthogonal().rotated(bullet_set.spawn_rotation) var weight = float(i) / float(bullet_count - 1) diff --git a/systems/bullets/spawn_patterns/ring_pattern.gd b/systems/bullets/spawn_patterns/ring_pattern.gd index 4377ff0..1c479fb 100644 --- a/systems/bullets/spawn_patterns/ring_pattern.gd +++ b/systems/bullets/spawn_patterns/ring_pattern.gd @@ -8,14 +8,9 @@ extends BulletSpawnPattern @export_custom(0, "radians_as_degrees") var direction_rotation: float -func spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void: +func _spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void: for i in bullet_count: 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 - ) + var bullet = Bullet.create(preset, Vector2.from_angle(angle + direction_rotation)) bullet.position = bullet_set.spawn_offset + Vector2.from_angle(angle) * distance_offset bullet_set.add_bullet(bullet) diff --git a/systems/bullets/spawn_patterns/spawn_pattern_randomizer.gd b/systems/bullets/spawn_patterns/spawn_pattern_randomizer.gd new file mode 100644 index 0000000..554628c --- /dev/null +++ b/systems/bullets/spawn_patterns/spawn_pattern_randomizer.gd @@ -0,0 +1,26 @@ +@tool +class_name SpawnPatternRandomizer +extends BulletSpawnPattern +## Randomizes properties of a child [BulletSpawnPattern] each [member iteration]. +## +## WARNING: Experimental. Only float properties are currently +## supported and this class is subject to change in the future. + + +## The pattern to randomize and defer to. +@export var pattern: BulletSpawnPattern + +## Minimum value for each randomized property. +@export var property_min_values: Dictionary[StringName, float] = {} +## Maximum value for each randomized property. +@export var property_max_values: Dictionary[StringName, float] = {} + + +func _spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void: + for property in property_min_values: + if property_max_values.has(property): + pattern.set(property, randf_range( + property_min_values[property], + property_max_values[property] + )) + pattern.spawn_bullets(bullet_set, preset) diff --git a/systems/bullets/spawn_patterns/spawn_pattern_randomizer.gd.uid b/systems/bullets/spawn_patterns/spawn_pattern_randomizer.gd.uid new file mode 100644 index 0000000..bd3e187 --- /dev/null +++ b/systems/bullets/spawn_patterns/spawn_pattern_randomizer.gd.uid @@ -0,0 +1 @@ +uid://ckedfcjjnv7dq