So last post I showed how mages can recover from a collision now.
But what if there never was a collision to begin with?
The necromancer did not move, the battlemage should’ve walked around them.
I’ve already added four steering behaviors, avoidance surely can’t be that different?
The two hardest parts of pathfollowing were avoidance and arrival.
-SC2 devs at GDC
Collision Avoidance
Craig Reynolds included avoidance steering in his paper as well, but Dave Leaver had an incredibly digestible explanation of the avoidance algorithm that I recommend reading. His explanation will be leagues better than mine with real code examples.
The rough outline:
- Check for collisions in the direction you’re traveling.
- If there’s a potential collision, turn to avoid it.
- If the collision is another moving unit (non-static), negotiate which direction to turn.
- The magnitude of the force to turn should be determined by how imminent the collision is.
My first attempt did not seem to work right. Note the debug arrow I added that shows the force applied to the mage.
I spent slightly more time to add what I’m calling my Scribble
system.
I can make arbitrary shapes and specify how long they should be rendered. I knew this would be difficult
to debug without a visual representation.
So I can now just draw shapes I need to debug, in this case, the raycast for looking ahead.
// snippet of code from the CollisionAvoidance force calculation
boolean empty = min.closest == null;
// Scribbles made it easy to just throw debug shapes on screen.
DebugRenderSystem.Scribble((shapes) -> {
// draw casting lines, color them red if I detect a future collision
shapes.setColor(empty ? Color.LIME : Color.RED);
shapes.triangle(position, lx + finalRayX, ly + finalRayY, rx + finalRayX, ry + finalRayY);
}, ShapeRenderer.ShapeType.Line);
To summarize hours of pain; it turned out that my raycast algorithm had problems.
And many more hours later… It worked!
This implementation worked fairly well, but mages had issues of avoiding obstacles beyond their destination, so I added a destination cap to the look-ahead raycast.
I also had to lerp direction of sprites to avoid them spamming direction changes in a few rare specific cases.
Oh, and my spells accidentally were pathfollowing…
If I want these mages to succeed the hallway gauntlet, however, unit avoidance is not enough. I will need static object avoidance. Mages are far too willing to run into walls and pillars.
But at least now they’re friends.