Implementing this successfully can be a nightmare.
There are a LOT of things you have to consider when you wait until the very last second to smooth as this function does.
- The "fancy stick" this method uses is supposed to originate from your position next turn, but since you only have your current heading and your requested heading, your guess for next turn's position will not be very accurate. So you have to take the maximum of the two, and even then it doesn't work perfectly. The only way I found to make this method work so far without iteration is to just assume that next turn I will be 8 units closer to the wall. This gets me within 8 units of the wall, with the occasional closer margin based on current movement.
- If you're in the middle of changing directions, you have to smooth the opposite of your requested heading until you finish changing directions. For instance, if you were driving your car fast in reverse next to a wall, you would wait until you finished braking before you turned away from the wall, otherwise you would just cut your wheels and smash into the wall.
- You have to smooth against all four directions. Imagine an enemy close to the top edge of the field, and you are moving to the right, a little ways below him. You want to orbit counterclockwise, so you start to move up, approaching vertical. If the enemy is very close to the wall, the listed code will not start smoothing until you reach vertical movement, far too late for smoothing.
Those are some 'gotchas' indeed! Particularly that middle one - it will take some integration between the smoothing and direction code to know to reverse but not turn until the robot velocity changes signs.
Lately, I've really been thinking about minimum-risk type movement. If you generate a bunch of movement options and then simulate them, it is easy to see whether they hit the wall. The trick is generating points which are likely to produce good movement options without having to generate millions of points.
Yeah, Diamond's Melee movement just precise predicts 5 ticks out and discards any movement option that hits a wall. It looks butter smooth and I love watching it.
But I once tried augmenting my existing 1v1 wall smoothing with this trick. In the end, the code was horribly ugly, I never hit a wall, and I didn't gain any points from it. Kind of killed my spirit to find points in improved wall smoothing. (And I removed it.)
And really, sometimes maximizing escape angle means slamming into the wall at full speed. If it means dodging a bullet it's still the right move.
Combat uses precise prediction to avoid walls in melee. It doesn't start turning until the very last tick.
It is iterative, which isn't a problem when combined with anti-gravity movement. Predicts 45 ticks ahead in 4 directions: forward/clockwise, forward/counter-clockwise, backward/clockwise and backward/counter-clockwise.
Predicts all 4 of them if starting to turn the current tick and again if wall avoidance is delayed to the next tick. If simulation shows delaying wall avoidance hits a wall then it starts turning, otherwise, keep with current movement.
It is still not calculating accurately when to stop turning and Combat zig-zags when moving parallel to walls. Looks ugly, but at least confuses opponents which relies heavily on heading in their targeting, like displacement vectors, PIF and segmenting data based on forward distance to walls.