SOLVED Begin Step "on_ground" check failing?

hogwater

Member
I've been using this check in the Begin Step event in order to quickly determine if my guy is on the ground or not, and transition to certain states.

Code:
/// @description check if on ground

if (place_meeting(x,y + 1,obj_all_ground_parent))
{
on_ground = true;
}
else on_ground = false;
obj_all_ground_parent includes the solid and one-way ground parents.


This is the issue: Whenever any part of my character's mask is colliding with a one-way platform, I am considered to be "on_ground" as the video shows. As soon as I walk out of the collision with the platform above me, I'll fall properly. I can even jump up through a one-way platform without landing on the top, and on_ground becomes true just while my mask rises through it.

Here's the code for both the Idle and Walk Left states, as well as the horizontal collision, although it can't be at fault as the Idle state doesn't have it.

Idle:
Code:
case harry_states.idle:

//flip sprites based on direction
if (move != 0) image_xscale = move;

sprite_index = spr_harry_idle;
image_index = 0;
image_speed = 0;

scr_harry_basic_movement();

if (down)
{
state = harry_states.duck;   
}

if (jump)
{
state = harry_states.jump;   
}

if (left)
{
state = harry_states.walk_left;   
}
else if (right)
{
state = harry_states.walk_right;   
}

if (attack_held)
{
state = harry_states.sword_pull;   
}

if (up && attack)
{
state = harry_states.upthrust;   
}

if (can_douken) && (attack)
{
state = harry_states.sword_throw_ground;   
}

if (can_spike) && (attack)
{
state = harry_states.sword_spike;   
}

if (!on_ground)
{
state = harry_states.fall;   
}

last_state = harry_states.idle;

break;

Walk Left:
Code:
case harry_states.walk_left:

//flip sprites based on direction
if (move != 0) image_xscale = move;

if (state != last_state)
{
sprite_index = spr_harry_walk;
image_index = 0;
image_speed = anim_walk_spd;
}

scr_harry_basic_movement();

if (run)
{
state = harry_states.run_left;   
}

if (!left)
{
state = harry_states.idle;   
}
else if (right)
{
state = harry_states.walk_right;
}

if (jump)
{
state = harry_states.jump;   
}

if (down)
{
state = harry_states.duck;   
}

if (attack_held)
{
state = harry_states.sword_pull;   
}

if (can_douken) && (attack)
{
state = harry_states.sword_throw_ground;   
}

if (can_spike) && (attack)
{
state = harry_states.sword_spike;   
}

if (!on_ground)
{
state = harry_states.fall;   
}

#region collision

scr_harry_collision_hori();
//scr_harry_collision_vert();

#endregion

//set last state
last_state = harry_states.walk_left;

break;

Horizontal Collision:
Code:
function scr_harry_collision_hori()
{

// Horizontal
repeat(abs(hspd))
{
    // Move up slope
    if (place_meeting(x + sign(hspd), y, obj_collision_solid_parent) && place_meeting(x + sign(hspd), y - 1, obj_collision_solid_parent) && !place_meeting(x + sign(hspd), y - 2, obj_collision_solid_parent))
        y -= 2;
    else if (place_meeting(x + sign(hspd), y, obj_collision_solid_parent) && !place_meeting(x + sign(hspd), y - 1, obj_collision_solid_parent))
        y -= 1;
   
    // Move down slope
    if (!place_meeting(x + sign(hspd), y, obj_collision_solid_parent) && !place_meeting(x + sign(hspd), y + 1, obj_collision_solid_parent) && !place_meeting(x + sign(hspd), y + 2, obj_collision_solid_parent) && place_meeting(x + sign(hspd), y + 3, obj_collision_solid_parent))
        y += 2;
    else if (!place_meeting(x + sign(hspd), y, obj_collision_solid_parent) && !place_meeting(x + sign(hspd), y + 1, obj_collision_solid_parent) && place_meeting(x + sign(hspd), y + 2, obj_collision_solid_parent))
        y += 1;

    if (!place_meeting(x + sign(hspd), y, obj_collision_solid_parent))
        x += sign(hspd);
    else
    {
    hspd = 0;
    break;
    }
}

}
 
Last edited:

Nidoking

Member
Well, yes. If your instance, when placed one pixel below its current location, collides with an obj_all_ground_parent, your check will succeed. That covers the entire bounding box, not just the bottom row of pixels. If you want to handle one-way platforms, you'll need to do something more sophisticated to check whether you're just falling through. A quick alternative would be to check that it's not place_meeting at its current location as well.
 

hogwater

Member
Well, yes. If your instance, when placed one pixel below its current location, collides with an obj_all_ground_parent, your check will succeed. That covers the entire bounding box, not just the bottom row of pixels. If you want to handle one-way platforms, you'll need to do something more sophisticated to check whether you're just falling through. A quick alternative would be to check that it's not place_meeting at its current location as well.
OK. I was under the impression that my check was only looking for a collision at the mask y +1 location in this instance. Now I understand how it's actually working. What do you mean by checking that it's not place_meeting at the current location?

Is this a poor way of doing it? Seems to work fine.

edit- amended to this:
Code:
if (collision_line(bbox_left,bbox_bottom+1,bbox_right,bbox_bottom+1,obj_all_ground_parent,false,true)) && (!place_meeting(x,y,obj_collision_solid_parent)) && (vspd >= 0)
{
on_ground = true;
}
else on_ground = false;
 
Last edited:
Top