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

GameMaker Help With Player Collision GMS2 (SOLVED)

KPJ

Member
I am making a top down game in gms2, and I have an issue with collisions. I have two player sprites (Idle and Walk). The walk sprite is a bit larger than the player sprite. Both are irregular shapes (top down humans), and both their collision masks are precise (for bullet collision).
When my player collides with the wall, everything works except for two things:

1) if my player collides with the wall (let's say the wall is above me) and i am not pressing any key, it is the idle sprite, and everything works. however if i press the w (up) key, then it will change to the walk sprite (which is larger than the idle sprite and the walk sprite will get stuck in the wall so the player cannot move.
Made in GameMaker Studio 2 1_20_2019 12_12_21 PM.png


2) If I rotate my player (it follows my mouse) it's arm will get stuck in the wall, and again, it will be unable to move.
Made in GameMaker Studio 2 1_20_2019 12_22_45 PM.png

I don't think it's an issue with the code, but here it is anyway
Code:
Code:
//Player Create Event
movespd = 2;

hspd = 0;
vspd = 0;


//Player Step Event
//Movement
upkey = -(keyboard_check(ord("W")))
leftkey = -(keyboard_check(ord("A")))
downkey = (keyboard_check(ord("S")))
rightkey = (keyboard_check(ord("D")))

horizontal = rightkey + leftkey;
vertical = upkey + downkey;
hspd = horizontal * movespd;
vspd = vertical * movespd;

//Movement & Collision
//Horizontal
if (place_meeting(x + hspd, y, oWall))
{
    while(!place_meeting(x + sign(hspd), y, oWall))
    {
        x += sign(hspd);
    }
  
    hspd = 0;
}

x += hspd;

//Vertical
if (place_meeting(x, y + vspd, oWall))
{
    while(!place_meeting(x, y + sign(vspd), oWall))
    {
        y += sign(vspd);
    }
  
    vspd = 0;
}

y += vspd;
 

mimusic

Member
I don't see any code designed to move the player object out of the wall if it somehow ends up partially inside / clipping. Your current code only accounts for collisions that are detected within the current motion vector, which it seems also halts horizontal/vertical speed so long as the collision is detected (which I think will continue to be detected if you're clipping in). Might need to add code that pushes the player back out in cases like these?

You could also consider using a different type of collision mask specifically against walls, like a circle, so that you can keep the precise bullet detection but have a more general, sprite-independent mask for the walls. I'd recommend you check out collision_rectangle() and collision_circle() and see if those might work for you here.

Also, is your wall object set to "solid" in the IDE? I've personally never had luck with that property being on, it always led to objects sticking and being unable to move.

This is all guesswork, though. I've always leaned toward math-based collision versus GM's built in sprite-based stuff, so these suggestions might not pan out so long as you're using sprite based collision.
 

KPJ

Member
Yes, my wall is solid. Could you give me an idea of the code i would need to implement your suggestion? Thanks!
 

johnwo

Member
You've already got a topic on this here.

Just edit the OP with this information instead of having two topics on basically the same thing.
 

mimusic

Member
Yes, my wall is solid. Could you give me an idea of the code i would need to implement your suggestion? Thanks!
Not gonna write the whole code out, but this should be good enough to give you an idea of what needs to be done. There are definitely way better ways to do this, this is mainly to give you the abstract idea. I encourage you to improve on the provided code, if you decide to use it. (please note, this is only effective if your level geometry is a buncha rectangles. If you start using circles or other shapes for your level map, this fix might not work so well)
Code:
//Check for collisions to the right
var _col = collision_point( x + 8, y, oWall, some other params i dont remember );
if (_col) {
    while (collision_point( x + 8, y, oWall, some other params i dont remember )) {
        x -= 1;
    }
}
this code will check if you're touching a wall 8 pixels to the left. If you are, you'll get pushed back until collision is no longer detected. You would need to do this 3 more times for the 3 other cardinal directions. Might need to make some other changes to the existing code, not sure

one last thing, this doesnt handle collision against corners well. For that, you'll need a more robust collision area, which I would recommend collision_rectangle for -- something like collision_rectangle(x, y -7, x +8, y +7, oWall, stuff, stuff, stuff...);
 
Top