Cakestax Ok. I'd prefer doing this directly in _process(), but since you started designing it with coroutines here's a coroutined version. I added attenuation as well as it's a common need for shakes.
This is a Shake class. It's a 2D version but you can easily extend it to 3D. Try it with a sprite first.
You instantiate it and call start() with all needed parameters. It'll run as a coroutine until time is up or you explicitly call stop()
class_name Shake extends RefCounted
var run = false
func start(node, pivot, amplitude, speed, duration, attenuation = 1.0):
run = true
var time = 0.0
var direction = Vector2.from_angle(randf_range(0, PI*2.0))
while(run):
# calculate camera position to tween to
direction = direction.rotated(randf_range(PI/2.0, PI*3.0/2.0)) # rotate direction vector by random angle in range 90-270 deg
var shake_offset = direction * amplitude * (1.0 - attenuation*time/duration) # multiply direction by (attenuated) amplitude
var shaken_pos = pivot + shake_offset # absolute offset position
# tween it and wait for tween to finish
var t = node.get_tree().create_tween()
t.tween_property(node, "position", shaken_pos, node.position.distance_to(shaken_pos) / speed )
await t.finished
# did we reach time limit?
time += t.get_total_elapsed_time()
if time > duration:
break
# reset to pivot position after the shake is done
node.position = pivot
func stop():
run = false
Test usage from a sprite node:
extends Sprite2D
var s
func _input(e):
if e is InputEventMouseButton and e.is_pressed():
if e.button_index == MOUSE_BUTTON_LEFT:
s = Shake.new()
s.start(self, self.position, 10, 800, 2)
if e.button_index == MOUSE_BUTTON_RIGHT:
s.stop()