• Hey! Guest! The 40th (!!!) GMC Jam will take place between February 25th, 12:00 UTC to March 1st 12:00 UTC. Why not join in this very special anniversary jam! Click here to find out more!

SOLVED Collision issue (works from all angles but one)

Solthall

Member
Hello.

Got some weird issue with my collision. I'm aware that this might not be the best code, but I'm still learning.
Hard to find complete tutorials on top down movement and collisions (taking sprite/mask rotations into account). But managed to draw the player sprites in the draw event, even though it's quite a hassle.

So the collision works from three angles, when I hit the solid from the top, beneath and the right. Left is not working, player walks into the wall and gets stuck!
The game is top down, player moves towards and rotates with mouse angle.

Here's the whole movement script:

GML:
function scr_movement()
{

//Input movement
forward = keyboard_check(ord("W"));
backward = keyboard_check(ord("S"));
right = keyboard_check(ord("D"));
left = keyboard_check(ord("A"));

//Movement direction
if obj_stairs.alarm[0] == -1
{
    if forward
    {
        speed = walkSpeed;
    }
    
    if backward
    {
        speed = -walkSpeed;
    }
    
    if right
    {
        direction += 90;
        speed = -walkSpeed;
    }
    
    if left
    {
        direction -= 90;
        speed = -walkSpeed;
    }
}
 
// Stop moving when no key is pressed // Not working, I can keep moving if I press any key while pressing movement input
if keyboard_check(vk_nokey)
{
    speed = 0;
    image_index = 0;
    //image_speed = 0;
}

// Stop moving if multiple inputs detected
if left and right
{
    speed = 0;
    image_index = 0;
    image_speed = 0;
}

// Stop moving if colliding with mouse pointer or shop/inventory open
if point_distance(x,y,mouse_x,mouse_y) < 15
or global.shop == true
or obj_inv_control.drawInventory == true
{
    speed = 0;
    image_index = 0;
    image_speed = 0;
}

if instance_exists(obj_attack) and obj_attack.image_index <= 2 //Player attack speed boost
{
    speed += 2;
}

//Collision check
if place_meeting(x + hspeed, y, obj_solid)
{
    if !place_meeting(x + sign(hspeed), y, obj_solid) //while (instead of "if" but causes crash)
    {
        speed -= min(abs(hspeed),1)*sign(hspeed);
    }
    hspeed = 0;   
}

if place_meeting(x, y + vspeed, obj_solid)
{
    if !place_meeting(x, y + sign(vspeed), obj_solid) //while (instead of "if" but causes crash)
    {
        speed -= min(abs(vspeed),1)*sign(vspeed);
    }
    vspeed = 0;   
}   
}
 

Nidoking

Member
I don't understand why you're ever setting speed to be -walkSpeed, rather than just setting the direction accordingly. I believe that's the root of all of your problems.
 

Solthall

Member
Thanks! Could you elaborate a bit on that?
Right and left makes the player strafe arround the mouse pointer, if I change the code he moves in wrong directions.

Tried:
direction -= 90;
speed = walkspeed;

But probaly misunderstood what you meant here..
 

Nidoking

Member
speed and direction interact to create movement. Setting negative speed is... weird, to say the least. I just can't grasp what the actual motion of your instance is supposed to be, but the things you're doing with speed here just look completely wrong to me. Then you're checking for collision using hspeed and vspeed, but adjusting speed instead of hspeed or vspeed. I think you might be better off rethinking your movement entirely. It looks like you've piled stuff on little by little and made random changes until you got something that looked correct in some way. Planning the entire movement from the start and programming it according to your plan will serve you well.
 

Solthall

Member
The problem could be as simple as the hitbox for your left walking sprite is shifted slightly more to one side as compared to the other sprites.
I only have one sprite atm. If idle, the image_speed and index is set to zero, other than that, I set img speed to 1.
I used a precise collision mask for the player, and the mask covered the player equally on all sides. But switching to a rectangular mask that is slightly bigger than the player, fixed my issue. Thank you!
 

Solthall

Member
speed and direction interact to create movement. Setting negative speed is... weird, to say the least. I just can't grasp what the actual motion of your instance is supposed to be, but the things you're doing with speed here just look completely wrong to me. Then you're checking for collision using hspeed and vspeed, but adjusting speed instead of hspeed or vspeed. I think you might be better off rethinking your movement entirely. It looks like you've piled stuff on little by little and made random changes until you got something that looked correct in some way. Planning the entire movement from the start and programming it according to your plan will serve you well.
With all due respect, I dont just pile stuff on. The movement itself is from a top down shooter tutorial(that was cut short of collisions). Other than that, I use the manual or whatever other information is at hand. But I will admit that it's a process of trial and error.
From what I understand though, if I adjust speed i any way it will also affect hspeed/vspeed (and vice versa). It seems I need hspeed and vspeed in the collision to make it work in a smooth manner. If I replace those values with just speed, I get stuck on collision. With the current hspeed and vspeed in the collision code, the player object slides alongside the walls, as it should. The movement might resemble that of Hotline Miami, just to make it a bit more clear.
I don't have the angle inside this script, but it's in the player object. and is set to move relative to the mouse pointer position.

Code:
angle = point_direction(x,y,mouse_x,mouse_y);
direction = angle;
I get what you're saying about setting negative speed, I now see that it's unecessary. So i cleaned up the code a bit.

GML:
//Input movement
forward = keyboard_check(ord("W"));
backward = keyboard_check(ord("S"));
right = keyboard_check(ord("D"));
left = keyboard_check(ord("A"));

if !forward and !backward and !right and !left
{
    speed = 0;
    image_index = 0;
    image_speed = 0;
}
else
{
    speed = 1;
}

//Movement direction
if obj_stairs.alarm[0] == -1
{
    if backward
    {
        direction += 180;
    }
    
    if right
    {
        direction += 90;
    }
    
    if left
    {
        direction -= 90;
    }
}
 
// Stop moving if multiple inputs detected
if left and right
{
    speed = 0;
    image_index = 0;
    image_speed = 0;
}
I appreciate the help, thank you!
 
Top