From ddf3590c96be0e4714be078f62d4ac7fe6396569 Mon Sep 17 00:00:00 2001 From: Haze Weathers Date: Fri, 2 Jan 2026 20:30:18 -0600 Subject: [PATCH] documentation pass before moving on --- scenes/test_scene_haze.tscn | 7 ++-- scenes/test_scene_penny.tscn | 2 +- systems/bullets/bullet.gd | 41 ++++++------------- .../bullets/bullet_actions/bullet_action.gd | 1 + .../bullet_behaviors/bullet_behavior.gd | 15 +++++-- ..._behavior.gd => linear_motion_behavior.gd} | 2 +- ...r.gd.uid => linear_motion_behavior.gd.uid} | 0 systems/bullets/bullet_preset.gd | 20 ++++++++- systems/bullets/bullet_set.gd | 4 ++ .../set_behaviors/bullet_set_behavior.gd | 1 + .../set_behaviors/multi_set_behavior.gd | 1 + .../random_spawn_set_behavior.gd | 5 +++ .../set_behaviors/rotation_set_behavior.gd | 3 ++ .../spawn_patterns/bullet_spawn_pattern.gd | 2 + .../bullets/spawn_patterns/line_pattern.gd | 6 ++- .../bullets/spawn_patterns/ring_pattern.gd | 11 +++-- systems/visuals/animation_strip.gd | 7 ++++ 17 files changed, 84 insertions(+), 44 deletions(-) rename systems/bullets/bullet_behaviors/{simple_linear_behavior.gd => linear_motion_behavior.gd} (98%) rename systems/bullets/bullet_behaviors/{simple_linear_behavior.gd.uid => linear_motion_behavior.gd.uid} (100%) diff --git a/scenes/test_scene_haze.tscn b/scenes/test_scene_haze.tscn index 355cb27..73f41aa 100644 --- a/scenes/test_scene_haze.tscn +++ b/scenes/test_scene_haze.tscn @@ -4,7 +4,7 @@ [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://0ognvvq2ncd7" path="res://systems/visuals/animation_strip.gd" id="4_4oowd"] -[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://dntp60my5f65m" path="res://systems/bullets/bullet_behaviors/linear_motion_behavior.gd" id="4_t1bs8"] [ext_resource type="Texture2D" uid="uid://c21fe72aym3fe" path="res://graphics/bullets/normal_bullet/test_bullet.png" id="5_4oowd"] [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"] @@ -32,7 +32,7 @@ metadata/_custom_type_script = "uid://0ognvvq2ncd7" [sub_resource type="Resource" id="Resource_4oowd"] script = ExtResource("6_uu3sg") -bullet_count = 1 +radius = 32.0 metadata/_custom_type_script = "uid://dtuc6qerbfset" [sub_resource type="Resource" id="Resource_sle1e"] @@ -44,16 +44,15 @@ property_min_values = Dictionary[StringName, float]({ property_max_values = Dictionary[StringName, float]({ &"direction_rotation": 3.142 }) -iterations = 50 metadata/_custom_type_script = "uid://ckedfcjjnv7dq" [sub_resource type="Resource" id="Resource_hxqcc"] script = ExtResource("6_sle1e") behavior = SubResource("Resource_t1bs8") +hitbox_size = Vector2i(6, 6) base_graphics = Array[ExtResource("4_4oowd")]([SubResource("Resource_c0i5a")]) overlay_graphics = Array[ExtResource("4_4oowd")]([SubResource("Resource_1xo0o")]) 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_sle1e") rounds = 99999999 round_delay = 0.5 diff --git a/scenes/test_scene_penny.tscn b/scenes/test_scene_penny.tscn index 092ed52..79dfe04 100644 --- a/scenes/test_scene_penny.tscn +++ b/scenes/test_scene_penny.tscn @@ -4,7 +4,7 @@ [ext_resource type="PackedScene" uid="uid://c714s5d7d5765" path="res://objects/player/player.tscn" id="2_ikr60"] [ext_resource type="Script" uid="uid://cj2fj7snls8aa" path="res://systems/bullets/bullet_set.gd" id="3_hwssd"] [ext_resource type="Script" uid="uid://d238qii8i2byl" path="res://systems/bullets/spawn_patterns/line_pattern.gd" id="5_e0h7n"] -[ext_resource type="Script" uid="uid://dntp60my5f65m" path="res://systems/bullets/bullet_behaviors/simple_linear_behavior.gd" id="5_jwla8"] +[ext_resource type="Script" uid="uid://dntp60my5f65m" path="res://systems/bullets/bullet_behaviors/linear_motion_behavior.gd" id="5_jwla8"] [ext_resource type="Script" uid="uid://vus1a0flwtnm" path="res://systems/bullets/bullet_preset.gd" id="7_qckwa"] [ext_resource type="Texture2D" uid="uid://du7gh3nk66mpo" path="res://graphics/bullets/normal_bullet/bullet_1.png" id="9_6buwp"] diff --git a/systems/bullets/bullet.gd b/systems/bullets/bullet.gd index b028645..3df28bb 100644 --- a/systems/bullets/bullet.gd +++ b/systems/bullets/bullet.gd @@ -8,19 +8,21 @@ extends Area2D signal recycled() -# ## The number of bullets to allocate at startup. -#const INITIAL_ALLOCATED_BULLETS: int = 2000 +# cached shapes for each hitbox size +static var _hitbox_shapes: Dictionary[Vector2i, RectangleShape2D] = {} -## Texture to draw for the bullet. +## Base graphic/animation to display, modulated by [member color]. @export var base_graphic: AnimationStrip = null: set(value): base_graphic = value queue_redraw() _update_visibility_notifier() +## The color that [member base_graphic] will be modulated by. @export var color: Color +## Extra graphic drawn over [member base_graphic] and not modulated by [member color]. @export var overlay_graphic: AnimationStrip = null: set(value): overlay_graphic = value @@ -49,22 +51,13 @@ var time_elapsed: float = 0.0 ## Whether the bullet has already been grazed by the player. var grazed: bool = false -#static var _cached_bullets: Array[Bullet] = [] -static var _hitbox_shapes: Dictionary[Vector2i, RectangleShape2D] = {} - var _hitbox: CollisionShape2D = CollisionShape2D.new() ## Returns a new [Bullet], which may be sourced from the cached bullets. @warning_ignore("shadowed_variable") -static func create( - preset: BulletPreset, - direction: Vector2 = Vector2.RIGHT, -) -> Bullet: - #var bullet: Bullet = _cached_bullets.pop_back() - #if not bullet: - #bullet = Bullet.new() +static func create(preset: BulletPreset, direction: Vector2 = Vector2.RIGHT) -> Bullet: var bullet := Bullet.new() if not preset.base_graphics.is_empty(): @@ -84,21 +77,6 @@ static func create( return bullet -## Removes the bullet from the scene tree and returns it to the bullet cache to be -## re-used later. -func recycle() -> void: - #if is_inside_tree(): - #get_parent().remove_child(self) - #_cached_bullets.append(self) - queue_free() - recycled.emit() - - -#static func _static_init() -> void: - #for _i in INITIAL_ALLOCATED_BULLETS: - #_cached_bullets.append(Bullet.new()) - - func _init() -> void: monitoring = false collision_layer = 1 << 3 @@ -130,6 +108,13 @@ func _get_configuration_warnings() -> PackedStringArray: return [] +## Removes the bullet from the scene tree and returns it to the bullet cache to be +## re-used later. +func recycle() -> void: + queue_free() + recycled.emit() + + # sets the canvas item up to notify when it leaves the screen # this essentially mimics `VisibleOnScreenNotifier` without an additional node func _update_visibility_notifier() -> void: diff --git a/systems/bullets/bullet_actions/bullet_action.gd b/systems/bullets/bullet_actions/bullet_action.gd index 842d34c..423f341 100644 --- a/systems/bullets/bullet_actions/bullet_action.gd +++ b/systems/bullets/bullet_actions/bullet_action.gd @@ -1,6 +1,7 @@ @abstract class_name BulletAction extends Resource +## An action that a bullet can perform when triggered. ## Performs the action on a given [Bullet]. diff --git a/systems/bullets/bullet_behaviors/bullet_behavior.gd b/systems/bullets/bullet_behaviors/bullet_behavior.gd index 8c0e2f3..5fe6ae5 100644 --- a/systems/bullets/bullet_behaviors/bullet_behavior.gd +++ b/systems/bullets/bullet_behaviors/bullet_behavior.gd @@ -1,6 +1,7 @@ @abstract class_name BulletBehavior extends Resource +## Controls the movment and actions of a [Bullet]. @export_group("Actions", "action_") @@ -14,11 +15,14 @@ extends Resource @export var action_on_interval: BulletAction +var _bullet_delay_cooldowns: Dictionary[Bullet, float] = {} var _bullet_interval_cooldowns: Dictionary[Bullet, float] = {} ## Performs behavior-specific initialization for a [Bullet]. func init_bullet(bullet: Bullet) -> void: + if action_on_delay: + _bullet_delay_cooldowns[bullet] = action_delay if action_on_interval: _bullet_interval_cooldowns[bullet] = action_interval bullet.recycled.connect(deinit_bullet.bind(bullet), CONNECT_ONE_SHOT) @@ -27,20 +31,23 @@ func init_bullet(bullet: Bullet) -> void: ## Cleans up behavior-specific state for a [Bullet]. func deinit_bullet(bullet: Bullet) -> void: + _bullet_delay_cooldowns.erase(bullet) _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_delay and _bullet_delay_cooldowns.has(bullet): + _bullet_delay_cooldowns[bullet] -= delta + if _bullet_delay_cooldowns[bullet] <= 0.0: + _bullet_delay_cooldowns.erase(bullet) + 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 + action_on_interval.perform(bullet) _process_bullet(bullet, delta) diff --git a/systems/bullets/bullet_behaviors/simple_linear_behavior.gd b/systems/bullets/bullet_behaviors/linear_motion_behavior.gd similarity index 98% rename from systems/bullets/bullet_behaviors/simple_linear_behavior.gd rename to systems/bullets/bullet_behaviors/linear_motion_behavior.gd index df4ec44..4f253f5 100644 --- a/systems/bullets/bullet_behaviors/simple_linear_behavior.gd +++ b/systems/bullets/bullet_behaviors/linear_motion_behavior.gd @@ -1,4 +1,4 @@ -class_name SimpleLinearBehavior +class_name LinearMotionBehavior extends BulletBehavior ## Makes bullets move in [member Bullet.direction], potentially accelerating. diff --git a/systems/bullets/bullet_behaviors/simple_linear_behavior.gd.uid b/systems/bullets/bullet_behaviors/linear_motion_behavior.gd.uid similarity index 100% rename from systems/bullets/bullet_behaviors/simple_linear_behavior.gd.uid rename to systems/bullets/bullet_behaviors/linear_motion_behavior.gd.uid diff --git a/systems/bullets/bullet_preset.gd b/systems/bullets/bullet_preset.gd index 03a1e54..62d76cd 100644 --- a/systems/bullets/bullet_preset.gd +++ b/systems/bullets/bullet_preset.gd @@ -4,27 +4,43 @@ extends Resource @export_group("Bullets") +## Behavior used to control the motion and actions of the bullets. @export var behavior: BulletBehavior = null + +## Size in pixels of the bullets' hitboxes. +@export var hitbox_size: Vector2i = Vector2i.ZERO +## If [code]true[/code], the bullets will rotate to face their direction. +@export var face_direction: bool = false + +## Array of graphics that will be picked from randomly for +## each bullet and modulated by the picked color. @export var base_graphics: Array[AnimationStrip] = []: set(value): base_graphics = value if base_graphics.size() != overlay_graphics.size(): overlay_graphics.resize(base_graphics.size()) notify_property_list_changed() +## Array of graphics that will be picked based on the chosen graphic from +## [member base_graphics] and drawn over top without being modulated. @export var overlay_graphics: Array[AnimationStrip] = []: set(value): overlay_graphics = value if base_graphics.size() != overlay_graphics.size(): overlay_graphics.resize(base_graphics.size()) notify_property_list_changed() +## Array of colors that will be picked from randomly to +## modulate the graphic chosen from [member base_graphics]. @export var colors: Array[Color] = [Color.WHITE] -@export var hitbox_size: Vector2i = Vector2i.ZERO -@export var face_direction: bool = false + @export_group("Spawning") +## The pattern to use for positioning each "round" of bullets. @export var pattern: BulletSpawnPattern = null +## How many rounds of bullets to spawn before stopping. @export var rounds: int = 1 +## The time to wait after each "round" of bullets before spawning the next. @export var round_delay: float = 0.0 @export_group("Bullet Set") +## Behavior that controls the movement and actions of the [BulletSet]. @export var set_behavior: BulletSetBehavior = null diff --git a/systems/bullets/bullet_set.gd b/systems/bullets/bullet_set.gd index 766fd32..2301d09 100644 --- a/systems/bullets/bullet_set.gd +++ b/systems/bullets/bullet_set.gd @@ -2,10 +2,14 @@ class_name BulletSet extends Node2D +## Preset that determines how bullets are spawned, look, and behave. @export var preset: BulletPreset +## Offset in pixels from the set's [member position] where +## a [BulletSpawnPattern] should spawn bullets. var spawn_offset: Vector2 = Vector2.ZERO +## Offset from the set's [member rotation] that a [BulletSpawnPattern] should rotate itself by. var spawn_rotation: float = 0.0 diff --git a/systems/bullets/set_behaviors/bullet_set_behavior.gd b/systems/bullets/set_behaviors/bullet_set_behavior.gd index aba36b1..51cd2cc 100644 --- a/systems/bullets/set_behaviors/bullet_set_behavior.gd +++ b/systems/bullets/set_behaviors/bullet_set_behavior.gd @@ -1,6 +1,7 @@ @abstract class_name BulletSetBehavior extends Resource +## Controls the movement and actions of a [BulletSet]. ## Process one physics tick for a [BulletSet]. diff --git a/systems/bullets/set_behaviors/multi_set_behavior.gd b/systems/bullets/set_behaviors/multi_set_behavior.gd index 2a9cdcf..830afb1 100644 --- a/systems/bullets/set_behaviors/multi_set_behavior.gd +++ b/systems/bullets/set_behaviors/multi_set_behavior.gd @@ -3,6 +3,7 @@ extends BulletSetBehavior ## Processes multiple [BulletSetBehavior]s in order for the [BulletSet]. +## Behaviors to process for the [BulletSet]. @export var behaviors: Array[BulletSetBehavior] = [] diff --git a/systems/bullets/set_behaviors/random_spawn_set_behavior.gd b/systems/bullets/set_behaviors/random_spawn_set_behavior.gd index 18e1c7b..517c7d1 100644 --- a/systems/bullets/set_behaviors/random_spawn_set_behavior.gd +++ b/systems/bullets/set_behaviors/random_spawn_set_behavior.gd @@ -1,24 +1,29 @@ @tool class_name RandomSpawnSetBehavior extends BulletSetBehavior +## Randomizes the spawn position for each round of spawning. +## Minimum possible value of [code]spawn_offset[/code]. @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) +## Maximum possible value of [code]spawn_offset[/code]. @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) +## Minimum possible value of [code]spawn_rotation[/code]. @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) +## Maximum possible value of [code]spawn_rotation[/code]. @export_custom(0, "radians_as_degrees") var spawn_rotation_max: float: set(value): spawn_rotation_max = value diff --git a/systems/bullets/set_behaviors/rotation_set_behavior.gd b/systems/bullets/set_behaviors/rotation_set_behavior.gd index b798556..9389e0a 100644 --- a/systems/bullets/set_behaviors/rotation_set_behavior.gd +++ b/systems/bullets/set_behaviors/rotation_set_behavior.gd @@ -1,8 +1,11 @@ class_name RotationSetBehavior extends BulletSetBehavior +## Applies rotational motion to a [BulletSet]. +## Speed at which the set rotates, including existing child [Bullet]s and [BulletSet]s. @export_custom(0, "radians_as_degrees,suffix:°/s") var rotation_speed: float = 0.0 +## Speed at which the rotation offset of spawned bullet patterns will change. @export_custom(0, "radians_as_degrees,suffix:°/s") var spawn_rotation_speed: float = 0.0 diff --git a/systems/bullets/spawn_patterns/bullet_spawn_pattern.gd b/systems/bullets/spawn_patterns/bullet_spawn_pattern.gd index ff0a514..0606d5e 100644 --- a/systems/bullets/spawn_patterns/bullet_spawn_pattern.gd +++ b/systems/bullets/spawn_patterns/bullet_spawn_pattern.gd @@ -1,6 +1,7 @@ @abstract class_name BulletSpawnPattern extends Resource +## Defines the placement of spawned bullets. ## The amount of times to spawning this pattern for one "round". @@ -9,6 +10,7 @@ extends Resource @export_range(1, 1, 1, "or_greater") var iterations: int = 1 +## Creates and adds bullets to the passed [BulletSet]. func spawn_bullets(bullet_set: BulletSet, preset: BulletPreset) -> void: for _n in iterations: _spawn_bullets(bullet_set, preset) diff --git a/systems/bullets/spawn_patterns/line_pattern.gd b/systems/bullets/spawn_patterns/line_pattern.gd index 79f834a..8412d18 100644 --- a/systems/bullets/spawn_patterns/line_pattern.gd +++ b/systems/bullets/spawn_patterns/line_pattern.gd @@ -1,15 +1,19 @@ class_name LinePattern extends BulletSpawnPattern +## Spawns bullets evenly spaced out along a line segment. +## Number of bullets to spawn along the line. @export var bullet_count: int +## Distance between the first and last bullet in the line. @export var line_width: float +## The direction that spawned bullets will travel, orthogonal to the line of bullets. @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, line_normal) + var bullet = Bullet.create(preset, line_normal.rotated(bullet_set.spawn_rotation)) 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 1c479fb..ce4b051 100644 --- a/systems/bullets/spawn_patterns/ring_pattern.gd +++ b/systems/bullets/spawn_patterns/ring_pattern.gd @@ -1,10 +1,15 @@ class_name RingPattern extends BulletSpawnPattern +## Spawns bullets evenly spaced out around a circle. -@export var bullet_count: int -@export var distance_offset: float +## The number of bullets to spawn along the circle. +@export var bullet_count: int = 3 +## Radius of the circle that bullets spawn along the edge of. +@export var radius: float +## Rotation of the entire ring pattern. @export_custom(0, "radians_as_degrees") var angle_offset: float +## Rotation of each bullet's travel direction. @export_custom(0, "radians_as_degrees") var direction_rotation: float @@ -12,5 +17,5 @@ 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, Vector2.from_angle(angle + direction_rotation)) - bullet.position = bullet_set.spawn_offset + Vector2.from_angle(angle) * distance_offset + bullet.position = bullet_set.spawn_offset + Vector2.from_angle(angle) * radius bullet_set.add_bullet(bullet) diff --git a/systems/visuals/animation_strip.gd b/systems/visuals/animation_strip.gd index 3f1d796..49e4b9d 100644 --- a/systems/visuals/animation_strip.gd +++ b/systems/visuals/animation_strip.gd @@ -1,12 +1,19 @@ class_name AnimationStrip extends Resource +## A texture sliced into a number of horizontal frames and played at a +## certain fps. +## Texture containing all frames in one row. @export var texture: Texture +## Number of frames to slice the texture into. @export var frames: int = 1 +## How many frames should be displayed per second. @export var fps: float = 1.0 +## Draws the frame that should be visible at a given point in time. This must be +## called during the [method CanvasItem._draw] of [param canvas_item]. func draw(canvas_item: CanvasItem, time: float, modulate: Color = Color.WHITE) -> void: var frame_size = Vector2((texture.get_width() / frames), float(texture.get_height())) var current_frame = fmod(floorf(time * fps), frames)