Knockback not working ?

V

ValDCX

Guest
Hi everybody,

I'm very new here and I am a beginner with Game Maker.
I'm trying to make a top down game, but I can't manage to get the player knockback working. I want the player to be knocked back by enemies when he touches them, so I created a collision event in the enemy object and used this code:

obj_player.speed = -10
alarm [0] = 5

Then i made an alarm event :

obj_player.speed += 10;

But when I touch an enemy, my character is not knocked back, but knocked left instead. I dont know what to do, does somebody have an idea ? Thanks.
 

TsukaYuriko

☄️
Forum Staff
Moderator
speed, when used the way you did, will only do what you expect it to if you're using the default movement system. If you're somehow interfering with this movement system or using a different movement system altogether, this code is not a suitable solution for what you are trying to do.

It is impossible to say any more than this without knowing how you're handling movement.
 
V

ValDCX

Guest
Hi, thanks for your answer.
To move my character, I made four keyboard events (one for each direction), and each event sets the x or y variable to 3 or -3. I don't know if this is the right way, as I said, I am just discovering Game Maker.
 
M

montiedragon

Guest
For knock back, you would have to check the direction of the enemy, and move in the opposite direction. Luckily, rather then using math that may be a little complicated for beginners, Gamemaker: Studio has functions to help. Just try something like this in the collision code.

Code:
var dir, knock;

knock = 10;//knockback distance

dir = point_direction(x, y, other.x, other.y) + 180 mod 360;//gets the direction from your location and turns it the opposite direction
//"mod 360" wraps the code to 360 so if the value is 361, it changes it to 1. It's not necessary as most of the functions will accept larger values but it is typically a good idea to do this anyway.

//move the object the distance and direction specified
x += lengthdir_x(knock, dir);
y += lengthdir_y(knock, dir);
edit: More specific comments.
 
V

ValDCX

Guest
This is exactly what I was looking for, thank you so much ! I do understand your code, so it really helps. Thank you.
 
R

Robert

Guest
Just fyi it can get a little more complicated. For example you don't want to get knocked into a wall or enemy so you should add some collision detection to the code. Also the code posted only does instant knock back, maybe you want it to be animated where it moves back a pixel every step for 10 steps or something, but you might like the instant knock back.
 
V

ValDCX

Guest
Hi Robert, thanks for your answer. Indeed, you are right, I should add some collision check, but the problem is, I'm not very comfortable using GML and I don't really know how to do. What do you suggest?
 
M

montiedragon

Guest
rather than using the value all at once, loop through each pixel and check for a collision so something similar to this
Code:
repeat(knock){
    xx += lengthdir_x(knock, dir);
    yy += lengthdir_y(knock, dir);
    if !collision_point( xx, yy, wall object goes here, 1, 1 );{
        x = xx;
        y = yy;
        }
    }
edit: typo
 
Last edited by a moderator:
V

ValDCX

Guest
Thanks again montiedragon, but I can't get your second piece of code to work. I can't manage to make the loop work properly.
 
Last edited by a moderator:
M

montiedragon

Guest
Oops. "loop" should have been "repeat". I fixed it in the post above. My bad.
 
V

ValDCX

Guest
I'm sorry but it still doesn't work... Actually I am not sure of what to do with your second piece of code. Where exactly am I supposed to put it? Right after the first piece? I really try to understand.
Sorry about all these dumb questions by the way, but I really want this knockback to work properly...
 
M

montiedragon

Guest
The entire code ( with a few improvements). Also are you copying and pasting? Because there is a bit of psudocode in it
Code:
var dir, knock;

knock = 10;//knockback distance
xx = x;
yy = y;
dir = point_direction(x, y, other.x, other.y) + 180 mod 360;//gets the direction from your location and turns it the opposite direction
//"mod 360" wraps the code to 360 so if the value is 361, it changes it to 1. It's not necessary as most of the functions will accept larger values but it is typically a good idea to do this anyway.

//move the object the distance and direction specified.
//This method essentially moves the object 1 pixel at a time while checking for a collision.
repeat(knock){
   xx += lengthdir_x(knock, dir);
    yy += lengthdir_y(knock, dir);
    if (!collision_square( xx, yy, xx + sprite width, yy + sprite height, wall object goes here, 1, 1 ));{ //checks if there is a collision at the destination
        //moves the object after confirming no collision.
        x = xx;
        y = yy;
        }
    }
 
V

ValDCX

Guest
Thanks again for this improvement to the code. Unfortunately, it still doesn't work. The player is only knocked back when touching an enemy from below. If touching it from anywhere else, the player instantly dies.
Also, I am not copy-pasting. I read the code carefully and try to understand it before I use it. By the way, when writing "collision_square", did you mean "collision_rectangle" ?
Right now, the code looks like this :

Code:
var dir, knock;

knock = 10;//knockback distance
xx = x;
yy = y;
dir = point_direction(x, y, other.x, other.y) + 180 mod 360;//gets the direction from your location and turns it the opposite direction
//"mod 360" wraps the code to 360 so if the value is 361, it changes it to 1. It's not necessary as most of the functions will accept larger values but it is typically a good idea to do this anyway.

//move the object the distance and direction specified.
//This method essentially moves the object 1 pixel at a time while checking for a collision.
repeat(knock){
   xx += lengthdir_x(knock, dir);
    yy += lengthdir_y(knock, dir);
    if (!collision_rectangle( xx, yy, xx + sprite_width, yy + sprite_height, obj_brick, 1, 1 ))
    { //checks if there is a collision at the destination
        //moves the object after confirming no collision.
        x = xx;
        y = yy;
        }
    }
 
Top