fuzzyworld

godot-shooter / commit

Added damage labels that pop up whenever ships are damaged, or when the player is healed by HP pick-ups.

2b4497bbd036684eb89b0e6cb2dc2dd779aa0005 · Pavel Safronov · 2023-11-27 15:31:45 -0800 · parents 13440f93cc16

Added damage labels that pop up whenever ships are damaged, or when the player is healed by HP pick-ups.
 actors/Enemy.gd         |   8 +++
 actors/Enemy.tscn       |   4 +-
 actors/Player.gd        |   9 +++
 actors/Player.tscn      |   4 +-
 effects/Damage.gd       |  24 ++++++++
 effects/Damage.tscn     | 146 ++++++++++++++++++++++++++++++++++++++++++++++++
 project.godot           |   6 ++
 themes/DamageTheme.tres |  14 +++++
 themes/HealTheme.tres   |  14 +++++
 9 files changed, 225 insertions(+), 4 deletions(-)

diff --git a/actors/Enemy.gd b/actors/Enemy.gd
index b48ad66..cb5137a 100644
--- a/actors/Enemy.gd
+++ b/actors/Enemy.gd
@@ -6,6 +6,7 @@ onready var damage_points = $DamagePoints
 const Utils = preload("res://utils/Utils.gd")
 const Explosion = preload("res://effects/Explosion.tscn")
 const Smoke = preload("res://effects/Smoke.tscn")
+const Damage = preload("res://effects/Damage.tscn")
 const Constants = preload("res://utils/Constants.gd")
 
 export var move_speed = Constants.SPEED * 1.05
@@ -88,6 +89,7 @@ func hurt(damage: int = 1):
 	if dead || is_invincible:
 		return
 	health -= damage
+	add_damage_label(damage)
 #	add_child(smoke)
 	_ensure_smoke_exists()
 	if health <= 0:
@@ -105,6 +107,12 @@ func kill():
 	z_index = -1
 	emit_signal("enemy_killed", global_position)
 
+func add_damage_label(damage_amount: int = 5) -> void:
+	var damage_label: Damage = Damage.instance()
+	damage_label.value = -damage_amount
+	damage_label.position = self.position
+	get_tree().root.add_child(damage_label)
+
 func teleport(dest: Vector2) -> void:
 	$Graphics/Alive/Trails.clear()
 	position = dest
diff --git a/actors/Enemy.tscn b/actors/Enemy.tscn
index c9d1778..f887843 100644
--- a/actors/Enemy.tscn
+++ b/actors/Enemy.tscn
@@ -116,8 +116,8 @@ gradient = SubResource( 4 )
 margin_left = -50.0
 margin_top = 45.0
 margin_right = 50.0
-margin_bottom = 55.0
-rect_min_size = Vector2( 100, 10 )
+margin_bottom = 50.0
+rect_min_size = Vector2( 100, 5 )
 custom_styles/fg = SubResource( 5 )
 custom_styles/bg = SubResource( 6 )
 value = 30.0
diff --git a/actors/Player.gd b/actors/Player.gd
index 6bfe9a4..99cf0cf 100644
--- a/actors/Player.gd
+++ b/actors/Player.gd
@@ -1,6 +1,7 @@
 extends KinematicBody2D
 class_name Player
 
+const Damage = preload("res://effects/Damage.tscn")
 const Weapons = preload("res://weapons/Weapons.gd")
 const Constants = preload("res://utils/Constants.gd")
 
@@ -136,6 +137,7 @@ func heal(amount: int = 1):
 	if dead:
 		return
 	health += amount
+	add_damage_label(-amount)
 	if health > max_health:
 		health = max_health
 
@@ -149,9 +151,16 @@ func hurt(damage_amount: int = 1):
 		return
 	else:
 		health -= damage_amount
+		add_damage_label(damage_amount)
 		if health <= 0:
 			kill()
 
+func add_damage_label(damage_amount: int = 5) -> void:
+	var damage_label: Damage = Damage.instance()
+	damage_label.value = -damage_amount
+	damage_label.position = self.position
+	get_tree().root.add_child(damage_label)
+
 func turn_towards(dest: Vector2, _delta: float):
 	var to_dir = (dest - global_position).normalized()
 	var curr_dir = velocity.normalized()
diff --git a/actors/Player.tscn b/actors/Player.tscn
index 82df0f3..a8bea0d 100644
--- a/actors/Player.tscn
+++ b/actors/Player.tscn
@@ -89,8 +89,8 @@ offset = Vector2( 0, -300 )
 margin_left = -50.0
 margin_top = 45.0
 margin_right = 50.0
-margin_bottom = 55.0
-rect_min_size = Vector2( 100, 10 )
+margin_bottom = 50.0
+rect_min_size = Vector2( 100, 5 )
 custom_styles/fg = SubResource( 13 )
 custom_styles/bg = SubResource( 14 )
 value = 30.0
diff --git a/effects/Damage.gd b/effects/Damage.gd
new file mode 100644
index 0000000..1dc6878
--- /dev/null
+++ b/effects/Damage.gd
@@ -0,0 +1,24 @@
+extends Node2D
+
+class_name Damage
+
+const HealTheme = preload("res://themes/HealTheme.tres")
+const DamageTheme = preload("res://themes/DamageTheme.tres")
+onready var animation_player = $AnimationPlayer
+onready var damage_label = $DamageLabel
+export var value: int = 5
+
+func _ready() -> void:
+	animation_player.queue("fade_in")
+	animation_player.queue("fade_out")
+
+func _process(delta: float) -> void:
+	var value_sign = "+"
+	if self.value < 0:
+		value_sign = "-"
+	var abs_value = abs(self.value)
+	damage_label.text = "%s%s" % [value_sign, abs_value]
+	if self.value >= 0:
+		damage_label.theme = HealTheme
+	else:
+		damage_label.theme = DamageTheme
diff --git a/effects/Damage.tscn b/effects/Damage.tscn
new file mode 100644
index 0000000..978f0b8
--- /dev/null
+++ b/effects/Damage.tscn
@@ -0,0 +1,146 @@
+[gd_scene load_steps=6 format=2]
+
+[ext_resource path="res://themes/DamageTheme.tres" type="Theme" id=1]
+[ext_resource path="res://effects/Damage.gd" type="Script" id=2]
+
+[sub_resource type="Animation" id=1]
+length = 0.001
+tracks/0/type = "value"
+tracks/0/path = NodePath(".:modulate")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/keys = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 0,
+"values": [ Color( 1, 1, 1, 0 ) ]
+}
+tracks/1/type = "value"
+tracks/1/path = NodePath(".:scale")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/keys = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 0,
+"values": [ Vector2( 0.1, 0.1 ) ]
+}
+tracks/2/type = "value"
+tracks/2/path = NodePath(".:position")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/keys = {
+"times": PoolRealArray( 0 ),
+"transitions": PoolRealArray( 1 ),
+"update": 0,
+"values": [ Vector2( 0, 100 ) ]
+}
+
+[sub_resource type="Animation" id=2]
+resource_name = "fade_in"
+length = 0.25
+tracks/0/type = "value"
+tracks/0/path = NodePath(".:modulate")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/keys = {
+"times": PoolRealArray( 0, 0.2 ),
+"transitions": PoolRealArray( 1, 1 ),
+"update": 0,
+"values": [ Color( 1, 1, 1, 0 ), Color( 1, 1, 1, 1 ) ]
+}
+tracks/1/type = "value"
+tracks/1/path = NodePath(".:scale")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/keys = {
+"times": PoolRealArray( 0, 0.2 ),
+"transitions": PoolRealArray( 1, 1 ),
+"update": 0,
+"values": [ Vector2( 0.1, 0.1 ), Vector2( 1, 1 ) ]
+}
+tracks/2/type = "value"
+tracks/2/path = NodePath(".:position")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/imported = false
+tracks/2/enabled = false
+tracks/2/keys = {
+"times": PoolRealArray( 0, 0.2 ),
+"transitions": PoolRealArray( 1, 1 ),
+"update": 0,
+"values": [ Vector2( 0, 100 ), Vector2( 0, 0 ) ]
+}
+
+[sub_resource type="Animation" id=3]
+resource_name = "fade_out"
+length = 2.0
+tracks/0/type = "value"
+tracks/0/path = NodePath(".:modulate")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/keys = {
+"times": PoolRealArray( 0, 2 ),
+"transitions": PoolRealArray( 1, 1 ),
+"update": 0,
+"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
+}
+tracks/1/type = "value"
+tracks/1/path = NodePath(".:scale")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/keys = {
+"times": PoolRealArray( 0, 2 ),
+"transitions": PoolRealArray( 1, 1 ),
+"update": 0,
+"values": [ Vector2( 1, 1 ), Vector2( 0.1, 0.1 ) ]
+}
+tracks/2/type = "method"
+tracks/2/path = NodePath(".")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/keys = {
+"times": PoolRealArray( 2 ),
+"transitions": PoolRealArray( 1 ),
+"values": [ {
+"args": [  ],
+"method": "queue_free"
+} ]
+}
+
+[node name="Damage" type="Node2D"]
+modulate = Color( 1, 1, 1, 0 )
+position = Vector2( 0, 100 )
+scale = Vector2( 0.1, 0.1 )
+script = ExtResource( 2 )
+
+[node name="DamageLabel" type="Label" parent="."]
+margin_left = -20.0
+margin_top = -19.0
+margin_right = 20.0
+margin_bottom = 18.0
+theme = ExtResource( 1 )
+text = "5"
+align = 1
+valign = 1
+
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
+anims/RESET = SubResource( 1 )
+anims/fade_in = SubResource( 2 )
+anims/fade_out = SubResource( 3 )
diff --git a/project.godot b/project.godot
index 28fe087..23b7065 100644
--- a/project.godot
+++ b/project.godot
@@ -19,6 +19,11 @@ _global_script_classes=[ {
 "language": "GDScript",
 "path": "res://items/ConstantItemGenerator.gd"
 }, {
+"base": "Node2D",
+"class": "Damage",
+"language": "GDScript",
+"path": "res://effects/Damage.gd"
+}, {
 "base": "KinematicBody2D",
 "class": "Enemy",
 "language": "GDScript",
@@ -62,6 +67,7 @@ _global_script_classes=[ {
 _global_script_class_icons={
 "Bullet": "",
 "ConstantItemGenerator": "",
+"Damage": "",
 "Enemy": "",
 "LevelItemGenerator": "",
 "Player": "",
diff --git a/themes/DamageTheme.tres b/themes/DamageTheme.tres
new file mode 100644
index 0000000..e2a85d5
--- /dev/null
+++ b/themes/DamageTheme.tres
@@ -0,0 +1,14 @@
+[gd_resource type="Theme" load_steps=3 format=2]
+
+[ext_resource path="res://assets/neuropolitical rg.otf" type="DynamicFontData" id=1]
+
+[sub_resource type="DynamicFont" id=1]
+size = 30
+outline_size = 3
+outline_color = Color( 1, 0, 0, 1 )
+use_mipmaps = true
+use_filter = true
+font_data = ExtResource( 1 )
+
+[resource]
+default_font = SubResource( 1 )
diff --git a/themes/HealTheme.tres b/themes/HealTheme.tres
new file mode 100644
index 0000000..9f6443a
--- /dev/null
+++ b/themes/HealTheme.tres
@@ -0,0 +1,14 @@
+[gd_resource type="Theme" load_steps=3 format=2]
+
+[ext_resource path="res://assets/neuropolitical rg.otf" type="DynamicFontData" id=1]
+
+[sub_resource type="DynamicFont" id=1]
+size = 30
+outline_size = 1
+outline_color = Color( 0.00392157, 0.686275, 0.0784314, 1 )
+use_mipmaps = true
+use_filter = true
+font_data = ExtResource( 1 )
+
+[resource]
+default_font = SubResource( 1 )