• 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!

Player jitters against tiles (SOLVED)

boy656

Member
I need some help. I want my player to collide with the tiles, but when i play it, it jitters against the tiles. How to fix? Thank you!

Code:

Create

move_speed = 8;
jump_impulse = 21;
grav = 0.75;
v_speed = 0;
var l = layer_get_id("Collision");
tilemap = layer_tilemap_get_id(l);
sprite_bbox_left = sprite_get_bbox_left(sprite_index) - sprite_get_xoffset(sprite_index);
sprite_bbox_right = sprite_get_bbox_right(sprite_index) - sprite_get_xoffset(sprite_index);
sprite_bbox_bottom = sprite_get_bbox_bottom(sprite_index) - sprite_get_yoffset(sprite_index);
sprite_bbox_top = sprite_get_bbox_top(sprite_index) - sprite_get_yoffset(sprite_index);

Step

var dy = v_speed;
v_speed += grav;
y += dy;
if ( dy > 0){
var t1 = tilemap_get_at_pixel(tilemap, bbox_left, bbox_bottom) & tile_index_mask;
var t2 = tilemap_get_at_pixel(tilemap, bbox_right, bbox_bottom) & tile_index_mask;

if (t1 != 0 || t2 != 0) {
y = ((bbox_bottom & ~64) - 1) - sprite_bbox_bottom;
v_speed = 0;
}
} else {
var t1 = tilemap_get_at_pixel(tilemap, bbox_left, bbox_top) & tile_index_mask;
var t2 = tilemap_get_at_pixel(tilemap, bbox_right, bbox_top) & tile_index_mask;

if (t1 != 0 || t2 != 0) {
y = ((bbox_top + 64) & ~63) - sprite_bbox_top;
v_speed = 0;
}
}
x += dx;
if (dx > 0){
var t1 = tilemap_get_at_pixel(tilemap, bbox_right, bbox_top) & tile_index_mask;
var t2 = tilemap_get_at_pixel(tilemap, bbox_right, bbox_bottom) & tile_index_mask;

if (t1 != 0 || t2 != 0) {
x = ((bbox_right & ~63) - 1) - sprite_bbox_right;
v_speed = 0;
}
} else {
var t1 = tilemap_get_at_pixel(tilemap, bbox_left, bbox_top) & tile_index_mask;
var t2 = tilemap_get_at_pixel(tilemap, bbox_left, bbox_bottom) & tile_index_mask;

if (t1 != 0 || t2 != 0) {
x = ((bbox_left + 64) & ~63) - sprite_bbox_left;
v_speed = 0;
}
}
 

NightFrost

Member
One of your bitmasks is wrong:
Code:
y = ((bbox_bottom & ~64) - 1) - sprite_bbox_bottom;
Should be 63 like the rest, not 64.
 

Rob

Member
still didnt work.
You're adding dy to your y before checking for any tiles. Adding to x/y before collision detection and modifying the vsp/hsp is always going to cause you problems with collision.

The process you should do is:
  • add grav to vsp
  • check if y + vsp will collide with a tile
  • if it will collide with a tile, run some kind of loop (while/for/repeat) that runs from 0 - (vsp + grav) and checks if the space is empty 1 pixel below
  • if there is no tile 1 pixel below, move y down 1 pixel inside the loop
  • once there is no empty space 1 pixel below, break the loop, stop the y movement and set vsp to 0
  • y += vsp should be after all these checks have been done
 
Last edited:

Rob

Member
Could you give the code just this once if you dont mind?
something like this:

Code:
repeat abs(vsp){
   var t1 = tilemap_get_at_pixel(tilemap, bbox_left, bbox_bottom + 1);
   var t2 = tilemap_get_at_pixel(tilemap, bbox_right, bbox_bottom + 1);
   if (t1 > 0) || (t2 > 0){
      vsp = 0;
      break;
   }else y ++;
}
 

TheouAegis

Member
@Rob There's not much point combining pixel-perfect object collision with tiles. The tiles will always be snapped to a grid (well, typically). Objects don't follow those same restrictions. The whole reason we started using the pixel-perfect collisions for objects was because people were putting objects in their rooms at odd coordinates.

With objects, we look for a collision ahead of us and move into it. With tiles, we need to look for a collision after we move into it, and then snap out of it.

The real issue with his code is he didn't stop his horizontal movement.
if (t1 != 0 || t2 != 0) {
x = ((bbox_right & ~63) - 1) - sprite_bbox_right;
v_speed = 0; <<<<<<<<<<<<<<<<<<<<<<<WRONG!!
}
} else {
var t1 = tilemap_get_at_pixel(tilemap, bbox_left, bbox_top) & tile_index_mask;
var t2 = tilemap_get_at_pixel(tilemap, bbox_left, bbox_bottom) & tile_index_mask;

if (t1 != 0 || t2 != 0) {
x = ((bbox_left + 64) & ~63) - sprite_bbox_left;
v_speed = 0; <<<<<<<<<<<<<<<<<<<<<<<<<WRONG!!
}
}
 

Rob

Member
@Rob There's not much point combining pixel-perfect object collision with tiles. The tiles will always be snapped to a grid (well, typically). Objects don't follow those same restrictions. The whole reason we started using the pixel-perfect collisions for objects was because people were putting objects in their rooms at odd coordinates.

With objects, we look for a collision ahead of us and move into it. With tiles, we need to look for a collision after we move into it, and then snap out of it.

The real issue with his code is he didn't stop his horizontal movement.
What about platformers? I had to make a platform engine for somebody using tile based collision and the method I described seemed like the best one
 

TheouAegis

Member
What about platformers? I had to make a platform engine for somebody using tile based collision and the method I described seemed like the best one
Unless your moving platforms are also tiles, there is little reason to use a loop to find out where you need to be when colliding with tiles. You will ALWAYS stop at the same place with a single calculation. Even with slopes, it's still the same.

The looping collision method is meant for when the point of collision would be arbitrary. It also helped for the most part with some rounding issues. Even with objects it wasn't always necessary, it was just the most inclusive. But it was also slower at higher your speeds - A LOT slower. Twenty instances moving 1 pixel would perform 20 collision checks. Twenty instances moving 4 pixels would perform up to 80 collision checks. Twenty instances falling at 8 pixels per step would perform up to 160 collision checks. In most cases they wouldn't all be running at once, but why even waste 7 extra checks per instance if you didn't need them?
 
Top