Easy Enemy AI (Idle, Chase, Attack, and Flee)

GM Version: Studio (All)
Target Platform: Any
Download: None (Code below)
Links: Example gif of the code below: https://alaskaminds.org/2020/02/11/game-maker-easy-enemy-ai-idle-chase-attack-and-flee/
Summary:
Hello All! I'm going to show you how to create an enemy object that will Idle, Chase, Attack, or Flee using one method (turns out there are many out there in programming).

This is an instance contained state system (states being idle, chase, attack, flee) using if statements all written within the enemy object's code, opposed to the state system others use by using enum to create the different states and using switch to define and change behavior. I hope this helps.

(Please note my grid is 32. You may need to adjust accordingly to your game's grid.)
Legend:
Main Character Object = char;
Wall Object = object1;
Enemy Object; obj_enemy;
Bullet/Sword/Any Attack Object = Bullet in Collision Event on Step 5 below

Steps to create an enemy object and write the AI logic:
Further explanations within the comments ("// text") in the code.

Step 1. Create object for enemy.
Step 2. Add Create Event and add code below.
Code:
// Instance Creation Variable Sets

healthenemy=100;
invincible=false;
chase=false;
runaway=false;
justrun=false;
Step 3. Add Step Event and add code below.
Code:
// AI Movement Logic

// Just Run
if justrun=true {
    move_towards_point(char.x,char.y,5);
} else {

// Initial Proximity Trigger for Chase
if runaway=false && chase=false && distance_to_object(char) < 200 {
    chase=true;
    runaway=false;
}

// New Proximity Trigger for Chase (Only one for life of instance)
if chase=true && runaway=false && distance_to_object(char) < 400{
    move_towards_point(char.x,char.y,5);
}

// If Char is more than 400 pixels away, stop Chase
if chase=true && runaway=false && distance_to_object(char) > 400 {
    move_towards_point(char.x,char.y,0);
}

// Flee in random direction away from Char after Collision Event with Char
if chase=false && runaway=true {
    move_towards_point(char.x,char.y,5);
    playerdirection = point_direction(x,y,char.x,char.y);
    direction = (playerdirection + (180 + random(40)) );
}
}

// Stop and Start Animation
if speed = 0 {
    image_speed = 0;
} else {
    image_speed = 2;
}
}
Step 4. Add Alarm Event and add code below.
Code:
// Stops Flee and Continues Chase
chase=true;
runaway=false;
invincible=false
Step 5. Add Collision Bullet Event and add code below.
Code:
// Initiates Chase
justrun=true;

// Death or enemy HP loss
if healthenemy <= 0 {
   instance_destroy(self);
   score += 100;
}else{
if invincible = false {
   healthenemy -= 30;
   invincible=true;
   alarm_set(0,20); // Set step value to length of Attack animation
}
}

// Moves instance away from bullet  (Provides Object Overlap Protection)
var dir;
var move_dis = 32;  // pixels to move away from other object in collision

// If both instances are in the same location, set direction random
if (x == other.x && y == other.y)
    dir = random(360);

// Move in opposite direction of object in collision
else
    dir = point_direction(other.x,other.y,x,y);

// Move to new location but away from char and other enemy

var dx = lengthdir_x(move_dis,dir);
var dy = lengthdir_y(move_dis,dir);

if (!place_meeting(x+dx,y,char)) x += dx;
if (!place_meeting(x,y+dy,char)) y += dy;
if (!place_meeting(x+dx,y,obj_enemy)) x+=dx;
if (!place_meeting(y,y+dy,obj_enemy)) y +=dy;
[/CODE]
Step 6. Add Collision Char Event and add code below.
Code:
// Sets variables to initiate Flee and an Alarm to begin Chase again
chase=false;
runaway=true;
justrun=false;
alarm_set(0,40);

// Removes one health point after collision of enemy and char objects
health -= 1;
if health < 1 {
   room_restart();
}

// Moves instance away from char (Provides Object Overlap Protection)
var dir;
var move_dis = 32;  // pixels to move away from other object in collision

// If both instances are in the same location, set direction random
if (x == other.x && y == other.y)
    dir = random(360);

// Move in opposite direction of object in collision
else
    dir = point_direction(other.x,other.y,x,y);

// Move to new location but away from wall and other enemy

var dx = lengthdir_x(move_dis,dir);
var dy = lengthdir_y(move_dis,dir);

if (!place_meeting(x+dx,y,object1)) x += dx;
if (!place_meeting(x,y+dy,object1)) y += dy;
if (!place_meeting(x+dx,y,obj_enemy)) x+=dx;
if (!place_meeting(y,y+dy,obj_enemy)) y +=dy;
Step 7. Add Collision Enemy Object and add code below.
Code:
// Moves instance away from another enemy (Provides Object Overlap Protection)
var dir;
var move_dis = 32;  // pixels to move away from other object in collision

// If both instances are in the same location, set direction random
if (x == other.x && y == other.y)
    dir = random(360);

// Move in opposite direction of object in collision
else
    dir = point_direction(other.x,other.y,x,y);

// Move to new location but away from wall and char

var dx = lengthdir_x(move_dis,dir);
var dy = lengthdir_y(move_dis,dir);

if (!place_meeting(x+dx,y,object1)) x += dx;
if (!place_meeting(x,y+dy,object1)) y += dy;
if (!place_meeting(x+dx,y,char)) x +=dx;
if (!place_meeting(x,y+dy,char)) y += dy;
Step 8. Add Collision Wall Object and add code below.
Code:
// Moves instance away from wall  (Provides Object Overlap Protection)
var dir;
var move_dis = 32;  // pixels to move away from other object in collision

// If both instances are in the same location, set direction random
if (x == other.x && y == other.y)
    dir = random(360);

// Move in opposite direction of object in collision
else
    dir = point_direction(other.x,other.y,x,y);

// Move to new location but away from char and other enemy

var dx = lengthdir_x(move_dis,dir);
var dy = lengthdir_y(move_dis,dir);

if (!place_meeting(x+dx,y,char)) x += dx;
if (!place_meeting(x,y+dy,char)) y += dy;
if (!place_meeting(x+dx,y,obj_enemy)) x+=dx;
if (!place_meeting(y,y+dy,obj_enemy)) y +=dy;
 
Last edited:
Top