• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GML Enemy AI (Enemy Attack State) How would I code that? [SOLVED]

A

Alexander Olofsson

Guest
How would I do if I wanted my enemy to come close, and then initiate the attack animation and create a hitbox in front of him? I have a state, but it's really glitchy.
Code:
if (en_state == 0)
{
    if (distance_to_object(obj_player) < 20)
   {
    state = 1
    sprite_index = spr_forestspirit_atk;
    image_index = 0.3
    movespeed = 0;
    hsp = 0;
    }
}

var hit = 0
   
   
   
if (en_state = 1) {
    if (image_index >= 2) && (image_index <= 3)
    {
        with (instance_create(x,y, obj_en_hitbox))
        {
            image_xscale = other.image_xscale;
            with (instance_place(x,y,obj_player))
            {
                if (hit==0)
                {
                    hit = 1;
                    vsp = -1
                    hsp = sign(x - other.x) * 10;
                    image_xscale = sign(hsp);
                }
            }
        }
    }
}
For example, when he gets close to me, he starts drifting super fast, completely skipping the line of code which tells him to stop moving (movespeed = 0;). And the animation does not work.

And whilst I'm in the subject, if the enemy damages me, any ways to make knockback?
 
Last edited by a moderator:

Nocturne

Friendly Tyrant
Forum Staff
Admin
You are checking the variable "en_state", but you are setting a variable "state"... Are they two different variables? From the code it seems like they should be the same... Oh, and use a "switch" to check the state, not multiple "if". As for knockback, you need to add a variable to the player instance to cancel the user input and then set an alarm to reset it again to permit it. For example (pseudo code alert!):

Code:
// PLAYER CREATE
knockback = false;

// STEP
if !knockback
{
// Player control here
}
else
{
// Knockback code here
}

// COLLISION EVENT WITH ENEMY/BULLET/Whatever
knockback = true;
alarm[0] = 10;

// ALARM[0]
knockback = false;
Something like that. :)
 
A

Alexander Olofsson

Guest
Hey, I tried using a switch, but the same thing keeps happening, when he gets in range he starts to slide, and I'll implement the knockback.
Code:
if (en_state = 0)
{
    switch (state)
    {
        case e_state.idle:
        {   
            hsp = 0
            vsp = (min(7,vsp+0.05));
            if (distance_to_object(obj_player) < 128) state = e_state.chase;
            if (distance_to_object(obj_player) < 10) state = e_state.attack;
        }
        break;
        case e_state.chase:
        {
            dir = sign(obj_player.x-x);
            hsp = dir * 2;
            vsp = (min(7,vsp+0.05));
            if (distance_to_object(obj_player) < 160) state = e_state.idle;
            if (distance_to_object(obj_player) < 10) state = e_state.attack;
        }
        break;
        case e_state.attack:
        {
        if (e_state.attack)
        {
            if (distance_to_object(obj_player) < 10)
            {
            sprite_index = spr_forestspirit_atk;
            image_index = 0.3;
            hsp = 0
            vsp = (min(7,vsp+0.05));
            }
        }
        
        var hit = 0
            
            
            
        if (spr_forestspirit_atk) {
            if (image_index >= 2) && (image_index <= 3)
            {
                with (instance_create(x,y, obj_en_hitbox))
                {
                    image_xscale = other.image_xscale;
                    with (instance_place(x,y,obj_player))
                    {
                        if (hit==0)
                        {
                            hit = 1;
                            vsp = -1
                            hsp = sign(x - other.x) * 10;
                            image_xscale = sign(hsp);
                        }
                    }
                }
            }
        }   
    }
}
 
A

Alexander Olofsson

Guest
AHA! I didn't notice that I set the state = 1!
They are two different variables, the state for player and the en_state for the enemy!

EDIT: same effect.
 
Last edited by a moderator:
A

Alexander Olofsson

Guest
Still need help!! How would I make an attack state for the enemy?
 

samspade

Member
Still need help!! How would I make an attack state for the enemy?
There's more than one way to create a state machine based on a switch statement, so I'm not saying you're wrong, but your code is strange. Perhaps I don't understand it. Regardless, here's what I use:

Code:
//state - moving, attacking
switch (state) {
    case "MOVING": {
        //put move code here
        if (instance_exists(object)) && (distance_to_object(object) < attack_range) {
            state = "ATTACKING";
            //put code to stop movement here something like
            //hsp = 0;
            //vsp = 0;
            //but with whatever you're using
        }
        break;
    }
    case "ATTACKING": {
        //put attack code here
        //do not put any movement code here
        //make sure to put a way out of the attack and back into the moving state here
        //something like
        if (alarm[0] == -1) alarm[0] = attack_delay;
        break;
    }
}

///alarm[0]
instance_create(x, y, obj_weapon);
state = "MOVING";
 
A

Alexander Olofsson

Guest
Yep, I know that and that code was pretty old, but yeah I also used (and still do) a switch statement when I posted that post, and the problem was:
Code:
sprite_index = spr_forestspirit_atk;
image_index = 0.1;
hsp = 0
vsp = (min(7,vsp+0.05));
movespeed = 0;
var hit = 0
        
if (spr_forestspirit_atk)
{
    if (image_index >= 0) && (image_index <= 5)
    {
        movespeed = 0;
        hsp = 0;
    }
}
I accidentally typed
sprite_index = spr_forestspirit_atk;
image_index = 0.1; < There. It was supposed to be image_speed.

OMG, I'M SO HAPPY NOW! Thanks
 

TheouAegis

Member
The player and the enemy can have the same variable name.... unless you did something silly like make the player's state variable a global.

But yeah, you need to practice proofreading your code more thoroughly. :p


As for state IDs, I feel enums are a waste of space (with that said, they do make things easier to read) and string-identifier states are a waste of speed. Your initial code that just used numbers is what I always use, especially since state machines don't have to have concretely distinct states; although it necessitates good commenting.
 
A

Alexander Olofsson

Guest
Yeah.



And I probably also have to practice proofreading my code too...
Well thanks for everything, see you around.
 
Top