107 lines
2.9 KiB
GDScript
107 lines
2.9 KiB
GDScript
extends AnimatedSprite
|
|
|
|
enum { RIGHT, DOWN_RIGHT, DOWN, DOWN_LEFT, LEFT, UP_LEFT, UP, UP_RIGHT }
|
|
|
|
export (int) var threshold = 5 # Range to snap around axis direction, in degrees.
|
|
export (String, "bus", "police", "car") var skin = "car"
|
|
var sprite := UP
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
func _ready():
|
|
set_animation(skin)
|
|
|
|
func _process(delta):
|
|
"""
|
|
The sprite contains a representation of rotation in its own, so we need to tweak things.
|
|
In particular, the sprite inherits orientation from its parent (TrackFollow) that must be canceled.
|
|
"""
|
|
var global = get_global_rotation_degrees()
|
|
var local = get_rotation_degrees()
|
|
var total = wrapf(global - local, -180.0, 180.0)
|
|
var r = snap_rotation(total)
|
|
if _update_sprite(r):
|
|
#print_debug("frame changed")
|
|
set_frame(sprite)
|
|
# We can just cancel out the "part of" the rotation
|
|
# embedded in the sprites, leaving out a small
|
|
# rotation for dynamic effect...
|
|
#set_rotation_degrees(-r)
|
|
# ...Or we just cancel out everything
|
|
set_rotation_degrees(-total)
|
|
|
|
|
|
func snap_rotation(r):
|
|
"""
|
|
Snap rotation to multiples of 45°
|
|
Also snaps within a certain range of direction axis
|
|
"""
|
|
if r >= 0 - threshold and r <= 0 + threshold: # Right
|
|
r = 0
|
|
elif r >= 180 - threshold or r <= -180 + threshold: # Left
|
|
r = 180
|
|
elif r >= 90 - threshold and r <= 90 + threshold: # Down
|
|
r = 90
|
|
elif r >= -90 - threshold and r <= -90 + threshold: # Up
|
|
r = -90
|
|
elif r > 0 + threshold and r < 90 - threshold:
|
|
r = 45
|
|
elif r > 90 + threshold and r < 180 - threshold:
|
|
r = 135
|
|
elif r > -90 + threshold and r < 0 - threshold:
|
|
r = -45
|
|
elif r > -180 + threshold and r < -90 - threshold:
|
|
r = -135
|
|
return r
|
|
|
|
|
|
func _update_sprite(rotation):
|
|
"""
|
|
Updates the sprite index given direction of movement.
|
|
Returns true if sprite was updated, false otherwise.
|
|
"""
|
|
var previous = sprite
|
|
# Use a specific algorithm according to difficulty mode
|
|
#__set_sprite_from_direction(round(direction.x), round(direction.y)) ## if abs(direction.y) > 0.1 else 0
|
|
__set_sprite_from_rotation( rotation )
|
|
return previous != sprite
|
|
|
|
|
|
func __set_sprite_from_direction(x, y):
|
|
""" Set the matching sprite according to given direction vector """
|
|
if x != 0 and y != 0:
|
|
if x < 0 and y < 0:
|
|
sprite = UP_LEFT
|
|
elif x < 0 and y > 0:
|
|
sprite = DOWN_LEFT
|
|
elif x > 0 and y < 0:
|
|
sprite = UP_RIGHT
|
|
elif x > 0 and y > 0:
|
|
sprite = DOWN_RIGHT
|
|
elif x != 0:
|
|
if x < 0:
|
|
sprite = LEFT
|
|
else:
|
|
sprite = RIGHT
|
|
elif y != 0:
|
|
if y < 0:
|
|
sprite = UP
|
|
else:
|
|
sprite = DOWN
|
|
|
|
|
|
func __set_sprite_from_rotation(r: int):
|
|
""" Set the matching sprite according to given rotation (in degrees) """
|
|
match r:
|
|
0: sprite = RIGHT
|
|
45: sprite = DOWN_RIGHT
|
|
90: sprite = DOWN
|
|
135: sprite = DOWN_LEFT
|
|
180, -180: sprite = LEFT
|
|
-45: sprite = UP_RIGHT
|
|
-90: sprite = UP
|
|
-135: sprite = UP_LEFT
|
|
|
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
#func _process(delta):
|
|
# pass
|