<Im trying to make health UI using Panel and sprite animation. If player health is 0-2 make health_bar01 sprite frame 0-2, and if health is 3-4 make health_bar02 sprite frame 3-4, and so on. I would appreciate if you could help me solve an error.
extends CanvasLayer
@onready var player_health_bar01 := $HBoxContainer/crystal_heart1/Sprite2D as Panel
@onready var player_health_bar02 := $HBoxContainer/crystal_heart2/Sprite2D as Panel
@onready var player_health_bar03 := $HBoxContainer/crystal_heart3/Sprite2D as Panel
@onready var player_health_bar04 := $HBoxContainer/crystal_heart4/Sprite2D as Panel
@onready var player_health_bar05 := $HBoxContainer/crystal_heart5/Sprite2D as Panel
func update_player_health_bar(points: int):
if points >= 0 and points <= 2: #0-2
player_health_bar01.frame = int(clampf(points, 0, 2))
if points >= 3 and points <= 4: #3-4
player_health_bar02.frame = int(clampf(points, 0, 2))
if points >= 5 and points <= 6: #5-6
player_health_bar03.frame = int(clampf(points, 0, 2))
if points >= 7 and points <= 8: #7-8
player_health_bar04.frame = int(clampf(points, 0, 2))
if points >= 9 and points <= 10: #9-10
player_health_bar05.frame = int(clampf(points, 0, 2))
i think the problem is that you set your player_health_bar0X “as Panel” eventhough they are sprites (im assuming from their name). Remove the as Panel and try again. Another possible problem is that since the variables are onready, they might not have been initialized when you first call the function
Thank you I changed it to as Sprite2D and an error solved. but sprite frame is not working as i expected. I have 5 sprites representing heart and each has 3 frames (0-2, 0 is empty, 1 is half, and 2 is full) I want to make each sprite’s frame to 2 if the points is 10. if the points is 9, make frame of sprite of 01 to 04 to 2 and 05 frame to 1. if the point is 8, 01-04 frame should be 2 and 05 frame to 0. and so on.
To achieve this you would want to set every sprite.frame (1-5) for all if statements, so everything is updated accordingly.
Extra tip:
Since you are trying to do a healthbar, you can use a texturerect and set the texture to a full heart. Then you set the stretchmode to “Tile” and now you can adjust the length of the texture rect to represent the current health you have availabe. In code it would look something like this:
const HEART_SIZE: int = 10 # Size of your heart in pixels
func changeHealth(health: int):
$TextureRect.size.x = health * (HEART_SIZE / 2)
And if you have a background for your hearts you can instead use the TextureProgressBar. I can tell how to set it up if you want
I would like to stick with a single sprite for single heart, since I want to animate them to move like sine wave (like vital sign). But I just realized that I cannot move position of panel cuz its a child of HBoxContainer.
func animateHealthBar() -> void:
for sprite in sprites: # sprites should be a list of your sprites
animateSprite(sprite)
await get_tree().create_timer(0.1).timeout
If I set the timer to 0.1, first three sprites move same time. Do you have any idea what is the cause of this. and is it possible to make the delay longer after the tween for last sprite is executed?
When do you want to call this function? you could consider using an animationPlayer with a function-track, that calls animateSprite() on the different frames. This might be easier if you want it to play continously and you can also change the play-speed of the animationplayer
I cannot find argument Object/sprite2D, or should it be string and name the sprite node name?
I tried with string with value name but didnt work. what am i doing wrong?
You can change the function to take an integer as an argument and in your script you can then reference a list with the sprites with this integer OR you set the argument type to NodePath then you should be able to put sprite-paths into it