GML Enemy animation and behavior bug

J

JohnSebek

Guest
Hello, so I made an enemy from a tutorial by Shaun Spalding. And added a little animation code. But I have several problems and I tried to fix them for two hours but still no luck.1. The enemy does not change sprite when walking left.2.When the enemy is attacking player he showed the right animation, but when the player tries to run, the enemy will change to standing sprite and stays until the attack.
Here is my code:

Create Event:
execute code:

vsp = 0;
grv = 0.3;
walksp = 2;
hsp = walksp;
hp = 20;
maxhp = hp;

Alarm Event for alarm 1:
execute code:

///alarm

Step Event:
execute code:

vsp = vsp + grv;

//horizontal colision
if (place_meeting(x+hsp,y,obj_floor))
{
while (!place_meeting(x+sign(hsp),y,obj_floor))
{
x = x + sign(hsp);
}
hsp = -hsp;
}
x = x + hsp;

//vertical colision
if (place_meeting(x,y+vsp,obj_floor))
{
while (!place_meeting(x,y+sign(vsp),obj_floor))
{
y = y + sign(vsp);
}
vsp = 0;
}
y = y + vsp;

//animation
if (!place_meeting(x,y+1,obj_floor))
{
sprite_index = spr_enemy_walk3;
image_speed = 0;
if (sign(vsp) > 0) image_index = 1; else image_index = 0;
}
else
{
image_speed = 0.16;
if (hsp ==0)
{
sprite_index = spr_enemy_stand3;
}
else
{
sprite_index = spr_enemy_walk3;
}
}


Collision Event with object obj_player:
execute code:

{
sprite_index = spr_enemy_hit3;
if(alarm[1] == -1){
hsp = 0;
health -=4;
alarm[1] = room_speed/2;
}
}

else
execute code:

if (distance_to_point(obj_player.x, obj_player.y) <= 2)
{
move_towards_point(obj_player.x,obj_player.y, 2)
}
else
{
hsp = 0
}

Draw Event:
Draw the instance
 
I think you have to use image_xscale = -1 when walking to the left, so that the sprite flips the other way.

if (hsp == 0) {
sprite_index = spr_enemy_stand3;
} else {
sprite_index = spr_enemy_walk3;
image_xscale = sign(hsp);
}
 
Last edited:
J

JohnSebek

Guest
I think you have to use image_xscale = -1 when walking to the left so that the sprite flips the other way.

if (hsp == 0) {
sprite_index = spr_enemy_stand3;
} else {
sprite_index = spr_enemy_walk3;
image_xscale = sign(hsp);
}
Thank you o i tried it and it does not work. When i use image_xscale = sign(hsp); enemy will not show walking animation at all.And when i use image_xscale = -1 enemy moves turned to the left all the time.
 
This is why your code does not work:
the enemy starts moving freely until the player is 2px far from the player, there you set his hsp to zero if the player moves away from him, so the animation stops to the stand one, as you coded in the step event.
if (hsp == 0) {
sprite_index = spr_enemy_stand3;
}

Try putting the following line of code in your step event, before you collision code, and delete it from the Collision Event.

if (distance_to_point(obj_player.x, obj_player.y) <= 2)
{
var dis = point_distance(x, y, obj_player.x, obj_player.y);
hsp = sign(dis) * walksp;
}
else
{
hsp = walksp;
}

This is how your code should look like:

Code:
/// CREATE EVENT

vsp = 0;
grv = 0.3;
walksp = 2;
hsp = walksp;
hp = 20;
maxhp = hp;
can_move = true;

/// ALARM 1
can_move = true;

/// STEP EVENT

vsp = vsp + grv;

if (distance_to_point(obj_player.x, obj_player.y) <= 2)
{
       var dis = point_distance(x, y, obj_player.x, obj_player.y);
       hsp = sign(dis) * walksp;
}
else
{
    if  (can_move) hsp = walksp;
}

//horizontal colision
if (place_meeting(x+hsp,y,obj_floor))
{
while (!place_meeting(x+sign(hsp),y,obj_floor))
{
x = x + sign(hsp);
}
hsp = -hsp;
}
x = x + hsp;

//vertical colision
if (place_meeting(x,y+vsp,obj_floor))
{
while (!place_meeting(x,y+sign(vsp),obj_floor))
{
y = y + sign(vsp);
}
vsp = 0;
}
y = y + vsp;

