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

SOLVED Neat collision handling with using sprite masks (in GM:S 1.4)

Hypotakt

Member
Hey guys,

I am obviously searching for a smooth collision handling system for my game. I spent a lot of time today, finding a good way to implement, but had no success yet.

The game character is moving per direction and speed, but it has only 4 different directions in sprite (left, right, up and down). I am doing the direction thing with a gamepad, so 360° is possible to move. I have objects, like trees, which the player can't access. So moving in the direction should not be possible. Every Sprite has a mask (Bounding Box) which I setted already.

All my tries leaded to bad results, like the player get's pushed away from the tree mask but since my view is following the player the screen was shaking hardcore (player can move again, every time it's pushed away). An other bad result was that the movement stopped when I the player was on 1px distance to the hitbox tree, but the movement was completly stucked.

I tried it many ways, but everything leads to a lot of redudant code (slow build at the end) or a lot of bugs. You guys can help out with some neat solution? I'm sick of can't solve this problem ^^

PS: If it's not clear - I search especially for a system which works for the whole mask. The X,Y of each sprite is centered, but if I use something like place_free() it checks just for the center of the sprite and the mask has access to the tree.

- cheers
 
Last edited:

Hypotakt

Member
Bump. I think I got a better system now, but it's still sloppy. Would be great if anyone could share some ideas :)
 
R

Rugensoft

Guest
Hey Mate,

i got it handled like this:

Code:
//Horizontal Collision
if (place_meeting(x+hsp,y,owall))
{
    while (!place_meeting(x+sign(hsp),y,owall))
    {
        x = x + sign(hsp);
    }
    hsp = 0;
}
x = x + hsp;

//Vertikal Collision
if (place_meeting(x,y+vsp,owall))
{
    while (!place_meeting(x,y+sign(vsp),owall))
    {
        y = y + sign(vsp);
    }
    vsp = 0;
}
y = y + vsp;

//Animation
if (!place_meeting(x,y+1,owall))
{
    sprite_index = splayerA;
    image_speed = 0;
    if (sign(vsp) >0) image_index = 1; else image_index = 0;
}
else
{
    image_speed = 1;
    if (hsp == 0)
    {
        sprite_index = (splayer); //you will change the sprite, since you dont want the animation to be stuck
    }
    else
    {
    sprite_index = (splayerR);
    }
}
Hope you can gather some Information from this.
If you have questions i try to get deeper in my code (its couple of years since i wrote it).

Greetings
Rugensoft
 

Hypotakt

Member
Well, this code snippet opened my eyes! I worked so much with speed and angles that I completely ignored the fact, that a push-away from a blocking object an absolute thing is. I can use speed and angles for movement, and for collision handeling absolute x / y. Thanks man, you really helped me a lot!

Btw, the basic structure for the solution is this:
GML:
//;;THIS IS A SCRIPT CALLED player_do_collision_handeling();;

//COLLISION LEFT
if(blocking_objects(x - 1,y))
{
    image_speed = 0;
   
    while(blocking_objects(x - 1,y))
    {
        x++;
    }

    image_speed = animation_speed;
}
//COLLISION RIGHT
if(blocking_objects(x + 1,y))
{
    image_speed = 0;
   
    while(blocking_objects(x + 1,y))
    {
        x--;
    }

    image_speed = animation_speed;
}
//COLLISION BOTTOM
if(blocking_objects(x, y + 1))
{
    image_speed = 0;
   
    while(blocking_objects(x, y + 1))
    {
        y--;
    }

    image_speed = animation_speed;
}
//COLLISION TOP
if(blocking_objects(x, y - 1))
{
    image_speed = 0;
   
    while(blocking_objects(x, y - 1))
    {
        y++;
    }

    image_speed = animation_speed;
}
And the blocking_objects() method is a custom script aswell, to support several blocking objects:
GML:
//;;THIS IS A SCRIPT CALLED blocking_objects();;

//Checks collisions with blocking objects;
//scr_blocks = array with blocking objects, ret_bool = result of place_meeting();
var scr_blocks;
var ret_bool = false;

scr_blocks[0] = tree_obj;
scr_blocks[1] = enemy_common_obj;
scr_blocks[2] = player_obj;

for(var scr_block = 0; scr_block < array_length_1d(scr_blocks); scr_block++){
    ret_bool = place_meeting(argument[0], argument[1], scr_blocks[scr_block]);
    if(ret_bool){
        break;
    }
}

return ret_bool;
Now the only thing which is left to do, is to set the mask for all sprites and put a call of 'player_do_collision_handeling()' into a step event :)
 
Top