Basic AI

This tutorial teaches you the logic of a simple AI system for a top-down shooter. Since making a good top-down shooter takes some skill, I'll assume that you know what you're doing. So if you haven't gotten your game's basic movement and shooting down this tutorial probably isn't for you.

Getting Started
First, we need to think about what we want our AI to do for us. For this tutorial, we'll make an AI that runs around and tries to shoot the player while strafing keeping his own health above a set minimum. The AI will also have a setting that adjusts the accuracy of its shots. Next, let's outline the environment our AI has to live in. Let's assume you have walls, ammo and health. To help our AI navigate, you need to set up an A* pathfinding system. The A* algorithm uses a grid to find the shortest route around obstacles, and it does this by examining a grid. The result of the algorithm is stored in a path. I recommend that you use the potential step method once the AI is close to the target. I will assume that you can make your own A* algorithm, but I have included a basic example in case you are having trouble.

Scripts
scr_ai_init

globalvar bot_health; //declare our bot's   //health as a global var //A* setup code //init vars bot_health = 100; bot_ammo = 25;

(You'll need to integrate bot_ammo into your shooting system.)

Now that you have your pathfinding set up, we need to decide how we want to design our AI's brain. We'll use a variable status to indicate what the bot's current objective is. The status actions are arranged by priority, with 0 being the lowest and 4 being the highest. This code should be in the initialization script.

//status variable //0 means doing nothing //1 means finding the enemy //2 means engaging the enemy //3 means looking for ammo //4 means looking for health status = 0; //the bot starts doing nothing

scr_ai_brain

Now let's make a main script that is run on a repeating alarm or when certain events trigger it. The script will check the bot's priorities and current environment to see if the status need changed. I'll leave the movement up to you, since there are so many different ways you could have implemented your movement.

//scr_ai_brain var cenemy; //closest enemy cenemy = instance_nearest(x,y,obj_enemy); if status == 0 //if doing nothing {   if bot_health < 30 then {scr_ai_health;exit} else if bot_ammo < 10 then {scr_ai_ammo; exit} else if point_distance(x,y,cenemy.x,cenemy.y) < 100 then {scr_ai_engage; exit} else scr_ai_find; }   if status == 1 //if finding the enemy {   if point_distance(x,y,cenemy.x,cenemy.y) < 100 then scr_ai_engage; //adjust distance // as needed //some sort of stuck movement checker here else {exit} }   if status == 2 //if engaging the enemy {   if bot_health < 30 then {scr_ai_health; exit} else if bot_ammo < 10 then {scr_ai_ammo; exit} else {scr_ai_engage; exit} }   if status ==3 //if looking for ammo {   if bot_health < 30 then {scr_ai_health; exit} }   //nothing is needed for status 4 //reset alarm here

You might notice that several scripts are called here. Specifically, scr_ai_find, scr_ai_health, scr_ai_ammo, and scr_ai_engage. We'll outline these next. I won't give you these scripts in detail; we'll just cover the concepts.  scr_ai_find

Here you will need to use instance_nearest to find the nearest enemy player and make a new path to the enemy's location. The brain script should change the AI from “find” to “engage” mode when the bot is somewhere close to the target. If it doesn't, you may need to shorten the repeat timer for the brain script.

scr_ai_health

In this script you need to use instance_nearest to find the nearest health powerup, and then compute a new path to get to it. The AI's brain should still be running on its timer. You'll need to add to the bot_heath variable in the collision event with the health object and then call the brain script.

scr_ai_ammo

Same idea here; you need to use instance_nearest to find the nearest ammo powerup and then compute a new path to get to it. The AI's brain should still be running on its timer during this. You'll need to use to the bot_ammo variable in the collision event with the ammo box and then call the brain script.

scr_ai_engage

Ok, this one will be a little more tricky. What you want to do is use the choose function to choose between strafing or shooting at the enemy. Obviously, you will want there to be many more chances to choose shooting than moving. The shooting should be done with a bit of randomization. Here's an example:

//random shooting accuracy var cenemy, denemy; cenemy = instance_nearest(x,y,obj_enemy); //the //nearest enemy denemy = point_direction(x,y,cenemy.x,cenemy.y); //direction of enemy randomize; denemy+=random(20); //lower this to change //accuracy randomize; denemy-=random(20); //lower this to change //accuracy

Conclusion
So the overall idea is that your AI frequently runs a priority scripts and takes action based on its environment. Here are some things you need to watch out for and tweak:

1. Your A* implementation. This is a whole different subject, so I'm leaving it out of this short tutorial. The included example can help get you started.

2. The repeat interval of the AI brain script.

3. scr_ai_engage needs to have good balance between moving and shooting.

4. Adjust the priority triggers to suit your game.

I hope that this can help you jumpstart your game's AI, and I'll look forward to playing it!