how to make the hp bar visible only when get hits

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

i have this enemy code and i am trying to create a hp bar that is visible only when get hits and i have no idea how
here is the enemy code :

extends KinematicBody2D

var velocity = Vector2(50,0)
var gravity = 15
var turned_side
var health = 100

func _ready():
	$AnimatedSprite.play("move")
	$CollisionShape2D.position.y == 0  
	$hpbar.value = health

func _physics_process(_delta):
	velocity.y += gravity
	
	move_and_slide(velocity,Vector2.UP)


func change_state():
	velocity.x *= -1
	scale.x *= -1
	
	if velocity.x < 0:
		turned_side = true
	elif velocity.x > 0:
		turned_side = false


func _on_detect_player_body_entered(body):
	if body.is_in_group("player"):
		$AnimatedSprite.play("attack")
		velocity = Vector2(0,0)


func _on_detect_player_body_exited(body):
	if body.is_in_group("player"):
		$AnimatedSprite.play("move")
		if turned_side == true:
			velocity.x = -50
		elif turned_side == false:
			velocity.x = 50


func _on_attack_player_body_entered(body):
	if body.is_in_group("player"):
		body.attack_detected(20)


func _on_player_is_back_body_entered(body):
	if body.is_in_group("player"):
		change_state()


func attacked(damage):
	health -= damage
	$hpbar.value = health
	if health == 0:
		$AnimatedSprite.play("die")
		$Timer.wait_time = 2
		$Timer.start()


func _on_Timer_timeout():
	queue_free()

Edited to fix code indentation.

Zylann | 2023-07-06 12:38

:bust_in_silhouette: Reply From: Zylann

How long do you want the HP bar to remain visible after the enemy got hit? And how do you want it to disappear?

The first thing you can do is to hide the HP bar by default.
Then in func attacked, make it visible again with $hpbar.show().

But then you need to hide it later.

A code-only solution would be to add a variable to the script

var hp_bar_remaining_time = 0.0

And a constant to store how long do you want the HP bar to remain visible after being hit:

const HP_BAR_REMAIN_TIME = 5.0

You can set that variable when the enemy takes damage:

func attacked(damage):
    health -= damage
    $hpbar.show()
    # Reset timer for keeping the bar shown
    hp_bar_remaining_time = HP_BAR_REMAIN_TIME
    # ...

And then, add some code into _process(delta) which will run every frame:

func _process(delta):
    if hp_bar_remaining_time > 0.0:
        hp_bar_remaining_time -= delta
        if hp_bar_remaining_time <= 0.0:
            # No time left, hide the HP bar
            $hpbar.hide()

Now if you want the bar to hide with some fading, you could also do this in _process:

var bar_color = $hpbar.modulate
var fade_time = 1.0 # Could be a const too
bar_color.a = clamp(hp_bar_remaining_time / fade_time, 0.0, 1.0)
$hpbar.modulate = bar_color

Alternatively to code, you could use another Timer node, which would hide the bar when it times out, and gets restarted every time the enemy takes damage. The bar could also be faded using an AnimationPlayer or a Tween, but you have to make sure to reset such animation if the enemy takes damage while it already started fading.

:bust_in_silhouette: Reply From: Vadalken

Change the $hpbar node to not be visible in the enemy scene. This can be done by turning off the “visible” property for the $hpbar in the enemy scene. It is in the inspector under “Visibility”.

Then you just need to make it visible when the enemy takes damage. Just add the line $hpbar.show() in your attacked(damage) function:

func attacked(damage):
    health -= damage
    $hpbar.value = health
    $hpbar.show() #<---new line
    if health == 0:
        $AnimatedSprite.play("die")
        $Timer.wait_time = 2
        $Timer.start()

If you only want the $hpbar to be visible for a brief time after taking damage you can add a Timer node to the enemy and add this to the enemy script:

func attacked(damage):
    health -= damage
    $hpbar.value = health
    $hpbar.show() #<---new line
    $Timer.start() #<---new line
    if health == 0:
        $AnimatedSprite.play("die")
        $Timer.wait_time = 2
        $Timer.start()

func _on_timer_timeout(): #<---new function
    $hpbar.hide()