GameMaker Tile Collision problem

Hi, I´m making an RPG game and I use a tileset collision system. I have one tileset for the collision blocks and I have this in my character´s collision script:
GML:
var _collision = false;

//Tiles horizontales
if (tilemap_get_at_pixel(collisionMap, x + hSpeed * 2, y))
{
    x -= x mod TILE_SIZE;
    if(sign(hSpeed) == 1) x += TILE_SIZE -1;
    hSpeed = 0;
    _collision = true;
}



//Cometer movimiento horizontal
x += hSpeed;

//Tiles verticales
if (tilemap_get_at_pixel(collisionMap, x, y + vSpeed))
{
    y -= y mod TILE_SIZE;
    if(sign(vSpeed) == 1) y += TILE_SIZE -1;
    vSpeed = 0;
    _collision = true;
}

//Cometer movimiento vertical
y += vSpeed;

return _collision;
When I touch a collision block my character teleports weirdly a bit up or down. And it tresspass a bit the block. How can I solve it?
 

Let's Clone

Member
It seems like you are trying to force movement when there either is or isn't a collision. It might be easier to only apply motion if the next move will avoid a collision, and avoid moving otherwise.
 

TheouAegis

Member
Well it is wrong, so we REALLY need to figure out why you are going into walls, because that is not a legitimate fix.

Your code does not take sprite dimensions into account anywhere. You check for a tile at (x,y), which for most sprites is toward the middle of the Sprite. It this follows that the center of the Sprite will be aligned to the grid, but not the edges of the Sprite.
 

curato

Member
I do someting similar in my title. You need to check several points around the border of your character You need a smaller gap than the tile size.
 

Apell

Member
Idk if its a good idea to just throw code at people - but check these out - I cant remember what tutorial videos I learned them from otherwise I would direct you to them :/

I tried to add as much commentation in it too, to help with understanding the code

The first - tile_place_meeting - will see if your hitbox collides with a tile at the inputed _x & _y
The second - move_hsp - is a simple movement loop that keeps you outside of walls
just flip all the x & y values around in move_hsp to make a move_vsp function :)

However I would like to note I've put simplified code here (I removed a lot of delta_time related stuff)
so this is all frame based code - meaning slow computers will be at a disadvantage.

delta_time is a WHOLE other hurdle to get over - for now just worry about these basics

I'm sure there are better ways to do this sort of code but,
I hope this helps!

GML:
function tile_place_meeting(_x,_y) {
    
    var _tmap = global.tilemap_id;//or layer_tilemap_get_id("layer_name_here");
    
    //move the instance to  the desired place
    var _tx = x;
    var _ty = y;
    
    x = _x;
    y = _y;
    
    //these check all collision points - bbox values are essentially the corner points of the hitbox
    var _left = (tilemap_get_at_pixel(_tmap,bbox_left,bbox_top) == 1) || (tilemap_get_at_pixel(_tmap,bbox_left,bbox_bottom) == 1);
    var _right = (tilemap_get_at_pixel(_tmap,bbox_right,bbox_top) == 1) || (tilemap_get_at_pixel(_tmap,bbox_right,bbox_bottom) == 1);

    //feel free to remove _middle & _center if your character is smaller - or same size as tiles
    var _middle = (tilemap_get_at_pixel(_tmap,bbox_right,bbox_top+(bbox_bottom-bbox_top)/2) == 1) || (tilemap_get_at_pixel(_tmap,bbox_left,bbox_top+(bbox_bottom-bbox_top)/2) == 1);
    var _center = (tilemap_get_at_pixel(_tmap,bbox_left+(bbox_right-bbox_left)/2,bbox_bottom) == 1) || (tilemap_get_at_pixel(_tmap,bbox_left+(bbox_right-bbox_left)/2,bbox_top) == 1);
    
    //move instance back to the original place
    x = _tx;
    y = _ty;
    
    return _left || _right || _middle || _center;
}

GML:
function move_hsp(_hsp){

    if (tile_place_meeting(x+_hsp,y)) {
        //move_snap will make sure we are pixel perfect
        move_snap(1,y);
        //this while loop will place the instance right next to the wall
        while (!tile_place_meeting(x+sign(_hsp),y)) {
            x+=sign(_hsp);
        }
        //safety check incase instance is in the wall
        if (tile_place_meeting(x,y)) {
            x-=sign(hsp);
        }
        //set _hsp to 0 as we dont want to move into the wall
        _hsp=0;
    }
    x+=_hsp;
    
    //return hsp so when script is used type "hsp = move_hsp(hsp)"
    //or just edit it here to say "hsp = _hsp" instead of "return _hsp"
    return _hsp;
}
 
Top