knockback not working

S

SashoTAI

Guest
So the knockback when an enemy touches the player doesn't work very well and nearly kills the player instantly since the player's health is only five. Here is my knockback code:
  1. obj_player.hspeed_ = random_range(-14,14)
  2. obj_player.y += -4
so for this I was going to add invincibility frames. But first I needed to fix the knockback. I couldn't really think of anything else tough so I came here. Any ideas? (It's a platformer game by the way).
 
Last edited by a moderator:

flerpyderp

Member
Post your movement code. Also, if collision with the player gives the player a horizontal speed anywhere between -14 and 14, then there's a high chance the player will move towards the enemy rather than away from it. Is this intentional?

As for the invincibilty frames, you could add a variable which starts as false, becomes true on collision with the enemy, then has a short timer to count down to make it false again. The player will only lose HP while it is false, so it only takes away HP once rather than every step that a collision is happening.

Player create event:
Code:
hit = false;
timerMax = 30;
timer = timerMax;
Enemy collision event with player (I'm assuming that's where your collision code is):
Code:
if (!obj_player.hit)
{
    obj_player.hit = true;
    obj_player.HP --;
}
Player step event:
Code:
if (hit)
{
    if (timer > 0)
    {
         timer --;
    }
    else
    {
         hit = false;
         timer = timerMax;
    }
}
 
Last edited:
S

SashoTAI

Guest
Post your movement code. Also, if collision with the player gives the player a horizontal speed anywhere between -14 and 14, then there's a high chance the player will move towards the enemy rather than away from it. Is this intentional?

As for the invincibilty frames, you could add a variable which starts as false, becomes true on collision with the enemy, then has a short timer to count down to make it false again.

Create:
Code:
hit = false;
timerMax = 30;
timer = timerMax;
Collision event (I'm assuming that's where your collision code is):
Code:
if (!obj_player.hit)
{
    obj_player.hit = true;
    obj_player.HP --;
}
Player step event:
Code:
if (hit)
{
    if (timer > 0)
    {
         timer --;
    }
    else
    {
         hit = false;
         timer = timerMax;
    }
}
No it's not intentional, it's supposed to go away from the enemy so it doesn't kill the player as fast, and for a cool effect.
My movement code:
var hinput = keyboard_check(vk_right) - keyboard_check(vk_left)

if hinput != 0
{
hspeed_ += hinput*acceleration_;
hspeed_ = clamp(hspeed_, -max_hspeed_, max_hspeed_);
} else
{
hspeed_ = lerp(hspeed_, 0, .3);
}
My collision codes:
if !place_meeting (x, y+1, obj_solid)
{
vspeed_ = vspeed_ + gravity_;
} else
{
if keyboard_check_pressed(vk_space)
{
vspeed_ = jump_height_
}
}

if place_meeting (x + hspeed_, y, obj_solid)
{
while !place_meeting (x + sign(hspeed_), y, obj_solid)
{
x += sign(hspeed_);
}
hspeed_ = 0
}

x = x + hspeed_

if place_meeting (x, y + vspeed_, obj_solid)
{
while !place_meeting (x, y + sign(vspeed_), obj_solid)
{
y += sign(vspeed_);
}
vspeed_ = 0
}

y = y + vspeed_
I am just going to mention that I put this code:
obj_player.hspeed_ = random_range(-14,14)
obj_player.y += -4
In a with other() statement in the enemy object in a collision to player event.
Also what does --; do? Just curious
 

flerpyderp

Member
"with other()" is unnecessary if you're using "obj_player." to reference the player object's variables. You could just use one or the other.

I would add a new variable to the player, let's call it knockDir. If the enemy's x coordinate is greater than that of the player's (it's to the right of the player), knockDir is given a value of -1, otherwise knockDir is given a value of 1. We then multiply the knockback speed by this value, making the player move either left or right depending on its position relative to the enemy which collided with it.

Player create event:
Code:
knockDir = 1;
In the collision event:
Code:
if (x > obj_player.x) obj_player.knockDir = -1;
else obj_player.knockDir = 1;

obj_player.hspeed_ = obj_player.knockDir * random_range(7,14); //Use whatever values work best
obj_player.y += -4
Also what does --; do? Just curious
It subtracts a value of 1 each step. It's a shorter way of writing "timer -= 1", or "timer = timer-1".
 
S

SashoTAI

Guest
"with other()" is unnecessary if you're using "obj_player." to reference the player object's variables. You could just use one or the other.

I would add a new variable to the player, let's call it knockDir. If the enemy's x coordinate is greater than that of the player's (it's to the right of the player), knockDir is given a value of -1, otherwise knockDir is given a value of 1. We then multiply the knockback speed by this value, making the player move either left or right depending on its position relative to the enemy which collided with it.

Player create event:
Code:
knockDir = 1;
In the collision event:
Code:
if (x > obj_player.x) obj_player.knockDir = -1;
else obj_player.knockDir = 1;

