How to make combat text animations like in WoW

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

Any ideas how to make numbers that appears upon enemy and disappear when it takes damage
Here is an example what i want to make https://www.youtube.com/watch?v=ta7lyqqPRXY

:bust_in_silhouette: Reply From: jgodfrey

There are lots of ways you could do this. Here’s an outline for one…

  • Add a Label or RichTextLabel as a child of your enemy
  • Set the visibility to False
  • Using either an AnimationPlayer or Tween, adjust all of the label properties you want over time (visibility, scale, rotation, position, …)
  • When the enemy takes damage…
  • Set the text / bbcode_text property of the Label / RichTextLabel to the value you want to display
  • Start the AnimationPlayer / Tween to animate the various properties as needed.

Good suggestions. Also, avoid animating the font size (use the scale instead as suggested by Jgodfrey). From experience, every time you change the font size it will save the resource changes to the disk and potentially lag your game.

godot_dev_ | 2022-08-19 15:41

so here what i made what i think you told me to do
here is a video with short example of what i made:
https://www.youtube.com/shorts/v0RfmWZ3jhQ
There is two functions one for displaying damage when i click on enemy another for passive damage, but as you can see text appears only once per click. How to make new instances of text per click and remove them after animation is finished?
Here is a code of how i calling animation

func playClickdmg(dmg):
	$Area2D/AnimationPlayer.play("RESET")
	$Area2D/AnimationPlayer.play("text floating ")
	$Area2D/AnimationPlayer/DamageLabel.text = "your dmg = " + str (dmg)

func playPassdmg(dmg):
	$Area2D/PasiveDamageAnimation.play("RESET")
	$Area2D/PasiveDamageAnimation.play("damage floating")
	$Area2D/PasiveDamageAnimation/PassiveDamageLabel.text = "pas damage =" + str (dmg)

hrp | 2022-08-20 16:12

I’d probably set up a dedicated scene explicitly for showing this animated damage value and then just instantiate it, position it, and start it wherever it’s needed. Further, I’d just have the scene destroy itself when the animation finishes.

For example, your scene could be setup like this (Damage.tscn)

Node2D
   Label
   AnimationPlayer

And, the Node2D could have the following script:

extends Node2D

func show_damage(damage_val):
	$Label.text = "Damage = %s" % damage_val
	$AnimationPlayer.play("damage")
	yield($AnimationPlayer, "animation_finished")
	queue_free()

Note, that yield() followed by queue_free() will cause the scene to destroy itself when the damage animation finishes playing.

Then, just instantiate the damage scene, position it as needed, and call the show_damage(). For example, this places a new instance at each mouse-click position and passes in a random damage value.

extends Node2D
var damage_scene = preload("res://Damage.tscn")

func _input(event):
	if event.is_action_pressed("click"):
		var pos = get_global_mouse_position()
		var d = damage_scene.instance()
		get_parent().add_child(d)
		d.position = pos
		d.show_damage(randi()%100+1)

Then, just season the underlying animation to taste. You could animate visibility, scale, rotation, position, color, … Whatever you need.

jgodfrey | 2022-08-20 22:29

Thank you very much, you helped a lot

hrp | 2022-08-21 17:34

:bust_in_silhouette: Reply From: RuKeN

Since Godot 3.5, you have the node Label3D which let’s you place text in a 3D world: