place_meeting vs other collision functions? player falls into wall object

MaxHP43

Member
I have been using this tutorial by Yoyo led by Shaun Spalding:

I tried a more advanced platformer tutorial by him and got an issue where my player lands halfway through the wall object rather than sitting nicely on the top of the object, and it also keeps the player in the falling image rather than the standing animation. I figured I did something wrong with the collision mask, or the use of Place_meeting vs position_meeting, so I tried the basic platformer tutorial above. However, using the exact same code and assets as Shaun, I get the same result.

I have tried moving the origin around and get different results. If the origin is in the very top left, beyond the collision mask, the play sits somewhat on top and plays the standing animation like normal, although the player does clip a little into the wall below. Moving the origin to the very bottom make the player land even further down into the wall object.

If I remove the last part of the code //animation then the collisions and standing animation works perfectly.

Did something change in GM2 that the tutorial is missing?


GML:
//get player input

keyleft = keyboard_check(vk_left);
keyright = keyboard_check(vk_right);
keyjump = keyboard_check_pressed(vk_space);

//calulate movement

var _move = keyright - keyleft;

hsp = _move * walksp;

vsp = grv + vsp;

if (place_meeting(x, y+1, owall)) and (keyjump)
{
    vsp = -jumpsp;    
}

// horizontal collision

if (place_meeting(x+hsp, y, owall))
{
    while (!place_meeting(x+sign(hsp),y,owall))
    {
            x = x + sign(hsp);
    }
    hsp = 0;
   
}

x = x + hsp;
   
//     vertical collision


if (place_meeting(x, y+vsp, owall))
{
    while (!place_meeting(x,y+sign(vsp),owall))
    {
            y = y + sign(vsp);
    }
    vsp = 0;
   
}

y = y + vsp;

// animation

if (!place_meeting(x,y+1,owall))
{
    sprite_index = splayerjump;
    image_speed = 0;
    if (vsp > 0) image_index = 1; else image_index = 0;
   
}
 
Last edited:

Mobie

Member
I am not the person to be answering this question because I don't know much, but I had that problem and figured out a solution. I expect someone more knowledgeable than me will have a better answer, but I will give you what I found out. My problem was the collision mask of my falling player sprite not matching the collision mask of my standing player sprite. I had player objects falling right through a floor because the standing player collision mask came in lower than the falling player. Thus, when the sprite change triggered, the collision mask was already too low and the player either stopped in the middle of a floor or fell right through it. When I was careful to make both falling and standing sprites exactly the same, the problem stopped.

Now you can wait for an answer from someone who actually knows what they are talking about. LOL.
 

MaxHP43

Member
So, I set the player obj collision mask to be splayer (which is the sprite of my standing player animation) instead of "same as sprite". It gives me less problems using the splayer sprite rather than "same as sprite", but still the same result as described in the post. Thanks for your input though

I noticed that removing the animation section of the code makes the collisions work perfectly fine and plays the animation as expected.

GML:
if (!place_meeting(x,y+1,owall))
{
    sprite_index = splayerjump;
    image_speed = 0;
    if (vsp > 0) image_index = 1; else image_index = 0;
    
}
 
Last edited:

Nidoking

Member
Instead of changing the collision mask, make sure that the sprite bounding boxes and origins are the same between all of the sprites that you use for an instance.
 

Mobie

Member
Instead of changing the collision mask, make sure that the sprite bounding boxes and origins are the same between all of the sprites that you use for an instance.
Yes, that is what I was trying to say but you said it much better. I actually duplicated my standing sprite and then erased the image on the duplicate. Then I drew my falling sprite onto the blank duplicate. That guaranteed everything was the same and I've never had a problem since I started doing that.
 
Last edited:

MaxHP43

Member
Instead of changing the collision mask, make sure that the sprite bounding boxes and origins are the same between all of the sprites that you use for an instance.
AHA! Setting all of the origin points to be identical completely fixed this issue.

Why does the origin points matter if place_meeting is checking for a collision of two object's collision masks?
 

kburkhart84

Firehammer Games
AHA! Setting all of the origin points to be identical completely fixed this issue.

Why does the origin points matter if place_meeting is checking for a collision of two object's collision masks?
Because the actual position of those collision masks as checked is based on the origin.
 

Yal

šŸ§ *penguin noises*
GMC Elder
Because the actual position of those collision masks as checked is based on the origin.
To be precise, the origin is the pixel that will be placed at the object's x/y coordinates. (When the sprite is rotated with image_angle, the origin stays at these coordinates, so basically the sprite also rotates around the origin)

This also leads to another potential issue with collisions: if your coordinates aren't integer, which pixel the origin will be placed in isn't well defined (since it's between two pixels), and you can get unexpected results and inconsistencies between different collision functions (place_meeting, collision_point, etc). Usually you won't notice it, but for very low-res pixelart and for very precise collisions (e.g. instead of a range, you check a single pixel thick zone) this can lead to all sorts of weird issues.
 
Top