GMS 2 Knockback

J

Jacco

Guest
Hi all,

I have a problem with creating knockback. I want a player to have a little bit of horizontal and vertical speed when hit by a bullet. So when colliding with a bullet, the variables hsp and vsp of the player should change. However only vsp changes!

Heres my code i have in the step event of the bullet:

Code:
if (place_meeting(x,y,obj_player1))
{
     with(obj_player1)     
     {         hp--; //hp -1         
               flash = 3;         
               hitfrom = other.direction;         
               direction = hitfrom;         
               hsp += 3;         
               vsp += -3;     
      }     
      instance_destroy(); 
}
and here is the code I use in the player object:

Code:
if(!place_meeting(x,y,obj_bullet)) 
{
     hsp = move * walksp; 
} 
vsp = vsp + grv;
My guess is the bullet gets destroyed before the hsp is increased or maybe because the hsp is set back to move * walksp faster than the collision happened. I tryed putting the first code in a beginstep event or endstep event, but it didn't work. When i don't destroy the bullet the code works and the hsp increases. But I want the bullet to get destroyed. Do you guys have any idea what is going wrong, and what is a solution? I'm using GameMaker 2 btw.

Thanks!
 

kupo15

Member
it all depends on your code order. For example your bullet collision code is fine, its getting destroyed after applying those variables. However if your second code is occurring after the collision code its not going to work because hsp is being SET to a value thus overwriting what came before:

Bullet code
hsp += 3 >>>>> HSP = 3;

Move code
hsp = move*walksp = 0 >>>>>HSP is set to 0

I assume move is a simple bool whether or not the player is moving. It doesn't matter anyway because that line "if it comes after the bullet" is overwriting the hsp of the bullet.

Notice how vsp works because it still has vsp in it thus its carrying over the vsp from the bullet hit but hsp is not doing so
 
J

Jacco

Guest
it all depends on your code order. For example your bullet collision code is fine, its getting destroyed after applying those variables. However if your second code is occurring after the collision code its not going to work because hsp is being SET to a value thus overwriting what came before:

Bullet code
hsp += 3 >>>>> HSP = 3;

Move code
hsp = move*walksp = 0 >>>>>HSP is set to 0

I assume move is a simple bool whether or not the player is moving. It doesn't matter anyway because that line "if it comes after the bullet" is overwriting the hsp of the bullet.

Notice how vsp works because it still has vsp in it thus its carrying over the vsp from the bullet hit but hsp is not doing so
That is what i thought as well, however therefore I used the ! negator in the player object code. But that's still not working i think because the collision is too short to give the hsp+=3 when the bullet gets destroyed. Therefore the ! negator doesn't do anything. Do you know how I can solve this?
 

kupo15

Member
That is what i thought as well, however therefore I used the ! negator in the player object code. But that's still not working i think because the collision is too short to give the hsp+=3 when the bullet gets destroyed. Therefore the ! negator doesn't do anything. Do you know how I can solve this?
I don't understand what you are saying and its hard to know without code you are referencing. Where is the code that is setting the x and y position? I'm assuming somewhere there is an x += hsp and y += vsp. And why did you add a ! in there?

Then the player would just skip a couple of pixels and move directly to the new x right?
This is exactly what movement is like in games. Even Hspeed and Vspeed does this. Its all skipping pixels and moving directly to a new x,y position
 
J

Jacco

