GameMaker [SOLVED] Find the edge of the platform in 2d platformer

P

player_2

Guest
Hi guys! I am newbie and I need your help. Recently I started making a game in GMS2 and ran into a couple of questions that I couldn’t find answers to:

1.There is an object that moves along the platform, reaches the edge and turns around in the opposite direction. it works like this:
Code:
var hspd = movespeed*dir;
if(!place_meeting(x+ sign(hspd)*sprite_width+ hspd, y+1, oSolid))
{
    while(place_meeting(x + sign(hspd)*sprite_width + sign(hspd), y+1,oSolid))
    {
        x+= sign(hspd);   
    }
hspd = 0;
dir *= -1;
}
x+= hspd;

Such a code has many disadvantages - if the hole is less than the width of the sprite of the object, then it will not notice it and will move on. Also, if i change the direction of the sprite depending on the direction of movement (image_xscale), the code starts to work incorrectly:

How to check the lack of a platform ahead? It seems that for 2d platformers this is a fairly common situation and the solution should be simple.

2. Same case, but I still need to find out the ID block on the edge of the platform . if I do it this way ( the color of the block changes for clarity)
Code:
var hspd = movespeed*dir;
if(!place_meeting(x+ sign(hspd)*sprite_width + hspd, y + 1, oSolid))
{
    while(place_meeting(x + sign(hspd)*sprite_width + sign(hspd), y+1, oSolid))
    {
    x+= sign(hspd);
    }
hspd = 0;
dir *= -1;
var inst = instance_place(x,y+1, all); // this string
inst.image_blend = c_red;
}
x+= hspd;
the code does not work correctly - on one side of the platform, the color changes at the desired block, on the other side - at the penultimate block:

How to do it right? (sprite origin for all objects is in the center)
 
P

player_2

Guest
You should be using sprite_width /2.
Yes, but this only solves the problem of getting the id of the last block.
The object does not stop at the very edge of the platform. Plus, changing the direction of the sprite (depending on the direction of movement) still breaks everything.
 

TheouAegis

Member
Oh, you need to use position_meeting() or instance_position().

if !position_meeting(x + sign(hspd) * sprite_width/2 + hspd, y+1, oSolid)

You don't need to check the whole mask for a collision, just the bottom corner points.

And unless your hspd is super high, you should be able to just use instance_position(x,y+1,oSolid) to get the id of the oSolid directly below the NPC, then get its bbox_left if the NPC's hspd is negative or get its bbox_right if the NPC's hspd is positive. Then add the difference between the specified variable of both instances.

if !position_meeting(x+sign(hspd)*sprite_width/2+hspd,y+1,oSolid) {
var inst = instance_position(x,y+1,oSolid)
if hspd<0 x+=(inst.bbox_left-bbox_left);
else if hspd>0 x+=(inst.bbox_right-bbox_right);
hspd = 0;
dir *= -1;
}

If changing image_xscale breaks anything, either you have unnecessary code somewhere or your sprite's origin-to-bounds ratios are to blame. If your sprite has a centered origin but the collision mask isn't centered, then you should mirror the sprite before moving it to the edge of the ledge.
 
Last edited:
P

player_2

Guest
Oh, you need to use position_meeting() or instance_position().

if !position_meeting(x + sign(hspd) * sprite_width/2 + hspd, y+1, oSolid)

You don't need to check the whole mask for a collision, just the bottom corner points.

And unless your hspd is super high, you should be able to just use instance_position(x,y+1,oSolid) to get the id of the oSolid directly below the NPC, then get its bbox_left if the NPC's hspd is negative or get its bbox_right if the NPC's hspd is positive. Then add the difference between the specified variable of both instances.

if !position_meeting(x+sign(hspd)*sprite_width/2+hspd,y+1,oSolid) {
var inst = instance_position(x,y+1,oSolid)
if hspd<0 x+=(inst.bbox_left-bbox_left);
else if hspd>0 x+=(inst.bbox_right-bbox_right);
hspd = 0;
dir *= -1;
}

If changing image_xscale breaks anything, either you have unnecessary code somewhere or your sprite's origin-to-bounds ratios are to blame. If your sprite has a centered origin but the collision mask isn't centered, then you should mirror the sprite before moving it to the edge of the ledge.
Many thanks! This seems to be what I was looking for.
 
P

player_2

Guest
and one more small question - I discovered if I change image_xscale to a negative value, the sign of sprite_width also changes. is this normal behavior?
 

TheouAegis

Member
Oh. Yeah. Yeah I see what you were saying about it messing things up. I haven't done collision checks the way you were doing them for a while, so I forgot about that. That was one reason why I stopped doing that way. You can use the function sprite_get_width(sprite_index) instead.
 

TheouAegis

Member
To expand on it real quick: sprite_width, sprite_height, sprite_xoffset and sprite_yoffset are negated when xscale or yscale are also negated, since they are both calculated using simple formulas that don't take negation into account. If you are going to use actual scaling on top of flipping and mirroring, then just remember to get the absolute value of those variables before you use them.
 
P

player_2

Guest
To expand on it real quick: sprite_width, sprite_height, sprite_xoffset and sprite_yoffset are negated when xscale or yscale are also negated, since they are both calculated using simple formulas that don't take negation into account. If you are going to use actual scaling on top of flipping and mirroring, then just remember to get the absolute value of those variables before you use them.
Thanks again!
 
Top