Last active
January 8, 2020 00:34
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Known issues: