Adventures in Ai
As I progressed with Captain Kaon (Greenlight this way), I needed to figure out some bad guy Ai. This was on the list of stuff I’d not done before and there are probably a fair few people out there in indieland who will find themselves in similar situation. Hopefully this little story will help anyone one looking to do Ai for their own indie game, failing that I hope it at least entertains. To see how this Ai ended you can find a download link to my latest alpha demo on my Greenlight page.
In my time as a tester I’d had many conversations with Ai programmers over bugs or in meetings. This had helped me to be aware of the kinds of things I needed to think about , although there would be a world of difference between my Ai and the strategic or battle Ai in Total War.
To help me be a better tester I had spent some time learning Ai, reading books and websites, writing little bits of code. It’s a useful thing to do that I recommend to any testers out there. The better you understand how something works under the hood, the better you are at breaking it and ruining a programmer’s day.
Getting ready to rumble
I needed to figure out what I wanted the Ai to do and then how I would get it to do it. Should it directly attack the player on its own? Should it back off until it’s in a group and then show the player whose boss? A good start for planning anything is to start asking questions to identify the things you need to know, so you can then then go out and find the answers.
What are the basic behaviours I would need? I could have the Ai be defensive. It could sit and guard positions from the player. You see this a lot in action games, bad guys dropped in to rooms to ensure there is someone in there to fight the player. They don’t really roam around much outside of a specific area.
I can also have the Ai be a little more pro-active and patrol around looking for the player. Make it follow a path and attempt to run into the player, so the player must always be alert. This would be simple and effective behaviour, but could I push it a little further?
I started thinking about all the Attenborough wildlife shows I liked to watch. Was there something in simple animal behaviours that I could mimic? Wolfs, Chimps, and other animals hunt in packs. They get into a simple formation where they each assume a role. Some will chase the prey to keep it on the move and separate it out. Others will move to the flanks to keep the prey boxed in. Maybe one will move ahead and ambush. I could look at giving the Ai different roles within a group.
Version 1, the headless chicken
The simplest behaviour you can have a bad guy do is move back and forth. It’s not particularly impressive, but sometimes you don’t need it to be. I created a basic spherical drone and gave it the ability to move along 8 different axes, I would then set the axis to be used and the distance they would travel when I placed them in the level. Initially I didn’t give them a gun; I wanted to focus on their movements first and build the Ai in layers, so I just made it damage the player if they touched.
When I played tested the level with this Ai I found that it just behaved like a moving hazard. This would have been fine if I were making a platform game where it would have provided a jumping challenge, but it wasn’t any good for me. They were far too passive; I needed enemies that responded to, and engaged with, the player.
Version 2, a change of direction
I created a waypoint object that I could place around the levels, each one held links to the other waypoint objects around them. When an Ai drone was created it would find the nearest waypoint, store it as its home point, then pathfind to it. Each time the Ai reached a waypoint it would then make a little decision about which way to go. To begin with I made it look to see if the waypoint was its home point, and if it wasn’t, it would then return to it. If it was at the home point it would then look at its list of waypoint links and pick one to pathfind to. The Ai would now move around the area where it was initially placed.
When I play-tested this behaviour I found that although it wasn’t as predictable as just going back and forth, the Ai was still limited to a small area.
I extended the range the Ai could go by logging each waypoint they passed through and giving them a range counter. Once the counter was hit they would go back along their route until they hit their home point and start again in a different direction.
This version of the Ai would effectively guard the point where they were initially deployed to and would then patrol around so that the player would encounter them in unexpected places. This was a good time to arm the Ai with laser guns and see how they handled the player.
Version 3, a little bit of brain
Once I had Ai that would move around and shoot the player it was time to kick them up a notch. As the Ai patrolled around the level it would switch to different states depending on the players’ actions.
So far, the Ai idly fired at the player whilst moving around, as if the gun knew the player was there but the body didn’t. I changed it so that if the player came close enough the Ai would leave its current patrol path and move towards the player. I did this by giving it the players’ coordinates as a position to pathfind to. It would then move to the player and if the player hovered, the Ai would appear to aggressively shunt them. If the player got far enough away the Ai would return to its patrol route, so it wasn’t dragged to far from the area it had been set to guard.
I also needed to give the Ai an awareness of the objectives they were guarding. When an Ai drone was created and it marked its home point; it would also find the nearest objective and log the waypoint next to it as its guard point. The Ai would then alternate between patrolling around and moving to its guard point to check on its objective.
This behaviour had a good balance of defending a location and chasing the player, but it didn’t react to direct plyer action. To fix this I added a ‘rage’ state. Depending on the objective, if it was attacked or stolen by the player the Ai would immediately stop their patrol and move to the players’ positon. I also gave the Ai a little speed boost so they could get there in a hurry.
Version 4, rank and file
The Ai’s behaviour didn’t look organised when they were actually engaging with the player. They would clump together, often on top of each other. I needed them to attack in a formation, spread out a bit, be a menace.
I created a set of positions around the player, mostly above and to the side so that they could shoot down on the player, I was hoping for a little psychological effect of ‘dominance’. I added one below the player and, just for fun, one on the players’ position. When the Ai approached the player they would pick one of the empty positions and sit on it.
This was effective, but too static. They would surround the player and shoot them, but effectively they just sat there while you destroyed them. I needed to add ways they could react aggressively and defensively.
I set the Ai to take turns making attack runs. Initially I set a point on the other side of the player that the Ai would move to it and then return from. This would cause it to move close to the player. It was pretty aggressive, but knocking the player around was also annoying. I changed it to create two points in a triangular loop around the player.
I then changed the formation to have two ranks. When the Ai was damaged it would drop back to the second rank and try and survive longer.
When I play tested this I found that the more complex the behaviour the more problems that were created. The two rank formation needed too much space to work. The Ai ended up bunched up and crammed in with the player. Also, the Ai tended to died too fast to retreat back a rank anyway. When they were taking hits and decided to move back, the position they would go to was still on a straight line with the bullets path and they would carry on getting hit.
I tried to fix this by adding a healing point that the Ai could flee to and get patched up. If you damaged Ai too much they would go there, heal, and then return. When I played this for the first time I realised it was pointless. The Ai drones are there to be cannon fodder to the player, they didn’t need to heal. It would be better if they died and were replaced.
So I created a spawner which would spew out new Ai frones to replace the ones the player had destroyed. I made it destructible so that you could completely eliminate the threat in the area of the level it was defending.
Version 5, a not so bright idea
Spine animation was integrated into Gamemaker and I started playing around with it. It’s pretty neat, if you use GameMaker you should check it out. I started using it for doors and other things, it gives you nice smooth animations without the need to draw lots of frames.
When I was playing around with it a little idea popped into my head, I could co-opt this animation system for formation structures, essentially making it a design tool for the formations. I could create an animated object that wasn’t visible, but had a series of bones marking the positions that the Ai would move to. This would replace the current formation that sat on the player. By then using different animations I could set the formation and by animate the formation, make the Ai move around within it.
I then changed the formations’ position so that instead of sitting on the player they moved between fixed positions and defended them.
When I play tested this it worked really well. The Ai now defended designated locations in an organised manner and then moved between them to react to the players’ movements.
Version 6, finishing off
I realised that using the animation system wasn’t gaining me anything. Animating the formation served no purpose and only one of the formations was of any use. I got rid of it and just had the formation object do the maths for the positions each step. There’s an old military maxim, Keep it simple, stupid, seemed to make sense at this point. When the formation was set it filled out an array with position data. During each step the new potions, relative to the rotation towards the player, were then calculated.
For the most part I’m happy with the way the Ai behave now, it’s simple and effective. They form an organised defense that challenges the player, whilst also being a wall of targets to be shot at. At this point it might be over-engineering to start adding anything else, changes would need to be made carefully.
The one potential change I might make is to allow the formation to move around within the area it has been placed. In a rectangular room I have to place the formation in the centre so that it can cover the room. I need to allow the formation to move along the room and follow the player.
Another thought I’ve had is to have an object in overall control of the Ai. It could look at the players positions, the Ai positions, and the objectives and would then tell the Ai which way to go. This would make the Ai much more organised. When I added the piece of script that the spawner uses to track the Ai it had spawned, I created it with a little bit of space to add issuing commands, if I wanted to go back and do that. Ultimately I wondered if there were any commands that would be effective, and would it be worth the time and effort? I suspect that it wouldn’t make the game any more fun from the players perspective, so it’s on the maybe-probably-not pile.
The final Ai
I have a spawner object which holds the id of a formation object, it spawns Ai drones and assigns them to the formation object. The Ai drone then gets a slot in the formation from the formation object and pathfinds to its assigned position.
The formation object has a list of ids for position markers. It checks which is closest to the player and then snaps to that location. The positon marker that the formation moves to determines the available space around it when it is created. It then passes this information on to the formation object so that it can adjust the radius of its formation.
This system allows me to determine which areas in the level are defended, or are ‘combat areas’, and which are for flight puzzles or some other kind of gameplay. It allows the Ai to defend key areas of levels in an efficient way.
In the end I didn’t need an Ai that was devious or tried to outwit the player. It didn’t need to be complex or ambitious. Captain Kaon is an action game. The Ai just needed to defend areas from the player in groups that were large targets for the player to shoot.
So there it is, the story of my first go at doing some ai. If you’d like to see how it turned out and want to support my indie journey, please visit my Greenlight here.