Basic AI? Follow and damage

L

LuckyTHR

Guest
Hi All

I am by no means a coder but I enjoy playing around with GM,

I have a semi working engine up and running, but now I need some advice with my AI, all they need to do is follow my player when they are in range and do damage when touching player, Mario style.

I had coding where they chased me around but somehow that broke.

Thanks
 
S

Shariku Onikage

Guest
If you're not a coder now's the time to learn. Enemy AI will require going beyond the basic DnD functions of Game Maker, and this is going to have different answers depending on the format of your game. Is it platformer, or top down?

I'm assuming from the mario comment it's a platformer. Your basic logic is going to be if player is close and nothing is in the way, then move towards player. distance_to_object is a pretty basic function to use for this. You can set it so that if the enemy is a certain distance from the player it 'sees' the player and you then increase the enemies speed to chase the player down.

Look up collision_line in the reference library as well if objects are likely to be in the way. You can have something like the following in the enemy's step process:

Code:
if distance_to_object(player)<=widthOfTheScreen{    //prevents Bowser from running across the map to get you
      if (collision_line(x,y,player.x,player.y,oBlock,true,true) = noone) {
           direction=point_direction(x,y,player.x,player.y);
           speed= fasterThanWalkingSpeed;
    }
}
That should help you get started.
 
Last edited by a moderator:

Yal

🐧 *penguin noises*
GMC Elder
I'd personally recommend using a speed that's slower than walking speed for the optimal game experience (unless the player can run to move faster). If the player can't run away from enemies they didn't see in time, the game becomes needlessly punishing.
 
L

LuckyTHR

Guest
Thanks Shariku

Yes it is a platformer.

Will give this a try now and let you know.

I would really like to learm more about GM, as I enjoy working with it.
 
L

LuckyTHR

Guest
Thanks Yal, will keep that in mind

Busy trying to get it to work, currently just getting:

------------------------------------------------------------------------------------------------------
FATAL ERROR in
action number 1
of Step Event0
for object obj_npc:

Variable obj_npc.vsp(100012, -2147483648) not set before reading it.
at gml_Object_obj_npc_StepNormalEvent_1 (line 3) - if (place_meeting(x,y+vsp,obj_player))
------------------------------------------------------------------------------------------------------

Prob just me doing it wrong, should the enemy object use physics?
 
S

Shariku Onikage

Guest
I'd personally recommend using a speed that's slower than walking speed for the optimal game experience (unless the player can run to move faster). If the player can't run away from enemies they didn't see in time, the game becomes needlessly punishing.
My logic was just if the enemy spots the player, then they would start running over to the player. Not insanely fast, but still faster than the enemy's standard walk.
 
Last edited by a moderator:
S

Shariku Onikage

Guest
Thanks Shariku

Yes it is a platformer.

Will give this a try now and let you know.

I would really like to learm more about GM, as I enjoy working with it.
I would recommend Tom Francis 'make a game with no experience'. It's a good starting point ffor GML and game making in general.

 
S

Shariku Onikage

Guest
Thanks Yal, will keep that in mind

Busy trying to get it to work, currently just getting:

------------------------------------------------------------------------------------------------------
FATAL ERROR in
action number 1
of Step Event0
for object obj_npc:

Variable obj_npc.vsp(100012, -2147483648) not set before reading it.
at gml_Object_obj_npc_StepNormalEvent_1 (line 3) - if (place_meeting(x,y+vsp,obj_player))
------------------------------------------------------------------------------------------------------

Prob just me doing it wrong, should the enemy object use physics?
Have you declared the vsp variable in the obj_npc create event? It's that that it's complaining about.
 
S

str3

Guest
If you're not a coder now's the time to learn. Enemy AI will require going beyond the basic DnD functions of Game Maker, and this is going to have different answers depending on the format of your game. Is it platformer, or top down?

I'm assuming from the mario comment it's a platformer. Your basic logic is going to be if player is close and nothing is in the way, then move towards player. distance_to_object is a pretty basic function to use for this. You can set it so that if the enemy is a certain distance from the player it 'sees' the player and you then increase the enemies speed to chase the player down.

Look up collision_line in the reference library as well if objects are likely to be in the way. You can have something like the following in the enemy's step process:

Code:
if distance_to_object(player)<=widthOfTheScreen{    //prevents Bowser from running across the map to get you
      if (collision_line(x,y,player.x,player.y,oBlock,true,true) = noone) {
           direction=point_direction(x,y,player.x,player.y);
           speed= fasterThanWalkingSpeed;
    }
}
That should help you get started.
I am new to GM, but i understand the basics and fundamentals. I also know a little bit of code. In the code above I only understand the first line, and after that it gets hazy. Any chance you can describe in detail what it means?
 
S

Shariku Onikage

