further elaboration on bullets

This commit is contained in:
Haze Weathers 2025-12-30 23:34:19 -06:00
parent da9111bcf2
commit 393c3b670a
16 changed files with 218 additions and 29 deletions

View file

@ -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

View file

@ -0,0 +1 @@
uid://mivkgn34ox41

View file

@ -0,0 +1,7 @@
class_name DespawnAction
extends BulletAction
## Removes and recycles the [Bullet] when triggered.
func _perform(bullet: Bullet) -> void:
bullet.recycle()

View file

@ -0,0 +1 @@
uid://pn143vuxc7wp

View file

@ -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)

View file

@ -0,0 +1 @@
uid://mair8nsxn7lp

View file

@ -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)

View file

@ -0,0 +1 @@
uid://oug6n1t6tnor

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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:

View file

@ -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)

View file

@ -0,0 +1 @@
uid://d238qii8i2byl