GameMaker Changed sprites from 32 to 16 bit, now collision logic allows player through the floor

P

polymorphic_ nw

Guest
I'm a bit embarrassed that I don't see the issue with this code, but I feel as if I'm missing something, as this code should work regardless of the sprite size. I'm specifically having issues with the vertical collision, so I'll post that, though I'm not sure if the horizontal is working either. It's for a sidescroller. The player just falls through the floor.

Code:
//vertical collision

var side;
//determine which side to test
if (vsp > 0) side = bbox_bottom;
else side = bbox_top;

//check top and bottom of side
var t1 = tilemap_get_at_pixel(global.map, bbox_left, side + vsp);
var t2 = tilemap_get_at_pixel(global.map, bbox_right, side + vsp);
var t3 = tilemap_get_at_pixel(global.map, bbox_left, bbox_bottom)
var t4 = tilemap_get_at_pixel(global.map, bbox_right, bbox_bottom)

if    (t1 != VOID and (((vsp > 0 or t1 != PLATFORM)) and t3 != PLATFORM) or (t1 == SOLID and t3 == PLATFORM)) or
    (t2 != VOID and (((vsp > 0 or t2 != PLATFORM)) and t4 != PLATFORM) or (t2 == SOLID and t4 == PLATFORM)) {
    //collision found
    if (vsp > 0) y = y - (y mod global.tile_size) + global.tile_size - 1 - (side-y);
    else y = y - (y mod global.tile_size) - (side - y);
    vsp = 0;
}
global.tile_size was changed from 32 to 16. The sprites for all the player states were changed as well, and their collision masks have all been redrawn to be the same for every sprite. It seems the collision code triggers before it actually hits the ground, which indicates the bounding box might be triggering incorrectly. Anyone see any obvious errors?
 

Amon

Member
Last time I did what you did I had to manually edit the collision box of each sprite to get everything working again.
 
P

polymorphic_ nw

Guest
I’ve tried that, unfortunately. I made every sprite have the same numbers in every box. Is there more I need to do?
 

Slyddar

Member
G'day! The collision code works perfectly. I have a 16x16 version of the project you have followed, and even copying your code into my collision script works fine, even though you missed the last line, applying the vsp to y. i.e. y+=vsp;

Sounds like you have a mask problem. In the create event, set all sprites to idle, and test it. If it works, add the next sprite to the array and test it one by one. You should find which one is causing the problem that way.
 

johnwo

Member
First off, resizing sprites has nothing to do with changing "bits". Bits refer to the amount of information stored per-pixel (1-bit [monochrome], 8-bit [e.g. grayscale or 256-colors from a 24-bit palette], and so on).

The collision detection itself is fine, but if abs(vsp) > global.tile_size, the player might go through the tiles.
The calculation when a collision is detected... Phew... It's a mouthful!

This is the calculation you're using:
Code:
if (vsp>0) y = y - (y mod tileSize) + tileSize - 1 - (side-y);
else y = y - (y mod global.tile_size) - (side - y);
That first line, used when vsp > 0 equates to:
Code:
y = tileSize - side - (y mod tileSize) + 2*y - 1;
Not only is it confusing, but it can, depending on how you handle gravity, cause issues like the player being set to a y-position above the tile (bbox_bottom <= tileY+1) when vsp > 0.

Assuming there are no special cases, you could replace this:
Code:
if (vsp>0) y = y - (y mod tileSize) + tileSize - 1 - (side-y);
else y = y - (y mod global.tile_size) - (side - y);
with this:
Code:
y = (side div tileSize)*tileSize;
This handles both collision when vsp > 0 and vsp < 0 since side is set to be the top/bottom bbox.
It simply finds the nearest y-coordinate divisible by global.tile_size with respect to side.

Let me know if this helped.

Happy coding!
 

johnwo

Member
And how does this handle the sprite offset?
It doesn't, it's based off of the bounding box, assuming yoffset at 0...

Just to quote myself:
Assuming there are no special cases
If the y-offset is not 0 (which I personally see no point in if it's a platformer, as x-offset set to sprite_width/2 is the usual "offender" in order to mirror the sprite based on hspeed), then the code can be amended by appending:
Code:
y = (side div tileSize)*tileSize+sprite_yoffset;
EDIT: Was missing an "a".
 
Last edited:

Slyddar

Member
Ah, didn't picture having a sprite with an offset as a special case. I guess all sprites are special cases then.

So do we just ignore the 1 pixel change in the bounding box position between top and bottom collisions, or right/left collisions?
 
P

polymorphic_ nw

Guest
Thank you so much for the help! It turns out it was an origin issue--having them all set to bottom center was causing issues for various reasons. I think the state transition was moving the bounding box and clipping into the floor. Anyway, it's resolved, and my code is better thanks to you all.
 

johnwo

Member
@polymorphic_ nw Glad you got to the bottom of it!

Ah, didn't picture having a sprite with an offset as a special case. I guess all sprites are special cases then.

So do we just ignore the 1 pixel change in the bounding box position between top and bottom collisions, or right/left collisions?
I don't know how you'd handle beyond the code displayed in this thread, but based off of OP's code, with the amendments I pointed out; I have no trouble getting pixel-perfect collisions in up/down-, left/right- or corner-cases for a 16x16 sprite.
Video below.
hsp/vsp at 5/6 respectively.
Please don't move the goalpost, and just have a fantastic day!
 

Mike

nobody important
GMC Elder
For the record.... sprites are always 32bit after loading... only the source image is 8/16/24. A lot of hardware doesn't even do 16bit textures anymore...
 

GMWolf

aka fel666
A lot of hardware doesn't even do 16bit textures anymore...
What? Of course they do!
Hardware now supports all sorts of 16 bit formats.
There is 565 unorm, R8G8_UNORM/UINT/SNORM, R16_UNORM/UINT/SNORM, R16_FLOAT, ..

Of course for RGB data you would only use 565 but most hardware supports that


[Edit] oh yeah, and B4G4R4A4. Not sure what you would use that for but there it is.
 
Last edited:
P

polymorphic_ nw

Guest
I did in fact mean pixels, not bits. I'm not sure why I said that, as I definitely know the difference.
 
Top