• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM Pixel-Perfect Collision

H

HalfSquat

Guest
For some reason whenever my character lands on the platforms, he lands at different positions, sometimes overlapping and sometimes landing outside the platform. When he's outside the platform, he can move left and right, but when he overlaps the platform, he's stuck until I jump. Is there a way to get pixel-perfect collision on the platforms? I tried using hps and vsp and using sign, but that doesn't seem to fix the issue.Capture2.PNG Capture.PNG Capture1.PNG
 

Slyddar

Member
Probably best to just check out a GML series that shows you a good way to set it up. Shaun's platform tutorial is worth following.


And if you want to start with DnD, I have a series on platforming which does it too. Link is below.
 
On top of @TheSly's post. Properly format your code, screenshots is fine on in-game action, but you should not be using screenshots of your code. Post the code inbetween [ code][/code] tags so we can copy and paste parts if necessary. Also, use brackets, lol. I'm not going to go through and fix the code because it's a screenshot and I would have to literally type the whole thing but:
Code:
if place_meeting && hp || place_meeting && hp {
Is very probably not doing what you want.
Code:
if ((place_meeting && hp) || (place_meeting && hp)) {
That lets the computer know what statements should be checked together and what are part of the or. As your code stands, it could be asking this:

Chunk 1: if place_meeting
Chunk 2: and hp or placemeeting
Chunk 3 and hp

Or it could be asking this:
Chunk 1: if place_meeting and hp
Chunk 2: or place_meeting and hp

The computer is choosing one of those and it might not be the one you want.
 
Last edited:

TheouAegis

Member
Why the y+20? That's a really odd, seemingly arbitrary number.

If you look for a collision at the current time, you need to move outside of the collision. Or if you check for a collision at the next future step, you need to move into the collision. Shaun's tutorials do the latter.
 
H

HalfSquat

Guest
Oops, yeah I know to use the code tags, I just forgot this time. I added in the parentheses, which doesn't seem to change anything.

I tried using sign and hps and vsp like Shaun does, but that results in my character floating in the air. I'm also hesitant to do my platforming controls exactly like he does, since I have my own code for keypresses that affect hspeed, which works just fine.

The reason I have y+20 is to try to keep the character out of the platform so that he doesn't overlap. Sometimes he floats above the platform, allowing him to move left and right, and sometimes he still gets stuck inside the platform and has to jump to get out.

Code:
if ((place_meeting(x,y,obj_ground) && hp > 0) || (place_meeting(x,y + 20,obj_platform) && hp > 0))
        {
            vspeed = 0      //standing still on collision
            sprite_index = spr_idle
          
            if keyboard_check_pressed(vk_space)     //jumping
            {
                vspeed = -jspeed;
                sprite_index = spr_jump
            }
            }else{
            if ((vspeed < grav) && !place_meeting(x,y, obj_ground)) || ((vspeed < grav) && !place_meeting(x,y + 20, obj_platform))  //falling code
            {
            vspeed += grav
            sprite_index = spr_jump
            }
 
O

Old School Ben

Guest
I ran into similar collision problems in my game. Upon inspection, my code looked good but since I was not using a sprite sheet and instead using individual GIFs for my sprites the collision masks would be different sizes between sprite animations. I also ran into problems with the origin position of the sprite being off by a few pixels.

How I solved this was going in and adjusting the collision mask to be the same across each individual sprite. I also went in and adjusted the origin position of my sprites so I didn't have my sprites jumping around between animation transitions.

You may also want to double check the collision mask/ code on the platforms that may be causing problems.

Not really sure if this is the problem you are running into but it may be worth looking into if your code doesn't dictate what you are seeing when you run your game.
 

TheouAegis

Member
You can still use the built-in variables, is simply only adjust the x & y position when there is actually a collision detected, you do not adjust the position manually any other time.

Don't forget to set the speed to 0.

And definitely verify that your sprites are properly aligned correctly. That is of the utmost importance.
 
Last edited:
H

HalfSquat

Guest
I ran into similar collision problems in my game. Upon inspection, my code looked good but since I was not using a sprite sheet and instead using individual GIFs for my sprites the collision masks would be different sizes between sprite animations. I also ran into problems with the origin position of the sprite being off by a few pixels.

How I solved this was going in and adjusting the collision mask to be the same across each individual sprite. I also went in and adjusted the origin position of my sprites so I didn't have my sprites jumping around between animation transitions.

You may also want to double check the collision mask/ code on the platforms that may be causing problems.

Not really sure if this is the problem you are running into but it may be worth looking into if your code doesn't dictate what you are seeing when you run your game.
So my character has several sprite animations, each with wildly different mask sizes and origin points. Would you know any way to make the masks and origin points uniform across multiple sprites (or a tutorial showing how to do so? I tried searching for one, but no dice)? I tried going into the individual animation sprites and changing the masks, but that made things more confusing for me.

The collision masks on the platforms are the exact shape and size as the sprites, so they're probably not the problem.
 

Slyddar

Member
In the properties of the object, you can set the object to always use a single mask. It's in a section called "Collision Mask", just under where you select the sprite for the object.
 
O

Old School Ben

Guest
So my character has several sprite animations, each with wildly different mask sizes and origin points. Would you know any way to make the masks and origin points uniform across multiple sprites (or a tutorial showing how to do so? I tried searching for one, but no dice)? I tried going into the individual animation sprites and changing the masks, but that made things more confusing for me.

The collision masks on the platforms are the exact shape and size as the sprites, so they're probably not the problem.
As far as I know, they all have to be edited individually, which is honestly a bit of a pain.

Your collision mask may be the same size across all your sprites, but are they all in the same position in the sprite (x and y position)? Just because you can't see your collision masks moving when you change the sprite_index doesn't mean that they aren't jumping around.

This sort of thing would cause my object to get stuck in walls when changing animations. I really do wish there was a simpler way to "sync" these values across multiple sprites. I'm not using a sprite sheet after all :/
 

Slyddar

Member
You can also add this to a draw event of your object to see the mask it is using.
Code:
draw_self();
draw_set_alpha(0.3);
draw_rectangle_colour(bbox_left,bbox_top,bbox_right,bbox_bottom,c_red,c_red,c_red,c_red,false);
draw_set_alpha(1);
 

Hyomoto

Member
I would propose an alternative take here, and one that is seemingly overlooked. The question is, "Do you actually need pixel perfect collision?" Or, to put it in a different way, do you need the computer to do pixel-perfect collisions for you? When it comes down to it, very few games have pixel perfect collision. It is entirely common to use circles, cylinders and rectangles to approximate collisions, and then work the art assets in around them. For example, perhaps you wish to have your character bump into a wall, and when they do so, they put their hands up on the wall. Having the computer figure out a bunch of calculations to make the sprite align with the wall might be fine during development, but to save performance (and arguably your own sanity), it would be far easier, and more reliable, to edit your sprites so that they animate naturally into the position you want them to be in. A pixel perfect collision with the wall, while still relying on the convenience of a rectangle to define the boundaries of the character, is much easier when you conform your art assets to your code, rather than vice versa.

In your case, you have admitted that your sprites constantly change size and origin points. Well, you have some options. You can store those differences in code, which you can then look up to make the corrections you need, or you can adjust your art assets to be more universal. you can have differently sized bounding boxes, and even offsets, if you need, but generally speaking it's best to have those be somewhat consistent. Even if your goal is, "Oh, but while I'm ducking I want my bounding box to get smaller so I can duck bullets with perfect accuracy!" Well, without changing the bounding box at all, you could easily just store the player height during the ducking animation and compare that during a collision to see if the bullet should hit or not. You start from a place of consistency and then add the exception, rather than starting from the exception and working towards consistency.

Other people might be able to offer a bit less abstract advice on this problem, but it's worthwhile to examine how much of the problem you are trying to solve is caused by other things you could be solving instead.
 
Last edited:
H

HalfSquat

Guest
I would propose an alternative take here, and one that is seemingly overlooked. The question is, "Do you actually need pixel perfect collision?" Or, to put it in a different way, do you need the computer to do pixel-perfect collisions for you? When it comes down to it, very few games have pixel perfect collision. It is entirely common to use circles, cylinders and rectangles to approximate collisions, and then work the art assets in around them. For example, perhaps you wish to have your character bump into a wall, and when they do so, they put their hands up on the wall. Having the computer figure out a bunch of calculations to make the sprite align with the wall might be fine during development, but to save performance (and arguably your own sanity), it would be far easier, and more reliable, to edit your sprites so that they animate naturally into the position you want them to be in. A pixel perfect collision with the wall, while still relying on the convenience of a rectangle to define the boundaries of the character, is much easier when you conform your art assets to your code, rather than vice versa.

In your case, you have admitted that your sprites constantly change size and origin points. Well, you have some options. You can store those differences in code, which you can then look up to make the corrections you need, or you can adjust your art assets to be more universal. you can have differently sized bounding boxes, and even offsets, if you need, but generally speaking it's best to have those be somewhat consistent. Even if your goal is, "Oh, but while I'm ducking I want my bounding box to get smaller so I can duck bullets with perfect accuracy!" Well, without changing the bounding box at all, you could easily just store the player height during the ducking animation and compare that during a collision to see if the bullet should hit or not. You start from a place of consistency and then add the exception, rather than starting from the exception and working towards consistency.

Other people might be able to offer a bit less abstract advice on this problem, but it's worthwhile to examine how much of the problem you are trying to solve is caused by other things you could be solving instead.
So I went and adjusted the bounding boxes for each of my player sprites to be an ellipse that is 80 pixels wide and 100 pixels tall. However, this doesn't seem to make any difference. I'm still having the issue of the player landing at different vertical positions when he jumps on the platforms. The player object itself has no sprite, it calls the different sprite animations through the code.
Capture.PNG Capture2.PNG
 

TheouAegis

Member
Your player object obviously has a Sprite, otherwise he will not be able to use place_meeting(). You set the sprite_index, which is the same as giving the player a Sprite.

Your two sprites have different bounding box positions. but this also means is if both sprites have the same origin, you are going to have collision issues because one Sprite is going to collide where another Sprite doesn't. it won't matter if you have Pixel perfect collision detection, because your sprites are not aligned with each other.
 
H

HalfSquat

Guest
I set the mask for the player object to a single sprite in the properties, and also used "mask_index" in the step event. I messed around with different shapes for the mask like a diamond or a precise ellipse, but I'm still having the same issue of the player floating or getting stuck in random positions when I try to jump.
Capture.PNG Capture2.PNG
 

Slyddar

Member
Your collision code is likely the problem. With the tutorial series I posted up the top, I suggest you just follow it and remove your reliance on vspeed and hspeed, as they are not the easiest way to code a platformer, imho.
 

Hyomoto

Member
To amplify what @TheSly is saying, the built-in variables are good, to some degree, when you are first starting. But it can be more difficult to control your game using them as complexity increases since you are essentially fighting against internal logic you aren't in control of. A variable like hspeed is really just doing `x = x + hspeed` each step. It's very easy to just do that yourself and have total control over what's happening. It's also good from a learning perspective because you will have a better understanding of what is happening "under the hood".
 

Yal

šŸ§ *penguin noises*
GMC Elder
The reason you don't always land at the same position is that you just stop gravity when there's an object so-and-so-many pixels below you, regardless of whether you're touching the ground or not (or overlapping it, even!). Depending on jump speed and how far you fell, you might register a collision before you touch the ground, just as you touch it, or when you're halfway through it. You would want to move all the way down until you're just barely touching the terrain.
Use some code like this:
upload_2019-9-4_21-5-49.png
 
Top