//animation
if (!place_meeting(x,y+1,obj_floor))
{
   sprite_index = spr_enemy_walk3;
   image_speed = 0;
   if (sign(vsp) > 0) image_index = 1; else image_index = 0;
}
else
{
     image_speed = 0.16;
     if (hsp ==0)
     {
        sprite_index = spr_enemy_stand3;
     }
     else
    {
       sprite_index = spr_enemy_walk3;
       image_xscale = sign(hsp);
    }
}


/// COLLISION EVENT WITH O_PLAYER


sprite_index = spr_enemy_hit3;
if(alarm[1] == -1){
   hsp = 0;
   can_move = false;
   health -=4;
   alarm[1] = room_speed/2;
}



/// DRAW EVENT
draw_sprite(sprite_index, image_index, x, y);
 
Last edited:
J

JohnSebek

Guest
This is why your code does not work:
the enemy starts moving freely until the player is 2px far from the player, there you set his hsp to zero if the player moves away from him, so the animation stops to the stand one, as you coded in the step event.
if (hsp == 0) {
sprite_index = spr_enemy_stand3;
}

Try putting the following line of code in your step event, before you collision code, and delete it from the Collision Event.

if (distance_to_point(obj_player.x, obj_player.y) <= 2)
{
var dis = point_distance(x, y, obj_player.x, obj_player.y);
hsp = sign(dis) * walksp;
}
else
{
hsp = walksp;
}

This is how your code should look like:

Code:
/// CREATE EVENT

vsp = 0;
grv = 0.3;
walksp = 2;
hsp = walksp;
hp = 20;
maxhp = hp;
can_move = true;

/// ALARM 1
can_move = true;

/// STEP EVENT

vsp = vsp + grv;

if (distance_to_point(obj_player.x, obj_player.y) <= 2)
{
       var dis = point_distance(x, y, obj_player.x, obj_player.y);
       hsp = sign(dis) * walksp;
}
else
{
    if  (can_move) hsp = walksp;
}

//horizontal colision
if (place_meeting(x+hsp,y,obj_floor))
{
while (!place_meeting(x+sign(hsp),y,obj_floor))
{
x = x + sign(hsp);
}
hsp = -hsp;
}
x = x + hsp;

//vertical colision
if (place_meeting(x,y+vsp,obj_floor))
{
while (!place_meeting(x,y+sign(vsp),obj_floor))
{
y = y + sign(vsp);
}
vsp = 0;
}
y = y + vsp;

//animation
if (!place_meeting(x,y+1,obj_floor))
{
   sprite_index = spr_enemy_walk3;
   image_speed = 0;
   if (sign(vsp) > 0) image_index = 1; else image_index = 0;
}
else
{
     image_speed = 0.16;
     if (hsp ==0)
     {
        sprite_index = spr_enemy_stand3;
     }
     else
    {
       sprite_index = spr_enemy_walk3;
       image_xscale = sign(hsp);
    }
}


/// COLLISION EVENT WITH O_PLAYER


sprite_index = spr_enemy_hit3;
if(alarm[1] == -1){
   hsp = 0;
   can_move = false;
   health -=4;
   alarm[1] = room_speed/2;
}



/// DRAW EVENT
draw_sprite(sprite_index, image_index, x, y);
Well now it sorta works.The enemy attacks properly,but when i move out of his attack distance,he will not follow me he will continue to walk right.
 
Ok just add this variable in the create event:
Code:
/// CREATE EVENT
following = false;
I would recommend changing the chase code into something like this:

Code:
var sight_range = 128;   // The enemy sight range: if the player is in that range the enemy starts following him, otherwise it stops following him and start moving freely
if (distance_to_point(obj_player.x, obj_player.y) <= sight_range)
{
      following = true;
} else if (distance_to_point(obj_player.x, obj_player.y) > sight_range)
{
     following = false;
}
Or, if you want, you can just put it in one line of code:
Code:
following = distance_to_point(obj_player.x, obj_player.y) <= sight_range;
Then:

Code:
// Follow the player
if (following)
{
      var dis = point_distance(x, y, obj_player.x, obj_player.y);
      hsp = sign(dis) * walksp;
} else {
// Stop following the player and start moving freely
      if  (can_move) hsp = walksp;
}
 
You can also make a circular detection, making the sight_range the radius of the circle:

Code:
var sight_range = 128;   // The enemy sight range: if the player is in that range the enemy starts following him, otherwise it stops following him and start moving freely

following = point_in_circle(obj_player.x, obj_player.y, x, y, sight_range);

So when the player is out of that range, the enemy stops following him.
 

Attachments

J

JohnSebek

Guest
You can also make a circular detection, making the sight_range the radius of the circle:

Code:
var sight_range = 128;   // The enemy sight range: if the player is in that range the enemy starts following him, otherwise it stops following him and start moving freely

following = point_in_circle(obj_player.x, obj_player.y, x, y, sight_range);

So when the player is out of that range, the enemy stops following him.
I don ´t know why but the zombie just won ´t work. He still does not follow me after putting your code in it(It should be in step event right?) He will just attack me when he collides me and if I run he will continue to walk right.
 
If you want the enemy to follow you for an unlimited amount of time after you entered his "sight area", just delete the else statement:
Code:
if (following)
{
      var dis = point_distance(x, y, obj_player.x, obj_player.y);
      hsp = sign(dis) * walksp;
}
Else, if you want the enemy to follow (or attack, I don't know what you mean for attacking), you can just increase the sight_range to a large pixel amount Ex: var sight_range = 256;
 
J

JohnSebek

Guest
If you want the enemy to follow you for an unlimited amount of time after you entered his "sight area", just delete the else statement:
Code:
if (following)
{
      var dis = point_distance(x, y, obj_player.x, obj_player.y);
      hsp = sign(dis) * walksp;
}
Else, if you want the enemy to follow (or attack, I don't know what you mean for attacking), you can just increase the sight_range to a large pixel amount Ex: var sight_range = 256;
By attacking i mean the collision with player.So i want the enemy to walk to player and attack him and if he will try to run the zombie will try to chase him.The code still does not work like this.Enemy will just walk right and if player is really close the enemy will sligthly get to player and starts attacking him(collision with player event).But when i run away the enemy continues to walk right.I can send the rewrited code because i have no idea why this still works the same.

CODE:
Information about object: obj_enemy4
Sprite: spr_enemy_stand3
Solid: false
Visible: true
Depth: 0
Persistent: false
Parent: obj_enemypar
Children:
Mask:
No Physics Object
Create Event:
execute code:

vsp = 0;
grv = 0.3;
walksp = 2;
hsp = walksp;
hp = 20;
maxhp = hp;
can_move = true;
/// CREATE EVENT
following = false;

Alarm Event for alarm 1:
execute code:

can_move = true;


Step Event:
execute code:

vsp = vsp + grv;

var sight_range = 350; // The enemy sight range: if the player is in that range the enemy starts following him, otherwise it stops following him and start moving freely

following = point_in_circle(obj_player.x, obj_player.y, x, y, sight_range);
// Follow the player
if (following)
{
var dis = point_distance(x, y, obj_player.x, obj_player.y);
hsp = sign(dis) * walksp;
}

//horizontal colision
if (place_meeting(x+hsp,y,obj_floor))
{
while (!place_meeting(x+sign(hsp),y,obj_floor))
{
x = x + sign(hsp);
}
hsp = -hsp;
}
x = x + hsp;

//vertical colision
if (place_meeting(x,y+vsp,obj_floor))
{
while (!place_meeting(x,y+sign(vsp),obj_floor))
{
y = y + sign(vsp);
}
vsp = 0;
}
y = y + vsp;

//animation
if (!place_meeting(x,y+1,obj_floor))
{
sprite_index = spr_enemy_walk3;
image_speed = 0;
if (sign(vsp) > 0) image_index = 1; else image_index = 0;
}
else
{
image_speed = 0.16;
if (hsp ==0)
{
sprite_index = spr_enemy_stand3;
}
else
{
sprite_index = spr_enemy_walk3;
image_xscale = sign(hsp);
}
}

execute code:

/*if (distance_to_point(obj_player.x, obj_player.y) <= 2)
{
var dis = point_distance(x, y, obj_player.x, obj_player.y);
hsp = sign(dis) * walksp;
}
else
{
if (can_move) hsp = walksp;
}

execute code:

/*/ Follow the player
if (following)
{
var dis = point_distance(x, y, obj_player.x, obj_player.y);
hsp = sign(dis) * walksp;
} else {
// Stop following the player and start moving freely
if (can_move) hsp = walksp;
}

Collision Event with object obj_player:
execute code:


sprite_index = spr_enemy_hit3;
if(alarm[1] == -1){
hsp = 0;
can_move = false;
health -=4;
alarm[1] = room_speed/2;
}


Draw Event:
execute code:

draw_sprite(sprite_index, image_index, x, y);
 
Top