After extensive research in path-finding algorithms, I decided upon the ubiquitous A*. Then, after days of trying to implement it, using many different techniques from just simple std::vector<Node*> lists to a much more complex and efficient std::priority_queue<Node> binary heap, I gave up. None of them worked properly, obviously due to faults in my programming, but I simple couldn't figure it out.
So I settled on a different approach: pre-defined movement paths. Obviously, this would significantly dumb-down AI decision-making, but I had to at least get something working. The map worked fine, but, again, after days of tweaking and planning and modifying, I couldn't even get the enemy tank to follow the path. I used a rather strange approach with lots of vector math and collision detection, which probably wasn't necessary. The algorithm (in pseudo-code) looked something like this:
Target = FindNearestPath
End
Update:
If reached Target
Target = FindNextTile
If no Target
Turn 3 degrees
Else
Adjust angle and drive.
End
FindNearestPath:
Find tile with minimum distance to entity.
Return tile
FindNextTile:
For each tile in AI map
If tile collides with line-of-sight
and tile not collides with entity
Return tile
Return no tile
Basically, that's what would happen every frame. If a target couldn't be found, the enemy would keep turning in a circle until its line-of-sight (a line segment with a length of 64 pixels protruding out from the front-center of the tank) hit a tile, then the tank would move towards it. As with anything, it didn't go exactly as expected. First, my vector-line-rect collision detection was extremely wrong. I spent near 2 days trying to figure it out. I used many techniques, most of them based on vector cross products and whatnot, but ended up going with a much simpler algebraic approach. I just determined the infinite line equation of the two line segments and found their intersection point. Then I checked if the intersection point was in the range of the line segments. If it was, there's a collision! If not, well, no collision, obviously. The source code looks like this, if anyone is interested:
Well, after jumping through all of these hurdles, I decided that it's time to take a look at A* and dynamic path-building/finding. Hopefully with this optimized collision detection approach that doesn't involve dozens of tiny rectangles representing a line, A* combined with line-of-sight target location will be much more effective.
No comments:
Post a Comment