While working on my game Biplane Racer, I had to code the AI. To summarize, its a 2d racing/platformer side scroller.
First, I had to determine the requirements that I wanted.
Why do my NPCs need to travel through the level?-It’s a race. They need to reach the finish line, duh.
How should they travel through the level?-The same way the player does. They are a player object, but controlled by the CPU. From the left of the level to the right of the level.
How do you travel in the level? By pressing up and down, gaz/break. You have to try and dodge other objects that stops or hurt you (like other players, walls, traps, hazards). This is the most basic things the AI needs to do (I won’t get in much details for the power-ups or other stuff like personality behavior.)
Possible options:-You could do pathfinding. Identify the locations that are safe to travel and then plan a course towards the safest path. Adjusting your direction and speed by faking key presses to move towards the planned path.-You could determine the “best line” through your racing path by calculating the areas between the outline of the track-You could just move forward trying to dodge any “blockers” you encounter-You could use a waypoint to move towards
This is probably the most perfect solution mathematically. However, it is not good at all in a game environment that needs to move dynamically. It also feels very unnatural as it predicts everything and feels “too” perfect. When I tested a solution using this, it was also very intensive cpu wise because it tested too much (goes with the “too perfect solution”).
Best line solution:
I have only tested a very short situation to try this solution and I did not like. It was too much work for little result (seeing as I am developing by myself, time is a big factor of design choices). This is one of the solution I would like to experiment if it was the only thing I had to work on.
Move forward and dodge everything:
Straightforward solution, don’t think about anything, just go forward and if you encounter objects just try to dodge them. This is easy enough to implement, but the results are just bad. However, it creates a lot of chaos and unexpected situations (which is good!)
This solution provided to be very quick and easy to implement and provided similar result to the “best line” solution. However, waypoints alone feel wonky and awkward even less than a perfect pathfinding.
So then I added variations, here and there, on waypoints. It improved results, but then, it was still too conformist and still felt robotic.
The obvious solution is perhaps the one we look at last right? Why don’t I combine all the things I like about all those methods?
By using Waypoints, I “crafted” my best line in order to have a “target” where the AI needs to go while detecting potential collisions with close objects using short vectors to dodge up and down. The dodge direction(temporary target routes) would be determined using minimal pathfinding (very short range, instead of predicting everything) and gave a more “chaotic” feeling to the AI decisions.
Among other things, I also added “types” of waypoints, powerups to use, character personality, to add more variety and chaos!
TLDR: When determining pathfinding/AI movement behavior, it is best to look at what your game needs and adapt your solution for the main purpose of generating fun rather than the “best” solution out there. I would even say; the less perfect it is, the better (ofc it has to work with your game and feel good).
There are many resources out there on AI/Steering Behavior and there are so many things to read. (My best reads on the topic I found at http://www.red3d.com/cwr/steer/)
AI is one of the most interesting topics, and you can do so much with it its lovely. <3