GML Player knock back after hit

Hi all! I've spent 2 days trying to get this to work and I know I'm close but being a noob is not easy. I had a look at all the other forums but it doesn't seem to be what I need or is a different method.
So in my 2d platformer when player is hit by an enemy I want them to get knocked left or right depending on the side of the enemy I get hit from.
Here is my code so far. I assume I need the "Sign" function in there but im not sure how to utilise it.

if (place_meeting(x,y,oHamish))
{
if (oHamish.y < y-16)
{
with (oHamish) vsp = jump;
}

else
{
if (oHamish.x > x-16)
{
with (oHamish) hsp = -10;
}
}
}

As you can see if I collide from the top I jump, if I collide from the left I get knocked back. How do I get the right side to knock me back? I have tried using sign but I am obviously writing it wrong if that's what I should do.

Anyway, Thanks to any one who can help. Love you all. You have all been so helpful.
 
Last edited:

Slyddar

Member
If the code you have is working, but you just need to have a right knockback, can't you just add another condition that checks the other side, so if oHamish.x < x+16 is true set hsp = 10 ?
 
If the code you have is working, but you just need to have a right knockback, can't you just add another condition that checks the other side, so if oHamish.x < x+16 is true set hsp = 10 ?
Thanks for helpin out. I tried this earlier but it will still only collide from the left, do you know if I am entering it in the wrong place? Here is the code I used...
Code:
if (place_meeting(x,y,oHamish))
{
    if (oHamish.y < y-16)
    {
        with (oHamish) vsp = jump;
    }
   
    else
    {
        if (oHamish.x > x-16)
        {
            with (oHamish) hsp = -10;
        }
        if (oHamish.x < x+16)
        {
            with (oHamish) hsp = 10;
        }
    }
}
 

Slyddar

Member
This is your code, I've just put it into a collision event in the player, between the player and the enemy. It's a very basic knockback effect, and it works ok.
Code:
var knockback = 20;
if (y < other.y - 16)
{
    vsp = jump;
}
else
{
    if (other.x > x - 16)
    {
        hsp = -knockback;
    }
    if (other.x < x + 16)
    {
        hsp = knockback;
    }
}
To do a true knockback effect it depends on how you have your hsp setup in your step. If you are adding onto the hsp per step, it will be different to if you are assigning your hsp per step.
For example
Code:
var move = key_right - key_left;

//assigning
hsp = move * dir;

//additive
hsp += move * dir;
A more complex way to do knockback is create another variable, called hsp_carry, for example, and have that carry any additional hsp. This means the players input won't cancel out the knockback/hsp. You should also apply drag to hsp_carry to reduce it's effect over time.

You could do it like this:
Player Create
Code:
walksp = 6;
grav = .8
hsp = 0;
hsp_carry = 0;
hsp_slowdown = 0.3;
hsp_max = 4;
vsp = 0;
jump = -13;
Player Step
Code:
key_left = keyboard_check(vk_left);
key_right = keyboard_check(vk_right);
key_jump  = keyboard_check_pressed(vk_space);

//apply movement
var move = key_right - key_left;

//drag
hsp_carry = lerp(hsp_carry, 0, hsp_slowdown);

//set hsp
hsp += move * walksp;

//limit hsp
hsp = clamp(hsp, -hsp_max, hsp_max);

//drag
hsp = lerp(hsp, 0, hsp_slowdown);

//set total hsp
hsp = hsp + hsp_carry
Player <> Enemy Collision
Code:
var knockback = 20;
if (y < other.y - 16)
{
    vsp = jump;
}
else
{
    if (other.x > x - 16)
    {
        hsp_carry = -knockback;
    }
    if (other.x < x + 16)
    {
        hsp_carry = knockback;
    }
}
 
Last edited:
This is incredible! Thanks so much for your help and the multiple options. I'll use the easy one for now just to get the functionality in. Then I'll implement the more complex one for any new games I make.

I have a question though, this code seems to only work from the right. If I collide on the left of the enemy I am pushed through to the right. Any idea why?
Code:
var knockback = 20;
if (y < other.y - 16)
{
    vsp = jump;
}
else
{
    if (other.x > x - 16)
    {
        hsp = -knockback;
    }
    if (other.x < x + 16)
    {
        hsp = knockback;
    }
}
 
Last edited:

Kyon

Member
This is incredible! Thanks so much for your help and the multiple options. I'll use the easy one for now just to get the functionality in. Then I'll implement the more complex one for any new games I make.

I have a question though, this code seems to only work from the right. If I collide on the left of the enemy I am pushed through to the right. Any idea why?
Code:
var knockback = 20;
if (y < other.y - 16)
{
    vsp = jump;
}
else
{
    if (other.x > x - 16)
    {
        hsp = -knockback;
    }
    if (other.x < x + 16)
    {
        hsp = knockback;
    }
}


Try put else between those 2.
Code:
if (other.x > x - 16)
    {
        hsp = -knockback;
    }
    else if (other.x < x + 16)
    {
        hsp = knockback;
    }
}
Also it could also be something about other.x<x+16
Because that says if the other one if LEFT of your x position with 16 pixels to the RIGHT.
Which means it could still trigger if you stood like 10 pixels to the right of his x position.
But this all depends on your sprite and collision mask. If you have a 32px mask with the x at the centre of that, this is fine I guess.
 

Slyddar

Member
You might want to replace the 16 with
sprite_get_width(sprite_index)/2
as I made the assumption based on your original code that all sprites were 32x32, but magic numbers like that are never good in the end.
 
Try put else between those 2.
Code:
if (other.x > x - 16)
    {
        hsp = -knockback;
    }
    else if (other.x < x + 16)
    {
        hsp = knockback;
    }
}
Also it could also be something about other.x<x+16
Because that says if the other one if LEFT of your x position with 16 pixels to the RIGHT.
Which means it could still trigger if you stood like 10 pixels to the right of his x position.
But this all depends on your sprite and collision mask. If you have a 32px mask with the x at the centre of that, this is fine I guess.

This works perfect! Its exactly what I wanted. Thank you so much!
 
Top