Log In  

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 ▽ | Embed ▽ | 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

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-28 19:25:07 | 0.018s | Q:15