obj_player.hspeed_ = obj_player.knockDir * random_range(7,14); //Use whatever values work best
obj_player.y += -4


It subtracts a value of 1 each step. It's a shorter way of writing "timer -= 1", or "timer = timer-1".
Ok thank you for the help :)
 
S

SashoTAI

Guest
Hey. So I added the invincibility frames to my player character. I was going to make it kind of flash so the player knows it's invincible, but they also knows where they are. My invincibility frames in the step event of the player.
  1. if (hit_)
  2. {
  3. if (timer_ > 0)
  4. {
  5. timer_ --;
  6. } else
  7. {
  8. hit_ = false;
  9. timer_ = timerMax_;
  10. image_alpha = 1;
  11. }
  12. }
Create event variables:
  1. hit_ = false;
  2. timerMax_ = 90;
  3. timer_ = timerMax_;
As you can see, I've made it so it becomes visible after the timer_ ends. I've also set it to become invisible in the collision between the enemy object and the player object here:
  1. if (!obj_player.hit_)
  2. {
  3. obj_player.hit_ = true;
  4. obj_player.hp_ --;
  5. obj_player.image_alpha = 0;
  6. }
I thought of maybe adding another timer, but I wasn't sure whether it will work so I'm just going to ask how to do it in the simplest way that you know. Any ideas?
 

flerpyderp

Member
A timer will work. While hit_ is true, a timer counts down and when it reaches zero, image_alpha becomes 0 if it's currently 1, and 1 if it's currently 0. The timer is then reset and the process repeats.

Step:
Code:
if (hit)
{
     if (flashTimer > 0)
     {
          flashTimer --;
     }
    else
    {
         if (image_alpha == 1) image_alpha = 0;
         else image_alpha = 1;
         flashTimer = flashTimerMax;
    }

    if (timer > 0)
    {
         timer --;
    }
    else
    {
         hit = false;
         timer = timerMax;
         flashTimer = flashTimerMax;
         image_alpha = 1;
    }
}
 
Last edited:
S

SashoTAI

Guest
A timer will work. While hit_ is true, a timer counts down and when it reaches zero, image_alpha becomes 0 if it's currently 1, and 1 if it's currently 0. The timer is then reset and the process repeats.

Step:
Code:
if (hit)
{
     if (flashTimer > 0)
     {
          flashTimer --;
     }
    else
    {
         if (image_alpha == 1) image_alpha = 0;
         else image_alpha = 1;
         flashTimer = flashTimerMax;
    }

    if (timer > 0)
    {
         timer --;
    }
    else
    {
         hit = false;
         timer = timerMax;
         flashTimer = flashTimerMax;
         image_alpha = 1;
    }
}
So what do I set flashTimer_ and flashTimerMax_? I suppose flashTimerMax_ would be the same as timerMax_ and that flashtimer_ would just be flashTimerMax_? I also know theat == equals a comparison between the two but couldn't you just put an equals sign (=) since I'm not sure why you would be comparing them.
 

flerpyderp

Member
I suppose flashTimerMax_ would be the same as timerMax_
flashTimerMax would be shorter than timerMax. It is the timer for how many steps pass before the image_alpha changes, so setting it to the same as timerMax would mean there'd be no change. If you want it to flash rapidly, try a value of around 5 or something.

Create:
Code:
timerMax = 30; //The number of invincibility frames
timer = timerMax;
flashTimerMax = 5; //The number of frames before the image_alpha changes
flashTimer = flashTimerMax
I also know theat == equals a comparison between the two but couldn't you just put an equals sign (=) since I'm not sure why you would be comparing them.
The comparison is between the value of image_alpha, and 1. If they are the same, then the image_alpha changes to 0. If they are not the same, then it changes to 1. You could just use a single "=" and it would work, but there are situations where it will not work as intended and it's good practice to use "==" when making a comparison.
 

TheouAegis

Member
image_alpha = !(timer_ & 1);

This is for faster flashing, which is basically just dithered 50% transparency used in most old games. This could be left to run every step. If timer_ is odd, the sprite is invisible (timer_ is even by default, so sprite is visible);

image_alpha ^= !(timer_ mod 4);

This is a slower flash and may require you to set image_alpha=1 manually when your timer reaches 0 unless you change maxtimer to something a little higher like 33. It toggles visibility every 4 steps of the timer.
 
S

SashoTAI

Guest
flashTimerMax would be shorter than timerMax. It is the timer for how many steps pass before the image_alpha changes, so setting it to the same as timerMax would mean there'd be no change. If you want it to flash rapidly, try a value of around 5 or something.

Create:
Code:
timerMax = 30; //The number of invincibility frames
timer = timerMax;
flashTimerMax = 5; //The number of frames before the image_alpha changes
flashTimer = flashTimerMax


The comparison is between the value of image_alpha, and 1. If they are the same, then the image_alpha changes to 0. If they are not the same, then it changes to 1. You could just use a single "=" and it would work, but there are situations where it will not work as intended and it's good practice to use "==" when making a comparison.
Ok thank you :)
 
Top