From c201a67bb804a5da5f837b65c0b3b5f5b9590a07 Mon Sep 17 00:00:00 2001 From: Nikolai Fedorov Date: Thu, 23 Apr 2026 18:10:52 +0300 Subject: [PATCH] add kick animation by enemy --- assets/Tutorial_shield.jpeg.import | 6 +-- scenes/Enemy.tscn | 86 ++++++++++++++++++++++++++++++ scripts/Enemy.gd | 54 ++++++++++++++----- 3 files changed, 130 insertions(+), 16 deletions(-) diff --git a/assets/Tutorial_shield.jpeg.import b/assets/Tutorial_shield.jpeg.import index 2721869..0434bc8 100644 --- a/assets/Tutorial_shield.jpeg.import +++ b/assets/Tutorial_shield.jpeg.import @@ -3,15 +3,15 @@ importer="texture" type="CompressedTexture2D" uid="uid://baeea1yfs0cnn" -path="res://.godot/imported/Tutorial_Shield.jpeg-6b96e6b9716aced42153397e827ce868.ctex" +path="res://.godot/imported/Tutorial_shield.jpeg-d9b563c9ca34dc1a19e82a0ec964c1b9.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://assets/Tutorial_Shield.jpeg" -dest_files=["res://.godot/imported/Tutorial_Shield.jpeg-6b96e6b9716aced42153397e827ce868.ctex"] +source_file="res://assets/Tutorial_shield.jpeg" +dest_files=["res://.godot/imported/Tutorial_shield.jpeg-d9b563c9ca34dc1a19e82a0ec964c1b9.ctex"] [params] diff --git a/scenes/Enemy.tscn b/scenes/Enemy.tscn index c7c3c33..7c49834 100644 --- a/scenes/Enemy.tscn +++ b/scenes/Enemy.tscn @@ -92,6 +92,91 @@ metadata/extras = { [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1i2q2"] albedo_texture = ExtResource("7_82o86") +[sub_resource type="Animation" id="Animation_ft8do"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("BodyMesh:blend_shapes/kick") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("BodyMesh1:blend_shapes/kick") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("BodyMesh2:blend_shapes/kick") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} + +[sub_resource type="Animation" id="Animation_5wwv6"] +resource_name = "kick" +length = 0.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("BodyMesh:blend_shapes/kick") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.15, 0.5), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [0.0, 1.0, 0.0] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("BodyMesh1:blend_shapes/kick") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.15, 0.5), +"transitions": PackedFloat32Array(1, 1, 1), +"update": 0, +"values": [0.0, 1.0, 0.0] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("BodyMesh2:blend_shapes/kick") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.0009999999, 0.15, 0.5), +"transitions": PackedFloat32Array(1, 1, 1, 1), +"update": 0, +"values": [0.0, 0.0, 1.0, 0.0] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_1vja8"] +_data = { +&"RESET": SubResource("Animation_ft8do"), +&"kick": SubResource("Animation_5wwv6") +} + [node name="Enemy" type="CharacterBody3D" unique_id=1639801124] script = ExtResource("1_enemy") @@ -121,3 +206,4 @@ blend_shapes/kick = 0.0 surface_material_override/0 = SubResource("StandardMaterial3D_1i2q2") [node name="AnimationPlayer" type="AnimationPlayer" parent="." unique_id=804352055] +libraries/ = SubResource("AnimationLibrary_1vja8") diff --git a/scripts/Enemy.gd b/scripts/Enemy.gd index 45f4cfb..64299c9 100644 --- a/scripts/Enemy.gd +++ b/scripts/Enemy.gd @@ -45,10 +45,13 @@ var merge_partner: Node = null var is_upgrading: bool = false @onready var mesh_node: MeshInstance3D = $BodyMesh -#@onready var mesh_node1: MeshInstance3D = $BodyMesh1 -#@onready var mesh_node2: MeshInstance3D = $BodyMesh2 +@onready var mesh_node1: MeshInstance3D = $BodyMesh1 +@onready var mesh_node2: MeshInstance3D = $BodyMesh2 +@onready var anim_player: AnimationPlayer = $AnimationPlayer + var mat: StandardMaterial3D var type_label: Label3D +var active_mesh: MeshInstance3D var COLOR_CHASE = Color(1.0, 0.28, 0.18) @@ -61,7 +64,9 @@ const AIR_FRICTION = 0.86 func _ready() -> void: process_mode = Node.PROCESS_MODE_PAUSABLE add_to_group("enemies") - mat = mesh_node.material_override.duplicate() as StandardMaterial3D + active_mesh = mesh_node + var orig := mesh_node.material_override + mat = (orig.duplicate() if orig != null else StandardMaterial3D.new()) as StandardMaterial3D mesh_node.material_override = mat #mesh_node1.set_visible(false) #mesh_node2.set_visible(false) @@ -123,19 +128,35 @@ func setup(type: String, wave: int) -> void: _apply_mesh(enemy_level) func _apply_mesh(level: int) -> void: - var idx := clampi(level, 1, 3) - var mesh_res := load("res://assets/gnome%d.obj" % idx) as Mesh - if mesh_res == null: + var idx := clampi(level, 1, 3) + var scene := load("res://assets/gnome%d.glb" % idx) as PackedScene + if scene == null: return - var new_mat := StandardMaterial3D.new() - var tex := load("res://assets/gnome%d.png" % idx) as Texture2D - if tex != null: - new_mat.albedo_texture = tex + var root := scene.instantiate() + var src: MeshInstance3D = null + for child in root.get_children(): + var mi := child as MeshInstance3D + if mi != null: + src = mi + break + if src == null: + root.queue_free() + return + mesh_node.mesh = src.mesh + var new_mat: StandardMaterial3D + if src.get_surface_override_material(0) != null: + new_mat = src.get_surface_override_material(0).duplicate() as StandardMaterial3D + else: + new_mat = StandardMaterial3D.new() + var tex := load("res://assets/gnome%d.png" % idx) as Texture2D + if tex != null: + new_mat.albedo_texture = tex new_mat.albedo_color = Color.WHITE - mesh_node.mesh = mesh_res mesh_node.material_override = new_mat + root.queue_free() mat = new_mat COLOR_CHASE = Color.WHITE + active_mesh = mesh_node func _physics_process(delta: float) -> void: match state: @@ -155,6 +176,7 @@ func _chase(delta: float) -> void: var dist := diff.length() if dist < 1.0 and contact_timer <= 0.0: contact_timer = CONTACT_CD + _play_kick_blend() if target.has_method("take_damage"): target.take_damage(damage_to_player) FX.hit_spark(target.global_position + Vector3(0, 0.5, 0), get_parent(), Color(0.95, 0.18, 0.08)) @@ -212,6 +234,7 @@ func _try_enemy_kick() -> void: nearest_dist = d.length() nearest_kickable = k if nearest_kickable != null: + _play_kick_blend() nearest_kickable.call("receive_kick", kick_dir, 35.0 + kick_tier * 8.0) FX.hit_spark(nearest_kickable.global_position + Vector3(0, 0.4, 0), get_parent(), Color(1.0, 0.72, 0.1)) kickable_kick_timer = KICKABLE_KICK_COOLDOWN @@ -233,6 +256,7 @@ func _try_enemy_kick() -> void: nearest_enemy_dist = d.length() nearest_enemy = en if nearest_enemy != null: + _play_kick_blend() nearest_enemy.call("receive_kick", kick_dir, 40.0 + kick_tier * 10.0) enemy_kick_timer = ENEMY_KICK_COOLDOWN return @@ -242,8 +266,7 @@ func _try_enemy_kick() -> void: if to_player.length() < ENEMY_KICK_RANGE: var player_toughness: int = target.get("toughness_tier") if target.get("toughness_tier") != null else 0 if player_toughness < kick_tier: - # light kick - # target.call("receive_kick", kick_dir, 12.0 + kick_tier * 10.0) + _play_kick_blend() target.call("receive_kick", kick_dir, 35.0 + kick_tier * 8.0) FX.hit_spark(target.global_position + Vector3(0, 0.5, 0), get_parent(), Color(0.95, 0.18, 0.08)) enemy_kick_timer = ENEMY_KICK_COOLDOWN @@ -381,6 +404,11 @@ func _take_hit(dmg: int) -> void: if health <= 0: _die() +func _play_kick_blend() -> void: + if anim_player != null and anim_player.has_animation("kick"): + anim_player.stop() + anim_player.play("kick") + func _wall_impact_effect() -> void: var tw := create_tween() tw.tween_property(mat, "albedo_color", Color.WHITE, 0.04)