Guest
I am new to GM, but i understand the basics and fundamentals. I also know a little bit of code. In the code above I only understand the first line, and after that it gets hazy. Any chance you can describe in detail what it means?
No worries. It was kind of rough but basically if the player is nearby (distance_to_object) and no oBlocks (i.e. whatever objects you're using for walls) are in the line of sight between the enemy and the player(collision_line), then the enemy should move in the direction of the player (point_direction) at an assigned speed.

Code:
if distance_to_object(player)<=widthOfTheScreen{    //prevents Bowser from running across the map to get you by limiting the enemy's line of sight to the width of the screen
      if (collision_line(x,y,player.x,player.y,oBlock,true,true) = noone) { //sets the line of sight between enemy and player. if there are no blocks (noone) then...
           direction=point_direction(x,y,player.x,player.y);       // enemy moves in the direction of the player, this will need to be more complex if player is above or below the enemy
           speed= fasterThanWalkingSpeed;             //speed in which to move
    }
}
Note that widthOfTheScreen and fasterThanWalkingSpeed are my terms. Substitute them for the appropriate numbers.
 

Zapzel-24

Member
I need help in GM on an enemy chase AI, the game I am planning to make you have the ability to switch between two characters with their own unique moves and abilities to overcome obstacles. However I have encountered a problem with the enemy chase AI in which the game crashes because it cannot find one character or the other I need some help in how to arrange this situation in code. both characters are written as obj_player and the other is obj_character and to save time use obj_enemy to describe the enemy object.

P.S If you can also figure out how make an enemy chase code that follows certain characters and ignore others that would be absolutely swell
 

Zapzel-24

Member
Also sorry being intrusive I'm still new to all of this and I am having difficulty figuring how this forum work and I only find this as the only way
 
S

Shariku Onikage

Guest
Also sorry being intrusive I'm still new to all of this and I am having difficulty figuring how this forum work and I only find this as the only way
No worries. The post new thread button is hidden at the top right of the page. It's grey so i can see that it'll be easy to miss.

How are your enemies finding your players at the moment? For a simple game, the basic thing to remember is that the AI needs to know where the player object is all the time, even if, in game, the enemy hasn't spotted the player. Something like point_direction(x,y,obj_player.x,obj_player.y) will create a link between the enemy and the player that will allow them to keep track of that player. If they don't have to worry about pathfinding, the following should do:
Code:
direction=point_direction(x,y,obj_player.x,obj_player.y);
P.S If you can also figure out how make an enemy chase code that follows certain characters and ignore others that would be absolutely swell
obj_enemy create event:
Code:
var iAmFollowing="";
step event
Code:
if (iAmFollowing=="player"){
   direction=point_direction(x,y,obj_player.x,obj_player.y);
   speed=2;
}

if (iAmFollowing=="character"){
   direction=point_direction(x,y,obj_character.x,obj_character.y);
   speed=2;
}
Then depending on who you want that enemy to follow set something that changes iAmFollowing to the appropriate string (you may want to switch them to integers/constants for the sake of cleaniness but this should do as an example).
 

Zapzel-24

Member
It works perfectly fine thank you, however the game crashes when I try to establish a detection range. I programmed the enemy to chase player when it at a certain distance ( aggroRange =200 pixels radius) and ignore character but the game still crashes because it does not know what to do if character is in its detection range. I thought that simply telling the enemy during a step event that whenever character is present within its range to set its speed to 0. But the game crashes and I get this message.

FATAL ERROR in
action number 1
of Step Event0
for object obj_enemy_chase:

Unable to find any instance for object index '1' name 'obj_character'
at gml_Object_obj_enemy_chase_StepNormalEvent_1 (line 12) - direction=point_direction(x,y,obj_character.x,obj_character.y);

I do not what I am doing wrong I have tried every possible angle and I keep getting errors because it cannot detect character. here is the script below:

if(instance_exists(obj_player) <= aggroRange)
{
direction=point_direction(x,y,obj_player.x,obj_player.y);
speed=2;
}


if(instance_exists(obj_character) <= aggroRange)
{
direction=point_direction(x,y,obj_character.x,obj_character.y);
speed=0;
}
 
S

Shariku Onikage

Guest
It works perfectly fine thank you, however the game crashes when I try to establish a detection range. I programmed the enemy to chase player when it at a certain distance ( aggroRange =200 pixels radius) and ignore character but the game still crashes because it does not know what to do if character is in its detection range. I thought that simply telling the enemy during a step event that whenever character is present within its range to set its speed to 0. But the game crashes and I get this message.

FATAL ERROR in
action number 1
of Step Event0
for object obj_enemy_chase:

Unable to find any instance for object index '1' name 'obj_character'
at gml_Object_obj_enemy_chase_StepNormalEvent_1 (line 12) - direction=point_direction(x,y,obj_character.x,obj_character.y);

I do not what I am doing wrong I have tried every possible angle and I keep getting errors because it cannot detect character. here is the script below:

if(instance_exists(obj_player) <= aggroRange)
{
direction=point_direction(x,y,obj_player.x,obj_player.y);
speed=2;
}


if(instance_exists(obj_character) <= aggroRange)
{
direction=point_direction(x,y,obj_character.x,obj_character.y);
speed=0;
}
The error message is basically saying that obj_character does not exist in the room as far as the script is concerned. Dumb question but do you actually have both the obj_player and obj_character as active objects in the room at the same time?

Could we get a screenshot of the room and let us know which ones are which, or a zip of the gmx file as well? It might help shed some light on things.
 

Zapzel-24

Member
No,the whole premise of the game is that you have the ability to switch between two characters on the spot via magical statues ( they are still in development so the C button on the keyboard serves as a placeholder ).

You control player who posses a gun that fires weak projectiles but has the ability to blow up certain walls and swim

When passing through a statue you turn into character who has a harder hitting sword (but runs the risk of being up close) and can double jump.

You have to overcome various types of enemies one of which chases when you are a specific character, I have watch videos on how to make chase AI which works quite well but immediately crashes when I press the C button to switch to character.

Player with chase enemy
player and Old chase AI.JPG

Chase enemy follows player when entering its radius
player and Old chase AI following.JPG

And this happens whenever I press the C button to switch characters.
old chase AI error.JPG

The old AI uses a script that chases the player whenever it enters a certain radius from the enemy I thought with that script alone it would chase player and ignore character here is the script and its variables on the next reply below.

The ones you gave me works very well but the problem is that the enemy immediately chases the moment the game starts until you switch. Also I am sorry that I could not upload any more images it seems the forums is restricting me to upload five images at a time and I will post on a reply below it.
 

Zapzel-24

Member
Here is the Variables for the chase AI
old chase varibles.JPG

Here is the script for its static state.
old chase AI static.JPG

And finally this is what does when the player enters its radius.
old chase AI follow.JPG
 
S

Shariku Onikage

Guest
Your game is going to run into difficulty if the player object is constantly switched out (any code that is constantly looking for the player object is going to freak out like this the second it disappears). I would more aim to create a parent object for the two characters that is always present in the room that can change its state (it is essentially one character that can switch to two separate forms).

For example have an object called obj_player (and no obj_character at all) and then have something like this:

create event
Code:
character="gunGuy";
step event:
Code:
if keyboard_check_pressed(ord('C')){
       if (character="gunGuy") {
           character = "swordGuy"
           image_index= (whatever swordguy's spriteset is) // may be sprite_index depending on how you've done it
          } else {
               character="gunGuy"
               image_index= (whatever gunguy's spriteset is) // may be sprite_index depending on how you've done it
          }
Then merge whatever code is unique from the obj_character into the obj_player object and set if conditions that rely on the character variable, so for example:

step event:
Code:
if keyboard_check_pressed(ord('X')){  //X is attack in this example
       if (character="gunGuy") {
             // insert shooting functions here
          } else if (character="swordGuy") {
             // insert swordstabby functions here
          }
As for your aggro range, try something more along these lines:

enemy step event:
Code:
if(distance_to_point(obj_player) <= aggroRange)
{
direction=point_direction(x,y,obj_player.x,obj_player.y);
speed=2;
}
Hope that helps. Sorry if that's a little vague. I'm just about to leave for the day.
 

Fredrik

Member
Well it depends if your game is top down'ish or side scroller. Let's say it's top down, then you can use: mp_potential_step_object(x,y,spd, obj); with x and y in your case being the player's x and y, spd being the walkspeed of the enemie and obj to be the object to avoid. So let's say that everything you'll collide with in your game has a parent_solid set as parent, now make the "obj" parent_solid. With this the enemie will now move towards you calculating a path to avoid any upcoming parent_solid.

Example:
mp_potential_step_object(player.x,player.y,3,parent_solid);

If you also want the enemie to attack you could make the player lose health as fast as the enemie touches you, or use distance_to_object(obj); to check if the player is close enough.

Example.
if distance_to_object(player) < 10 {attack = 1} else {attack = 0}
if attack = 1 {bla bla;}

In my project I have it so a enemie will play a attack animation (sprite) when attack is 1, like:
if attack = 1 {sub + = 1 {if sub > 10 {sub = 0}}
if sub = 5 {if distance_to_object(player) < 10 {player.dmg -= 1}}

^ something around that. I'm using sub as in subimage ofc.
This is not taken from the project tho but just wrote something similar.
 
H

Halph-Price

Guest
I would recommend Tom Francis 'make a game with no experience'. It's a good starting point ffor GML and game making in general.

Thanks that's really nifty, and his game kind of inspired me too with gunpoint. His got a simple and straight forward tutorial that works for what I want to do. Much thanks.
 
Top