tile colition fixing

S

supermasher/ti

Guest
I was trying to make tile collision but some thing strange happens so i recorded it so you can see what is happening

https://photos.app.goo.gl/V9m9Geda7s5QHkF4A

so this is what i have for my collision code right now

OBJ_player

create//:
Code:
tilemap = layer_tilemap_get_id("wall_colisin");
step//:
Code:
//tiles

var bbox_side;


if (hspeed > 0) bbox_side = bbox_right; else bbox_side = bbox_left;
if (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_top) != 0) || (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_bottom) != 0)
{
    if (hspeed > 0) x = x - (x mod 32) + 31 - (bbox_right - x);
     else x = x - (x mod 32) - (bbox_left - x);
    
}


if (vspeed > 0) bbox_side = bbox_bottom; else bbox_side = bbox_top;
if (tilemap_get_at_pixel(tilemap,bbox_left,bbox_side+vspeed) != 0) || (tilemap_get_at_pixel(tilemap,bbox_right,bbox_side+vspeed) != 0)
{
    if (vspeed > 0) y = y - (y mod 32) + 31 - (bbox_bottom - y);
     else y = y - (y mod 32) - (bbox_top - y);
    
}
 

TheouAegis

Member
Your sprite is 2 tiles tall. You need to check at bbox_bottom, bbox_top, AND bbox_bottom-H, where H is half the height of your sprite.
 
S

supermasher/ti

Guest
i am still kinda new to programming in game maker and even newer to walls/tiles so can you pleas explain a little more so i under stand better
 

TheouAegis

Member
The code you are using is checking bbox_top and bbox_bottom for the y-coordinates. The problem is your player's sprite is taller than the tiles it is trying to collide with, so it is entirely possible for bbox_top and bbox_bottom to both be collision-free. You need to check at bbox_bottom-sprite_height/2 in addition to checking at bbox_bottom and bbox_top.
 

NightFrost

Member
It is important to realize that you are doing point collision checking, that is, you are checking single pixels for collision. For example, when you are moving left you are checking the very top left and bottom left pixels of your collision box (offset by your movement speed to look at your potential new position). As the distance between those two spots is larger then the height of your wall piece, when you are roughly centered with the wall neither will find a collision. The top left check will check above the wall, the bottom left, below. TheouAegis is suggesting you add a third collision check that looks at halfway point between the existing points, so a wall can't slip undetected between them.

(The number of checks you need to do is directly related to the height of your character versus height of wall pieces. If your character was over two times the height of a wall piece, you'd need two additional checks between the corners, and so on.)
 
S

supermasher/ti

Guest
thanks this is what i did to make the side of the walls work

Create://
Code:
H = sprite_height/2
Step://
Code:
if (hspeed > 0) bbox_side = bbox_right; else bbox_side = bbox_left;
if (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_top) != 0) || (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_bottom-H) != 0)
{
    if (hspeed > 0) x = x - (x mod 32) + 31 - (bbox_right - x);
     else x = x - (x mod 32) - (bbox_left - x);
    
}
So the sides work fine now but I have a few problems withe the top and bottom here watch this

https://photos.app.goo.gl/DaUPeFvaKPVenjsK6
 

TheouAegis

Member
Ok, first thing we need to check:

In your HORIZONTAL collision code, change it to this temporarily:
Code:
if (hspeed > 0) bbox_side = bbox_right; else bbox_side = bbox_left;
if (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_top) != 0) || (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_bottom-H) != 0)
{
    show_message("Horizontal Check!");
   if (hspeed > 0) x = x - (x mod 32) + 31 - (bbox_right - x);
    else x = x - (x mod 32) - (bbox_left - x);
   
}
Run the game, with that code, and test your collisions moving up or down. Do not test a horizontal collision otherwise you will get spammed with message pop ups. What I suspect will happen is you should get a message popping up during a vertical collision. Let me know if that's the case.
 
S

supermasher/ti

Guest
OK I did this and it works fine on top but when I run into the bottom it gives me a message

(horizontal check)
 

TheouAegis

Member
So change this line:

if (hspeed > 0) bbox_side = bbox_right; else bbox_side = bbox_left;

to

if (hspeed > 0) bbox_side = bbox_right; else if hspeed < 0 bbox_side = bbox_left;

Then try it. If you don't get the message at all no matter how many times you run up or down into different walls (try different walls), then you can remove the show_message() line I had you put in earlier.
 
S

supermasher/ti

Guest
so I did what you said but then this happens


___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Step Event0
for object OBJ_Player:

local variable bbox_side(100001, -2147483648) not set before reading it.
at gml_Object_OBJ_Player_Step_0 (line 47) - if (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_top) != 0) || (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_bottom-H) != 0)
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_OBJ_Player_Step_0 (line 47)


and my code is this

Code:
//tiles

