Skip to content

Instantly share code, notes, and snippets.

@luizcarlos1405
Last active January 8, 2020 00:34
Show Gist options
  • Save luizcarlos1405/5ab7d951e65b54ab92a7809ddfe14771 to your computer and use it in GitHub Desktop.
Save luizcarlos1405/5ab7d951e65b54ab92a7809ddfe14771 to your computer and use it in GitHub Desktop.
Creates a trail of copies of the parent node's texture. The parent can be a Sprite or an Animated Sprite
tool
extends Node2D
class_name SpriteTrail
# Add a trail of copies of the parent's texture.
#
# Works as child of Sprite or AnimatedSprite.
# The `_trail_copies` variable has information about the copies as dictionaries
# in the following format:
# {
# global_position, # (Vector2) The global position of this copy
# texture, # (Texture) A reference to the texture used in this copy
# remaining_time, # (float) Remaining time until it disappears
# transform_scale, # (Vector2) x = -1 if flip_h and y = -1 if flip_v, else both = 1
# }
# This works by using `draw_texture` method to draw copies of the parent's
# texture. If it is an AnimatedSprite it records the current frame's texture.
# There is a problem when flipping the sprite, the flipping doesn't occur when
# calling `draw_texture`. So there is a work-arround setting the draw_scale as
# -1 and then correcting the positions for the new transform.
export var active: = true setget set_active
export var life_time: = 0.6
export var fake_velocity: = Vector2(0, 0)
export var copy_period: = 0.2
export var gradient: Gradient
export var behind_parent: = true setget set_behind_parent
var _trail_copies: = []
var _elapsed_time: = 0.0
onready var sprite: Node2D = get_parent()
func _ready() -> void:
set_active(active)
show_behind_parent = behind_parent
func _process(delta) -> void:
if active:
_elapsed_time += delta
process_copies(delta)
if _elapsed_time > copy_period and active:
spawn_copy(delta)
_elapsed_time = 0.0
update()
func _draw() -> void:
for i in _trail_copies.size():
var copy: Dictionary = _trail_copies[i]
# We need to correct the direction if the scale is set to -1, see
# spawn_copy method.
var draw_translation: Vector2 = (to_local(copy.global_position) + sprite.offset) * copy.transform_scale
if sprite.centered:
draw_translation -= copy.texture.get_size() / 2.0
var draw_transform = Transform2D(0.0, Vector2()) \
.scaled(copy.transform_scale) \
.translated(draw_translation)
draw_set_transform_matrix(draw_transform)
draw_texture(
copy.texture,
Vector2(),
calculate_copy_color(copy)
)
func process_copies(delta: float) -> void:
for copy in _trail_copies:
copy.remaining_time -= delta
if copy.remaining_time <= 0:
_trail_copies.erase(copy)
continue
copy.global_position -= fake_velocity * delta
if _trail_copies.empty() and not active:
set_process(false)
func get_texture(sprite: Node2D) -> Texture:
if sprite is Sprite:
return sprite.texture
elif sprite is AnimatedSprite:
return sprite.frames.get_frame(sprite.animation, sprite.frame)
else:
push_error("The SpriteTrail has to have a Sprite or an AnimatedSpriet as parent.")
return null
func calculate_copy_color(copy: Dictionary) -> Color:
if gradient:
return gradient.interpolate(range_lerp(copy.remaining_time, 0, life_time, 1, 0))
return Color(1, 1, 1)
func spawn_copy(delta: int) -> void:
var copy_texture: = get_texture(sprite)
var copy_position: Vector2
if not copy_texture:
return
if sprite.centered:
copy_position = sprite.global_position# - copy_texture.get_size() / 2.0 * sprite.scale
else:
copy_position = sprite.global_position
# This is needed because the draw transform's scale is set to -1 on the flip
# direction when the sprite is flipped
var transform_scale: = Vector2(1, 1)
if sprite.flip_h:
transform_scale.x = -1
if sprite.flip_v:
transform_scale.y = -1
var trail_copy: = {
global_position = copy_position,
texture = copy_texture,
remaining_time = life_time,
transform_scale = transform_scale,
}
_trail_copies.append(trail_copy)
func set_active(value: bool) -> void:
active = value
if active:
set_process(true)
func set_behind_parent(value: bool) -> void:
behind_parent = value
show_behind_parent = behind_parent
@luizcarlos1405
Copy link
Author

luizcarlos1405 commented Jan 4, 2020

Known issues:

  • Doesn't work with Sprite region.
  • Doesn't work with sprite frame, hframes and vframes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment