artificial-intelligencecollisiongame-maker-studio-2

Vertical collision of the enemy does not work


I'm a beginner in Gamemaker and I'm doing a simple platformer, and yesterday I was programming for the enemy to switch between standing still or moving, and in the middle of the process I went to do his collision, and for some reason, the horizontal collision works perfectly, but the vertical collision doesn't, I tried everything, but the vertical collision just doesn't seem to exist.

Below is the enemy's "AI" code in create event to make him switch between standing or walking.

//BIGGER SPRITE
image_xscale = 3
image_yscale = 3

//VARIABLES
hsp=0
vsp=0
grav=2

state=noone 
state_time = room_speed * 10;
state_timer=0;

destination_x = x;
vel=2
//STANDING STATE

//WALKING STATE

//METHOD OF CHANGE OF STATE
change_state = function(_state)
{
    state_time--;
    state_timer = irandom(state_time);
    
    if (state_timer == state_time or state_time <= 0)
    {
        //I'LL CHECK WHICH STATE SHOULD I GO
        state = _state[irandom(array_length(_state)-1)];
        
        time_state = room_speed * 10;
    }
}


//METHOD OF IT STANDING
standing_state = function()
{
    //image_blend = c_white;
    
    sprite_index = spr_enemy
    
    change_state([walking_state, standing_state]);
}

walking_state = function()
{
    //MAKE HIM WALK
    //HE WILL CHOOSE ANY POINT WITHIN THE ROOM
    //CHECKING MY DISTANCE FROM THE DESTINATION
    var _dist = point_distance(x, y, destination_x, y);
    //I WILL ONLY SET A DESTINATION IF I AM CLOSE TO MY DESTINATION
    if (_dist < 100)
    {
        destination_x = random(room_width);
    }
    
    //FINDING THE DIRECTION TO MY DESTINATION
    var _dir = point_direction(x, y, destination_x, y)
    
    //MOVING TO MY DESTINATION
    x += lengthdir_x(vel, _dir);
    
    //image_blend = c_red;
    
    //SETTING THE SPRITE
    sprite_index = spr_enemy_run
    if (destination_x < x)
    {
        image_xscale = -3
    }
    else
    {
        image_xscale = 3
    }
    
    change_state([standing_state, walking_state]);
}

//SETTING ITS INITIAL STATE
state = standing_state;`

And below is the code of collisions and gravity in step event

//HORIZONTAL COLLISION
if place_meeting(x + hsp, y, obj_block)
{
    var _hsp = sign(hsp);
    //AS LONG AS I'M NOT COLLIDING 1 PIXEL IN THE DIRECTION I'M
    while (!place_meeting(x + _hsp, y, obj_block))
    {
        //I MOVE 1 PIXEL IN THAT DIRECTION
        x+=_hsp;
    }
    //I'VE MOVED WHAT I HAD TO MOVE, AND NOW I'M COLLIDING.
    //I END MY SPEED
    hsp = 0;
    show_debug_message("colliding with the floor")
}
//I MOVE
x += hsp;

//VERTICAL COLLISION
if place_meeting(x, y + vsp, obj_block)
{
    var _vsp = sign(vsp);
    while (!place_meeting(x, y + _vsp, obj_block))
    {
        y+=_vsp;
    }
    vsp = 0;
    show_debug_message("colliding with the wall")
}
y += vsp;

//GRAVITY
if !place_meeting(x,y,obj_block)
{
    vsp += grav;
}


//RUNNING THE CURRENT STATE
state();

And one thing I don't understand, the messages "colliding with the wall" and "colliding with the floor" are appearing inversely, that is, when the enemy collides with the wall, the message "colliding with the floor" appears, and when it collides with the floor, the message "colliding with the wall" appears.

I need help as I'm almost going crazy lmao (and the fact that I'm a beginner and totally dependent on tutorials doesn't help much)

Sorry if my English has flaws, I had to translate all the code into English for better understanding because before it was in Portuguese

I expected the enemy to collide with the wall, like any collision, the enemy stops when it touches a wall, but instead, the enemy simply goes through the wall as if it were a ghost.

I tried everything, tested the collision masks, checked the variables, the order of the code, checked the name of the object, but nothing works


Solution

  • Call state() and the gravity code before collisions. It will work without but won't feel as responsive as the player will always be moving 1 frame after it was told to move.

    Your collision code is what is actually moving the player so never change x and y directly unless you want to teleport the player. Instead use the variables hsp and vsp.

    In walking_state, you call "x += lengthdir_x(vel, _dir);" which will move the player directly. Since the collision code is dependent on hsp so by moving the player by changing it's x position directly collisions won't be checked for that movement.

    You should instead say: "hsp = lengthdir_x(vel, _dir);" and the collision code will then take care of moving the player and colliding

    Edit: also, the reason the messages are swapped is because the X axis is horizontal and the Y axis is vertical. So X are the walls and Y is the floor and ceiling.