jup
July 19, 2024, 11:54am
1
Creating knockback for my character when they get hit by an enemy although it seems to always register enemy position as Vector2(0,0).
Knockback direction is a Vector2 that’s defined by:
if (character.position.x - enemy_position.x > 0):
Knockback currently only works in one direction since player position is correct but enemy position is always 0
(print() is just for debugging)
How would you properly call enemy position?
full script:
@export var enemy_position: Vector2
#-------------------------------------------
func _on_knockback_collision_body_entered(body):
if (body.is_in_group("enemy")):
enemy_position = body.global_position
func knockback(force: float, x_pos: float, up_force: float):
if (character.position.x - enemy_position.x > 0):
character.velocity = Vector2(-force * 2 * x_pos, -force * up_force)
print(enemy_position.x)
print(character.global_position.x)
else:
character.velocity = Vector2(force * 2 * x_pos, -force * up_force)
jup:
character.position.x
This should be character.global_position.x
jup
July 19, 2024, 12:11pm
3
fair, but character position already works. Enemy_position.x is always 0
Do you know how to get enemy position because that’s what seems to mess up the knockback
I think you are doing enemy position right. But if you haven’t collided that vector2 will initialize to zero before the collision.
What is this initial value?
Also when is knock back called? I think it should happen during the collision detection. But I don’t see it there.
jup
July 19, 2024, 12:35pm
5
I’m using a finite state machine so knockback is called whenever the player is hurt e.g whenever the player hits the enemy
Full script:
class_name hurtstate
extends Player_State
#-------------------------------------------
@export var fall_state : Player_State
@export var ground_state : Player_State
@export var hurt_animation : String = "Hurt"
@export var run_animation_node : String = "Run"
@export var fall_animation_node : String = "Fall"
@export var enemy_position: Vector2
@onready var timer: Timer = $Hurt_Timer
#-------------------------------------------
func _on_knockback_collision_body_entered(body):
if (body.is_in_group("enemy")):
enemy_position = body.global_position
func knockback(force: float, x_pos: float, up_force: float):
if (character.position.x - enemy_position.x > 0):
character.velocity = Vector2(-force * 2 * x_pos, -force * up_force)
print(enemy_position.x)
print(character.global_position.x)
else:
character.velocity = Vector2(force * 2 * x_pos, -force * up_force)
func on_enter():
timer.start()
playback.travel(hurt_animation)
character.startslowmo()
knockback(1,1500,300)
func _on_hurt_timer_timeout():
Game.hurt = false
character.endslowmo()
if (character.is_on_floor()):
character.velocity = Vector2(0, 0)
playback.travel(run_animation_node)
next_state = ground_state
elif(character.is_on_floor() == false):
character.velocity = Vector2(0, 0)
playback.travel(fall_animation_node)
next_state = fall_state
Where @export var fall_state : Player_State
is manually set
func on_enter():
is when the player enters the state (when they lose health)
I think the initial value is just (0,0), but it should be the enemy_position
I’m still relatively new to godot what do you by “colliding a vector2 so that it doesn’t initialize to zero before the collision.”?
Oh, I think there could be some issues with collision detection if you instantiated a collision body dynamically. My bet is _on_knockback_collision_body_entered is never being called in time. It may need to run a frame or two before the collision is called back.
I would probably pass the collision point or enemy position into the hurt state rather then collecting the information again.
Or you could query the collision manually. This is for area2d
For character body
KinematicCollision2D get_last_slide_collision ( )
For rigid body
Node2D get_colliding_bodies ( )
Btw godot AnimationtTree has a built in state machine.
jup
July 19, 2024, 3:50pm
7
I’m still pretty new to godot should i just write func get_overlapping_bodies() and insert my code?
Yes, at least give it a try. It should be one or two lines because it will give you an array and you need to get to the body in the data structure.
var bodies = $KnockBackArea.get_overlapping_bodies()
for body in bodies:
if (body.is_in_group("enemy")):
enemy_position = body.global_position
break
jup
July 19, 2024, 4:03pm
9
The result was the same as before. Knockback worked in 1 direction and enemy x position still returns 0
Did you do something like this in on_enter
var bodies = $KnockBackArea.get_overlapping_bodies()
for body in bodies:
if (body.is_in_group("enemy")):
enemy_position = body.global_position
break
breakpoint
And did you update the character.global_position.x ?
jup
July 19, 2024, 4:15pm
13
It still returned the same
I have this code now:
func get_overlapping_bodies(body):
if (body.is_in_group("enemy")):
enemy_position = body.global_position
#-------------------------------------------
func knockback(force: float, x_pos: float, up_force: float):
if (character.position.x - enemy_position.x > 0):
character.velocity = Vector2(-force * 2 * x_pos, -force * up_force)
print(enemy_position.x)
print(character.global_position.x)
else:
character.velocity = Vector2(force * 2 * x_pos, -force * up_force)
func on_enter():
var bodies = $"../../knockback_collision".get_overlapping_bodies()
for body in bodies:
if (body.is_in_group("enemy")):
enemy_position = body.global_position
timer.start()
playback.travel(hurt_animation)
character.startslowmo()
knockback(1,1500,300)
func get_overlapping_bodies(body):
needed to insert body into this function to remove red warnings
? What is this for ?
Anyway you should add a breakpoint
after the for loop and inspect the stack to see what’s in the array at that time.
Also this is still using local position use global_position on the character
jup
July 19, 2024, 5:12pm
16
After messing around with it i found that i had to delete some other code that was interfering with it
Thank you so much for the help
system
Closed
August 18, 2024, 5:12pm
17
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.