Guest
I don't understand what you are saying and its hard to know without code you are referencing. Where is the code that is setting the x and y position? I'm assuming somewhere there is an x += hsp and y += vsp. And why did you add a ! in there?
The if(!place_meeting(x,y,obj_bullet) part was an attempt to fix the problem of hsp updating by move*walksp right after hsp+=3 in the bullet.

You're exactly right about the y+=vsp and c+=hsl.
 

kupo15

Member
The if(!place_meeting(x,y,obj_bullet) part was an attempt to fix the problem of hsp updating by move*walksp right after hsp+=3 in the bullet.

You're exactly right about the y+=vsp and c+=hsl.
Ok this is what you need to do

Code:
// set movement speed first
hsp = move * walksp;
vsp += grv;

// add bullet kb next
if (place_meeting(x,y,obj_player1))
{
     with(obj_player1)   
     {         hp--; //hp -1       
               flash = 3;       
               hitfrom = other.direction;       
               direction = hitfrom;       
               hsp += 3;       
               vsp += -3;   
      }   
      instance_destroy();
}

// update your position
x += hsp;
y += vsp;
I'm not sure where your movement code is in relation to your collision code. If you want to keep the collision code in the bullet object instead of the player object you need to put

the player movement code in the begin step
the bullet collsion in the step
and the update position in the end step

If you are going to have the player check for the collision instead which I think is cleaner then you can have them all happen in the same step in that exact order otherwise the movement will once again override the kb.

One last option would be to throw a conditional in front of the movement code so that it doesn't activate when you get stunned otherwise in your current way of doing it, if you are moving while getting hit then you will have the knockback happen for one frame then the next frame the kb hsp won't be there anymore and it will be replaced by the walking movement

Code:
if !in_kb
hsp = move * walksp;
vsp += grv;
 
J

Jacco

Guest
Ok this is what you need to do

Code:
// set movement speed first
hsp = move * walksp;
vsp += grv;

// add bullet kb next
if (place_meeting(x,y,obj_player1))
{
     with(obj_player1)  
     {         hp--; //hp -1      
               flash = 3;      
               hitfrom = other.direction;      
               direction = hitfrom;      
               hsp += 3;      
               vsp += -3;  
      }  
      instance_destroy();
}

// update your position
x += hsp;
y += vsp;
I'm not sure where your movement code is in relation to your collision code. If you want to keep the collision code in the bullet object instead of the player object you need to put

the player movement code in the begin step
the bullet collsion in the step
and the update position in the end step

If you are going to have the player check for the collision instead which I think is cleaner then you can have them all happen in the same step in that exact order otherwise the movement will once again override the kb.

One last option would be to throw a conditional in front of the movement code so that it doesn't activate when you get stunned otherwise in your current way of doing it, if you are moving while getting hit then you will have the knockback happen for one frame then the next frame the kb hsp won't be there anymore and it will be replaced by the walking movement

Code:
if !in_kb
hsp = move * walksp;
vsp += grv;
It works by putting everything in the right order in the player object! Thanks for this. The only problem I have now is that instance_destroy destroys all bullets now instead of only the one that is colliding.
Code:
if (place_meeting(x,y,obj_bullet))
{
    hp--; //hp -1
    flash = 3;
    hitfrom = obj_bullet.direction;
    direction = hitfrom;
    hsp += 3;
    vsp += -3;
    instance_destroy(obj_bullet);
}
Do you have a solution for this?
 

kupo15

Member
Great glad to hear it! Its probably because you specified obj_bullet in the instance_destroy line. Simply do instance_destroy() instead
 
J

Jacco

Guest
Great glad to hear it! Its probably because you specified obj_bullet in the instance_destroy line. Simply do instance_destroy() instead
Well if I do that it destroys the player, because im working in the player step now.
 

kupo15

Member
Well if I do that it destroys the player, because im working in the player step now.
oh right, then you need to use a different function and capture the id of the bullet you collided with

Code:
var bullet_id = with (instance_place(x,y,obj_bullet)) // check for a collision and return the id of the bullet inside bullet_id
{
    hp--; //hp -1
    flash = 3;
    hitfrom = obj_bullet.direction;
    direction = hitfrom;
    hsp += 3;
    vsp += -3;
    instance_destroy(bullet_id); // destroy that single bullet from the id you stored
}
 
J

Jacco

Guest
oh right, then you need to use a different function and capture the id of the bullet you collided with

Code:
var bullet_id = with (instance_place(x,y,obj_bullet)) // check for a collision and return the id of the bullet inside bullet_id
{
    hp--; //hp -1
    flash = 3;
    hitfrom = obj_bullet.direction;
    direction = hitfrom;
    hsp += 3;
    vsp += -3;
    instance_destroy(bullet_id); // destroy that single bullet from the id you stored
}
You are my hero man! Thank you so much for helping out a beginner! Spent so much time on this small thing. It finally works!
 

kupo15

Member
You are my hero man! Thank you so much for helping out a beginner! Spent so much time on this small thing. It finally works!
Glad to hear it! Sure thing, collisions are one of those easy things in principle but are super tricky for some reason. We've all been there before, glad to pay it forward :)
 
Top