yes, they canjj st!
This commit is contained in:
parent
6b92473eeb
commit
a6421235f8
22 changed files with 510 additions and 14 deletions
|
|
@ -1,17 +1,22 @@
|
|||
@tool
|
||||
@icon("bullet.svg")
|
||||
class_name Bullet
|
||||
extends Area2D
|
||||
|
||||
|
||||
static var _hitbox_shapes: Dictionary[Vector2i, RectangleShape2D] = {}
|
||||
## The number of bullets to allocate at startup.
|
||||
const INITIAL_ALLOCATED_BULLETS: int = 2000
|
||||
|
||||
|
||||
@export var texture: Texture2D:
|
||||
## Texture to draw for the bullet.
|
||||
@export var texture: Texture2D = null:
|
||||
set(value):
|
||||
texture = value
|
||||
queue_redraw()
|
||||
_update_visibility_notifier()
|
||||
|
||||
@export var hitbox_size: Vector2i:
|
||||
## Size of the bullet's collision box.
|
||||
@export var hitbox_size: Vector2i = Vector2i.ZERO:
|
||||
set(value):
|
||||
hitbox_size = value
|
||||
if not _hitbox_shapes.has(hitbox_size):
|
||||
|
|
@ -20,18 +25,100 @@ static var _hitbox_shapes: Dictionary[Vector2i, RectangleShape2D] = {}
|
|||
_hitbox_shapes[hitbox_size] = new_shape
|
||||
_hitbox.shape = _hitbox_shapes[hitbox_size]
|
||||
|
||||
## The direction that the bullet is travelling.
|
||||
@export_custom(0, "direction") var direction: Vector2 = Vector2.RIGHT
|
||||
|
||||
## If [code]true[/code], the bullet will always rotate to face toward [member direction].
|
||||
@export var face_direction: bool = false
|
||||
|
||||
|
||||
## The amount of time in seconds that the bullet has existed.
|
||||
var time_elapsed: float = 0.0
|
||||
|
||||
|
||||
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(
|
||||
texture: Texture2D = null,
|
||||
hitbox_size: Vector2i = Vector2i.ZERO,
|
||||
direction: Vector2 = Vector2.RIGHT,
|
||||
face_direction: bool = false,
|
||||
) -> Bullet:
|
||||
var bullet: Bullet = _cached_bullets.pop_back()
|
||||
if not bullet:
|
||||
bullet = Bullet.new()
|
||||
|
||||
bullet.texture = texture
|
||||
bullet.hitbox_size = hitbox_size
|
||||
bullet.direction = direction
|
||||
bullet.face_direction = face_direction
|
||||
bullet.time_elapsed = 0.0
|
||||
|
||||
return bullet
|
||||
|
||||
|
||||
## 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)
|
||||
|
||||
|
||||
static func _static_init() -> void:
|
||||
for _i in INITIAL_ALLOCATED_BULLETS:
|
||||
_cached_bullets.append(Bullet.new())
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
monitoring = false
|
||||
add_to_group(&"bullets")
|
||||
_hitbox.debug_color.a = 0.0
|
||||
add_child(_hitbox)
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
_update_visibility_notifier()
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not Engine.is_editor_hint():
|
||||
time_elapsed += delta
|
||||
|
||||
if face_direction:
|
||||
rotation = direction.angle()
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
draw_texture(texture, -texture.get_size() * 0.5)
|
||||
if texture:
|
||||
draw_texture(texture, -texture.get_size() * 0.5)
|
||||
|
||||
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
return []
|
||||
|
||||
|
||||
# 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:
|
||||
if not texture or not is_inside_tree() or Engine.is_editor_hint():
|
||||
return
|
||||
|
||||
# the visibility rect is set to twice the size of the texture to add a little margin
|
||||
# (func(): pass) is the cleanest way i could think of to have a callback that does nothing
|
||||
RenderingServer.canvas_item_set_visibility_notifier(
|
||||
get_canvas_item(), true,
|
||||
Rect2(-texture.get_size(), texture.get_size() * 2.0),
|
||||
(func(): pass), _on_screen_exited
|
||||
)
|
||||
|
||||
|
||||
# called when the bullet leaves the screen.
|
||||
func _on_screen_exited() -> void:
|
||||
recycle()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue