Hey!
I just can’t wrap my head around how quaternions and radians work and I would love some help with a function how to make one game object turn towards another game object along the Z-axis (making a strict 2D game).
Also I’d love to use the animation system to achieve this!
Thanks so much in advance!
1 Like
Hey!
Take the positions from both things, do target - source to get the delta, put that into math.atan(y, x) which gives you the angle (radians), and put that into vmath.quat_rotation_z(angle) to get the quat, and do go.set_rotation using that. You might need to normalize the delta, I don’t remember. The best way to test would be to use the mouse/touch as the target so you can move around and see you get the correct quat. Make sure to test for when both positions are the same, the lua-docs says that atan can deal with 0, but I would be suspicious about that. 
1 Like
I just thought if we didn’t have anything simpler, and there is of course vmath.quat_from_to. To get the direction of a thing, take the rotation and use that with vmath.rotate and the vector (1, 0, 0).
This is what my code looks like:
local y = go.get_position().y - newmousePos.y
local x = go.get_position().x - newmousePos.x
local angle = math.atan2(y, x)
go.animate("main:/collision", "rotation", go.PLAYBACK_ONCE_FORWARD, vmath.quat_rotation_z(angle), go.EASING_LINEAR, 0.5)
And the video below is the result, Why does the thing change size when it rotates sometimes? 
2 Likes
I would assume it is because the animation lerps the quaternion, which makes the quaternion non-normalized. Instead you could try to animate the euler angle of the thing (euler is expressed in degrees around each axis):
go.animate("main:/collision", "euler.z", go.PLAYBACK_ONCE_FORWARD, angle * 180 / math.pi, go.EASING_LINEAR, 0.5)
There might however be a different problem then, when going across the circle. For example from 120 -> -120 degrees will animate across the zero-degree mark, rather than crossing the 180/-180 degree mark. A way to fix this is to check if the amount (abs-diff) between the angles is larger than 180, if so adjust the desired angle so that the lerping moves in the desired direction.
1 Like
Nice! That looks so much better!
This abs-diff is a little over my head though…
What would a piece of code look like that checked if the angle is over 180? And how would I adjust the angle so that it’s still pointing the right direction but still Lerps the right way?
1 Like
Great to hear! With abs-diff I just meant math.abs(target_angle - source_angle). That was vague of me, sorry. 
You can adjust any angle by +/- 360 and it describes the same angle. It is however another numerical value, which is important for the anim. The anim does not care about rads/degrees/quats, but purely numerically turns one number into another. So what you need to do is to make sure the angles are numerically suitable for anim. In the case I mentioned before, source= 120 and target= -120, the anim would go:
120 … 60 … 0 … -60 … -120. But you would probably like it to cross the 180/-180 point, so by adjusting the target: -120 + 360 = 240, the anim would now do: 120 … 150 … 180 … 210 … 240. I will leave the rest to you to figure out because practice is always good.
The best way is to make use of the hot-reload, debug-printing and tie one of the points to input (like you already did), so that you can quickly experiment and learn more how it works. The euler the thing currently has can be retrieved through go.get(“euler.z”) so you can print it in the update or something if you want to know what’s going on.
3 Likes