I have an issue with getting knockback from shooting as my player in my 2d platformer

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Im Acoustic

I’ve been looking through multiple tutorials and trying what they say you should do, but they either didn’t work or didn’t do what I wanted it to do.

I want my player to get pushed back in the opposite way of where I shoot.
The code I have now is made up of 2 separate attempts, but both with the same result. My player only gets pushed back in the y direction, but not in the x direction.
How do I fix this?

if Input.is_action_pressed("Fire") and is_on_floor() and can_fire:
	var knockback_strength = 500
	var knockback_sideways = 500
	var player_to_bullet_x = (get_global_mouse_position().x - get_global_position().x)
	var player_to_bullet_y = (get_global_mouse_position().y - get_global_position().y)
	var pixels = abs(player_to_bullet_x) + abs(player_to_bullet_y)
	var percentage_x = (radius / pixels * player_to_bullet_x) / radius
	var percentage_y = (radius / pixels * player_to_bullet_y) / radius
	var knockback_x = percentage_x * knockback_sideways
	var knockback_y = percentage_y * knockback_strength
	vel.x -= knockback_x
	vel.y -= knockback_y
	can_fire = false
	yield(get_tree().create_timer(fire_rate), "timeout")
	can_fire = true
elif Input.is_action_pressed("Fire") and can_fire:
	var knockback_strength = 80
	var knockback_sideways = 500
	var player_to_bullet = (get_global_mouse_position() - get_global_position()).normalized()
	var knockback_x = player_to_bullet.x * knockback_sideways
	var knockback_y = player_to_bullet.y * knockback_strength
	vel.x -= knockback_x
	vel.y -= knockback_y
	can_fire = false
	yield(get_tree().create_timer(fire_rate), "timeout")
	can_fire = true

This is more a comment on coding style. I would recommend avoid using yield in such a manner, it’ll get messy fast. If you ever decide to change your design and let the player fire or change other things the player can do, you will have difficulty with this because of that timer and yield. For example, what if you want to change the fire rate? Your code’s elegance breaks down since the yield will be waiting on an old version of the fire_rate.

godot_dev_ | 2022-08-11 18:52

Hi, thanks for your reply.

I’ve just started with godot and I have no clue what yield does. A tutorial told me to use this code, they didn’t tell me why or what it does, so I didn’t know it was bad or made things messy.

I am not so good at coding yet. So thanks, I will look up what yield does.

Im Acoustic | 2022-08-12 17:27

:bust_in_silhouette: Reply From: Inces

It surely is conflicting with your movement code.
Post your movement code.
I hope it is not so abundant in custom variables as this one :smiley:

This is my movement code:

func _physics_process(delta):

vel.x = 0

# Movement inputs
if Input.is_action_pressed("move_left"):
	vel.x -= speed
if Input.is_action_pressed("move_right"):
	vel.x += speed
# Define Velocity
vel = move_and_slide(vel, Vector2.UP)

# Gravity
vel.y += gravity * delta

I also have a way to flip my sprite horizontally. The sprite does flip when I shoot, so shooting must be changing my horizontal velocity.

    if vel.x < 0:
	sprite.flip_h = true
elif vel.x > 0:
	sprite.flip_h = false

Im Acoustic | 2022-08-12 17:22

According to this code, your players speed is set to 0 every time no input is pressed. So your knockback can only work, when an input or shoot button is held.

Gravity is a natural mechanism to impede your vertical velocity. You need to design similar thing for horizontal velocity. For example :

var friction = 0.99
func _physics_process(delta):
       vel.x = lerp(vel.x,0, friction * delta)

with this your horizontal velocity is calculated instead of arbitrary set, so it can be modified from other sources. It will be affected by your knockback code now. Additionally, your player will be slowly impeding its movement, as opposite to stopping immadietely. You can tweak strenght of this impedation by changing value of friction. Finally, You will want to design a code to detect if your player is on the ground. You will need it, to stop impedation when player is in the air.

Inces | 2022-08-14 19:38

Thank you!

Is it necessary to multiply friction by delta? Because when I do my player goes at supersonic speeds and changing speed doesn’t seem to have any effect.

Im Acoustic | 2022-08-14 20:39

multiplying any constant process by delta ensures, that it is going to take exactly the same amount of real time on every CPU, so it will become framerate independent. Just change constant value of friction so it is of optimum speed. I just went there with 0.99 but I have no idea what number it should be, You need to find out :slight_smile:

Inces | 2022-08-14 20:46