var bbox_side;

if (hspeed > 0) bbox_side = bbox_right; else if hspeed < 0 bbox_side = bbox_left;
if (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_top) != 0) || (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_bottom-H) != 0)
{
    show_message("Horizontal Check!");
   if (hspeed > 0) x = x - (x mod 32) + 31 - (bbox_right - x);
    else x = x - (x mod 32) - (bbox_left - x);
  
}
    


if (vspeed > 0) bbox_side = bbox_bottom; else bbox_side = bbox_top;
if (tilemap_get_at_pixel(tilemap,bbox_left,bbox_side+vspeed) != 0) || (tilemap_get_at_pixel(tilemap,bbox_right,bbox_side+vspeed) != 0)
{
    if (vspeed > 0) y = y - (y mod 32) + 31 - (bbox_bottom - y);
     else y = y - (y mod 32) - (bbox_top - y);
    
}
so Idk what is going on!
 

TheouAegis

Member
Oh, put the whole collision block inside

Code:
if hspeed != 0
{
if (hspeed > 0) bbox_side = bbox_right; else if hspeed < 0 bbox_side = bbox_left;
if (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_top) != 0) || (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_bottom-H) != 0)
{
   show_message("Horizontal Check!");
   if (hspeed > 0) x = x - (x mod 32) + 31 - (bbox_right - x);
   else x = x - (x mod 32) - (bbox_left - x);
 
}
}
No point doing horizontal checks if you aren't moving, right?
 
S

supermasher/ti

Guest
oh and hereis my code
Step//:
Code:
//tiles

var bbox_side;

if hspeed != 0
{
if (hspeed > 0) bbox_side = bbox_right; else if hspeed < 0 bbox_side = bbox_left;
if (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_top) != 0) || (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_bottom-H) != 0)
{
   show_message("Horizontal Check!");
   if (hspeed > 0) x = x - (x mod 32) + 31 - (bbox_right - x);
   else x = x - (x mod 32) - (bbox_left - x);
 
}
}
    


if (vspeed > 0) bbox_side = bbox_bottom; else bbox_side = bbox_top;
if (tilemap_get_at_pixel(tilemap,bbox_left,bbox_side+vspeed) != 0) || (tilemap_get_at_pixel(tilemap,bbox_right,bbox_side+vspeed) != 0)
{
    if (vspeed > 0) y = y - (y mod 32) + 31 - (bbox_bottom - y);
     else y = y - (y mod 32) - (bbox_top - y);
    
}
 

TheouAegis

Member
You still need to check (bbox_side+hspeed,bbox_bottom), not just (bbox_side+hspeed,bbox_bottom-H). Because your sprite is so tall, you need 3 collision checks when moving horizontally. Right now you only have 2.
 
S

supermasher/ti

Guest
OK I did this but some thing are still wonky for example every now and then if I am on the top will take my player if he is on the to right or left will teleport him to the other side of the top(but no message)

also on the bottom i I go slightly to the right or left side and then try to move inwards ( from right to left ) then I get the message

then the sides are wired if the bottom half of my player is touching the block then i try to go down wile leaning against it it will either teleport me up or I get stuck until i stop leaning on it (but no message) on the other hand if the top half of my player touches the wall at all then i gives me the message.

here is a video of me doing an example of these in the order they are written above





and my code looks like this

Step//:
Code:
//tiles

var bbox_side;

if hspeed != 0
{
if (hspeed > 0) bbox_side = bbox_right; else if hspeed < 0 bbox_side = bbox_left;
if (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_top) != 0) || (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_bottom-H) != 0)
{
   show_message("Horizontal Check!");
   if (hspeed > 0) x = x - (x mod 32) + 31 - (bbox_right - x);
   else x = x - (x mod 32) - (bbox_left - x);
 
}
}
    


if (vspeed > 0) bbox_side = bbox_bottom; else bbox_side = bbox_top;
if (tilemap_get_at_pixel(tilemap,bbox_left,bbox_side+vspeed) != 0) || (tilemap_get_at_pixel(tilemap,bbox_right,bbox_side+vspeed) != 0)
{
    if (vspeed > 0) y = y - (y mod 32) + 31 - (bbox_bottom - y);
     else y = y - (y mod 32) - (bbox_top - y);
    
}

if hspeed != 0
{
if (hspeed > 0) bbox_side = bbox_right; else if hspeed < 0 bbox_side = bbox_left;
if (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_top) != 0) || (tilemap_get_at_pixel(tilemap,bbox_side+hspeed,bbox_bottom) != 0)
{
  
   if (hspeed > 0) x = x - (x mod 32) + 31 - (bbox_right - x);
   else x = x - (x mod 32) - (bbox_left - x);
 
}
}
 
S

supermasher/ti

Guest
ops i forgot the video just let me know if you need to see it.
 
Top