Godot Version
4.5
Question
I am currently designing a shooting game and want to display current score player has achieved. I also want to achieve a visual effect where the score increment gradually with some animation effect.
here is how it is currently implemented:
func update_score(value: int):
score += value * score_factor
func _on_add_score_timer_timeout() -> void:
if int($score.get_parsed_text()) < score:
if !$AnimationPlayer.current_animation == "increase_score":
$AnimationPlayer.play("increase_score")
$score.text = "[center]" \
+ str(int($score.get_parsed_text()) + 1) + "[/center]"
# add rich text label back
else:
$AnimationPlayer.play("RESET")
# keep adding until final score is reached
while this does achive the visual effect, if the score is too big. Its going to take a long time for score to stop incrementing. Also having a signal emitted every 0.1 sec feels quite inefficient.
I made this approaching after tween fails to work so I must be missing something. Can anyone find some better approach?
Use a tween or manually increment displayed value towards actual value every frame in _process()
Hi!
I’ve tried tween before and instad of incrementing one by one it directly jumps to the new number when score increases. Updating score in process() has similar effects except it update so fast that even BBcode shows up in actual gameplay.
The increment speed would depend on tween duration. And in _process() it would depend on time slice. Since time slice is typically small, you need to update by a small value. Updating by 1 per frame will likely be too fast if your score values are typically not very big.
Here’s the _process() version example:
var score := 0.0
var score_displayed := 0.0
const SCORE_INCREMENT_SPEED := 25.0 # per second
func _process(dt: float) -> void:
score_displayed = move_toward(score_displayed, score, SCORE_INCREMENT_SPEED * dt)
$Label.text = "%d"%round(score_displayed)
func _input(e: InputEvent) -> void:
if e.is_action_pressed(&"ui_accept"):
score += 10.0
And here’s the tween version as well:
var score := 0.0
var score_displayed := 0.0
const SCORE_INCREMENT_SPEED := 25.0 # per second
var tween: Tween = null
func add_score(value: float) -> void:
score += value
var tween_duration = (score - score_displayed) / SCORE_INCREMENT_SPEED
if tween:
tween.kill()
tween = create_tween()
tween.set_parallel()
tween.tween_property(self, "score_displayed", score, tween_duration)
tween.tween_method(func(_unused): $Label.text = "%d"%round(score_displayed), 0, 0, tween_duration)
func _input(e: InputEvent) -> void:
if e.is_action_pressed(&"ui_accept"):
add_score(10.0)
1 Like
thanks! I think I see my problem when using tween, instead of doing integer format I cast digit into string using str() and didn’t use another variable to trace the currently updated score. which cause tween node to not increment one by one but update the new score as a string. I fixed it now and make SCORE_INCREMENT_SPEED a variable instead so scores increment faster when there is a lot of score to update.