Can somebody explain why my steering code (well, @2darray's mostly) sometimes goes bananas and sine's itself off-screen rather than heading to the next waypoint? It only happens occasionally and I can't see why and always to the left.

Cart #nokikfiyu-1 | 2019-05-09 | Code ▽ | License: CC4-BY-NC-SA

Sometimes it'll do this...

Would greatly appreciate any help and a math explanation. It seems to happen more often if I decrease the turning speed from say

 ```turnspeed=2*(pi/180) ```

to

 ```turnspeed=0.5*(pi/180) ```

but that doesn't explain the example gif because the distance between node 5 and 6 is quite far.

Edit: I've uploaded a version with a simpler sprite and a vector to show the current target node.

P#64258 2019-05-09 13:58 ( Edited 2019-05-09 14:57)

1

If you stick srand(1) in _init(), it'll generate a breaking path on the first try.

When the object has to move almost straight to the right, the target angle is either almost 0 or almost 1 depending on whether it's above or below the destination. When it's below the target, diff is low, so it turns right. Then as soon as it's above the target, diff jumps to a high value, so it turns left. And so on.

It's a small change to work around that: just normalize the difference and compare against 180°. Try this:

 ```function update_invader_steer() local dx=invader.tx-invader.x local dy=invader.ty-invader.y invader.tangle=atan2(dx,dy) invader.diff=(invader.tangle-invader.rotation)%1 if invader.diff<=invader.turnspeed then invader.rotation=invader.tangle elseif invader.diff<0.5 then invader.rotation+=invader.turnspeed else invader.rotation-=invader.turnspeed end invader.rotation%=1 add(invader.trails,{x=invader.x,y=invader.y}) invader.x+=cos(invader.rotation)*invader.speed invader.y+=sin(invader.rotation)*invader.speed if distance(invader.x,invader.y,invader.tx,invader.ty)<=1.5 then next_node(invader,path) end end ```

Note also that there's no need to involve pi; angles in P8 are [0, 1). invader.rotation%=1 is all it takes to keep it in range.

That's slightly asymmetrical - invader.diff<=invader.turnspeed only checks if it's in range in one direction - but the difference it makes is probably too insignificant to justify using more tokens.

P#64267 2019-05-09 18:12

That's brilliant - thank you so much. I was tearing my hair out :)

P#64271 2019-05-09 19:34