diff --git a/Cutscenes/prototype_start.tres b/Cutscenes/prototype_start.tres index 90e8860..1428d55 100644 --- a/Cutscenes/prototype_start.tres +++ b/Cutscenes/prototype_start.tres @@ -1,18 +1,29 @@ -[gd_resource type="Resource" script_class="Cutscene" load_steps=9 format=3 uid="uid://bj3rm1r1ouq0r"] +[gd_resource type="Resource" script_class="Cutscene" load_steps=13 format=3 uid="uid://bj3rm1r1ouq0r"] [ext_resource type="Script" path="res://Scripts/Cutscenes/cutscene.gd" id="1_ejncn"] +[ext_resource type="Script" path="res://Scripts/Cutscenes/Commands/wait.gd" id="1_mrqg0"] [ext_resource type="Script" path="res://Scripts/Cutscenes/Commands/show_dialogue.gd" id="1_r5tuj"] [ext_resource type="Script" path="res://Scripts/Cutscenes/Commands/turn_character.gd" id="2_eqfp1"] +[ext_resource type="Script" path="res://Scripts/Cutscenes/Commands/move_character.gd" id="3_rxd5p"] +[ext_resource type="Script" path="res://Scripts/Cutscenes/Commands/lookat_character.gd" id="4_dcsx8"] -[sub_resource type="Resource" id="Resource_o72ak"] -script = ExtResource("2_eqfp1") -character = NodePath("../HiroPlayer") -facing_direction = 3 +[sub_resource type="Resource" id="Resource_h6w6u"] +script = ExtResource("1_mrqg0") +time = 1.0 -[sub_resource type="Resource" id="Resource_vdtv6"] -script = ExtResource("2_eqfp1") +[sub_resource type="Resource" id="Resource_22owj"] +script = ExtResource("3_rxd5p") +target_character = NodePath("../HiroAI") +target_type = "Node" +speed = 75.0 +animation_state = "cut_walk" +target_vector = Vector2(0, 0) +target_node = NodePath("../PositionMarkers/Marker1") + +[sub_resource type="Resource" id="Resource_rtvbh"] +script = ExtResource("4_dcsx8") character = NodePath("../HiroAI") -facing_direction = 0 +lookat_target = NodePath("../HiroPlayer") [sub_resource type="Resource" id="Resource_r2p8t"] script = ExtResource("1_r5tuj") @@ -23,7 +34,7 @@ textbox_direction = 1 [sub_resource type="Resource" id="Resource_fuu2y"] script = ExtResource("2_eqfp1") character = NodePath("../HiroPlayer") -facing_direction = 2 +facing_direction = 3 [sub_resource type="Resource" id="Resource_x3xc6"] script = ExtResource("1_r5tuj") @@ -34,4 +45,4 @@ textbox_direction = 0 [resource] resource_name = "prototype_start" script = ExtResource("1_ejncn") -commands = Array[Resource("res://Scripts/Cutscenes/Commands/base.gd")]([SubResource("Resource_o72ak"), SubResource("Resource_vdtv6"), SubResource("Resource_r2p8t"), SubResource("Resource_fuu2y"), SubResource("Resource_x3xc6")]) +commands = Array[Resource("res://Scripts/Cutscenes/Commands/base.gd")]([SubResource("Resource_h6w6u"), SubResource("Resource_22owj"), SubResource("Resource_rtvbh"), SubResource("Resource_r2p8t"), SubResource("Resource_fuu2y"), SubResource("Resource_x3xc6")]) diff --git a/Hiro/hiro_ai.tscn b/Hiro/hiro_ai.tscn index f08cec7..145cbac 100644 --- a/Hiro/hiro_ai.tscn +++ b/Hiro/hiro_ai.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=61 format=3 uid="uid://dd2km6qhpdicx"] +[gd_scene load_steps=64 format=3 uid="uid://dd2km6qhpdicx"] [ext_resource type="Script" path="res://Scripts/hiro_ai.gd" id="1_inmen"] [ext_resource type="Shader" uid="uid://bcnip762rd6yj" path="res://Shaders/character.tres" id="2_6u0oh"] @@ -14,6 +14,29 @@ shader = ExtResource("2_6u0oh") shader_parameter/FlashColor = Color(1, 0, 0, 0) +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_vk5j3"] +animation = &"walking_south" + +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_87pv0"] +animation = &"walking_west" + +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_4xdsu"] +animation = &"walking_east" + +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_tmboi"] +animation = &"walking_north" + +[sub_resource type="AnimationNodeBlendSpace2D" id="AnimationNodeBlendSpace2D_h2456"] +blend_point_0/node = SubResource("AnimationNodeAnimation_vk5j3") +blend_point_0/pos = Vector2(0, 1) +blend_point_1/node = SubResource("AnimationNodeAnimation_87pv0") +blend_point_1/pos = Vector2(-1, 0) +blend_point_2/node = SubResource("AnimationNodeAnimation_4xdsu") +blend_point_2/pos = Vector2(1, 0) +blend_point_3/node = SubResource("AnimationNodeAnimation_tmboi") +blend_point_3/pos = Vector2(0, -1) +blend_mode = 1 + [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_8ov0j"] animation = &"player_defeated" @@ -197,18 +220,12 @@ advance_mode = 2 switch_mode = 2 advance_mode = 2 -[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_86ydq"] -switch_mode = 2 -advance_mode = 2 - -[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_yav5y"] -switch_mode = 2 -advance_mode = 2 - [sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_b0avg"] allow_transition_to_self = true states/End/position = Vector2(1026, 108) states/Start/position = Vector2(197, 108) +states/cut_walk/node = SubResource("AnimationNodeBlendSpace2D_h2456") +states/cut_walk/position = Vector2(563, 400) states/defeated/node = SubResource("AnimationNodeAnimation_8ov0j") states/defeated/position = Vector2(734, 74) states/hurt/node = SubResource("AnimationNodeBlendSpace2D_h2vkc") @@ -222,9 +239,9 @@ states/naked/position = Vector2(895, 202) states/naked_start/node = SubResource("AnimationNodeAnimation_kgin3") states/naked_start/position = Vector2(734, 202) states/walk/node = SubResource("AnimationNodeBlendSpace2D_vunsg") -states/walk/position = Vector2(520, 108) -transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_akmuq"), "idle", "walk", SubResource("AnimationNodeStateMachineTransition_sn1tm"), "walk", "idle", SubResource("AnimationNodeStateMachineTransition_5i3fu"), "idle", "melee", SubResource("AnimationNodeStateMachineTransition_y8p74"), "melee", "idle", SubResource("AnimationNodeStateMachineTransition_l17k0"), "hurt", "idle", SubResource("AnimationNodeStateMachineTransition_ln3pc"), "naked_start", "naked", SubResource("AnimationNodeStateMachineTransition_l5ng5"), "defeated", "End", SubResource("AnimationNodeStateMachineTransition_86ydq"), "naked", "End", SubResource("AnimationNodeStateMachineTransition_yav5y")] -graph_offset = Vector2(273, 34) +states/walk/position = Vector2(519, 108) +transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_akmuq"), "idle", "walk", SubResource("AnimationNodeStateMachineTransition_sn1tm"), "walk", "idle", SubResource("AnimationNodeStateMachineTransition_5i3fu"), "idle", "melee", SubResource("AnimationNodeStateMachineTransition_y8p74"), "melee", "idle", SubResource("AnimationNodeStateMachineTransition_l17k0"), "hurt", "idle", SubResource("AnimationNodeStateMachineTransition_ln3pc"), "naked_start", "naked", SubResource("AnimationNodeStateMachineTransition_l5ng5")] +graph_offset = Vector2(79, 269) [sub_resource type="CapsuleShape2D" id="CapsuleShape2D_vm050"] radius = 9.0 @@ -270,6 +287,7 @@ libraries = { tree_root = SubResource("AnimationNodeStateMachine_b0avg") parameters/conditions/is_moving = false parameters/conditions/melee = false +parameters/cut_walk/blend_position = Vector2(0.116751, -1.05556) parameters/hurt/blend_position = Vector2(0.949916, -0.0132159) parameters/idle/blend_position = Vector2(-0.0243112, 0.73545) parameters/melee/blend_position = 0.0 diff --git a/Scripts/Cutscenes/Commands/lookat_character.gd b/Scripts/Cutscenes/Commands/lookat_character.gd new file mode 100644 index 0000000..e90c2c8 --- /dev/null +++ b/Scripts/Cutscenes/Commands/lookat_character.gd @@ -0,0 +1,10 @@ +class_name LookAtTargetCommand extends CutsceneCommand + +@export_node_path("CharacterBody2D") var character: NodePath +@export_node_path("Node2D") var lookat_target: NodePath + +func get_direction(manager: CutsceneManager) -> Vector2: + var target_character: CharacterBody2D = manager.get_node(character) + var target_position: Node2D = manager.get_node(lookat_target) + assert(target_character != target_position) + return target_character.global_position.direction_to(target_position.global_position) diff --git a/Scripts/Cutscenes/Commands/move_character.gd b/Scripts/Cutscenes/Commands/move_character.gd new file mode 100644 index 0000000..c3ce5c8 --- /dev/null +++ b/Scripts/Cutscenes/Commands/move_character.gd @@ -0,0 +1,27 @@ +@tool +extends CutsceneCommand +class_name MoveCharacterCommand + +@export_group("Setup") +@export_node_path("CharacterBody2D") var target_character: NodePath +@export_enum("Node", "Vector") var target_type = "Node": + set(value): + target_type = value + notify_property_list_changed() +@export var speed: float = 300 +## AnimationTreeFiniteStateMachine state node that will be transitioned to. +@export var animation_state: String = "" + +@export_group("Targets") +@export var target_vector = Vector2(0,0) +@export_node_path("Node2D") var target_node: NodePath + +func _validate_property(property: Dictionary): + if property.name == "target_node" and target_type == "Vector": + property.usage |= PROPERTY_USAGE_READ_ONLY + elif property.name == "target_node" and target_type == "Node": + property.usage &= ~PROPERTY_USAGE_READ_ONLY + if property.name == "target_vector" and target_type == "Vector": + property.usage &= ~PROPERTY_USAGE_READ_ONLY + elif property.name == "target_vector" and target_type == "Node": + property.usage |= PROPERTY_USAGE_READ_ONLY diff --git a/Scripts/Cutscenes/Commands/turn_character.gd b/Scripts/Cutscenes/Commands/turn_character.gd index e801233..5b32705 100644 --- a/Scripts/Cutscenes/Commands/turn_character.gd +++ b/Scripts/Cutscenes/Commands/turn_character.gd @@ -11,5 +11,5 @@ var _directions = [ Vector2.RIGHT ] -func get_direction() -> Vector2: +func get_direction(_manager: CutsceneManager) -> Vector2: return _directions[facing_direction] diff --git a/Scripts/Cutscenes/Commands/wait.gd b/Scripts/Cutscenes/Commands/wait.gd new file mode 100644 index 0000000..4fbe7a3 --- /dev/null +++ b/Scripts/Cutscenes/Commands/wait.gd @@ -0,0 +1,5 @@ +@tool +class_name WaitCommand extends CutsceneCommand + +## Time in seconds to wait before the next command +@export_range(1/60.0, 4096.0, 0.1) var time = 1.0 diff --git a/Scripts/Cutscenes/manager.gd b/Scripts/Cutscenes/manager.gd index 3629f11..dc76aa8 100644 --- a/Scripts/Cutscenes/manager.gd +++ b/Scripts/Cutscenes/manager.gd @@ -10,6 +10,13 @@ signal finished(cutscene_name: String) @onready var _step = -1 var _current_command: CutsceneCommand: get = get_current_command +var _inner_timer = 0.0 + +func _process(delta): + if _inner_timer > 0.0: + _inner_timer -= delta + if _inner_timer <= 0.0: + step() func get_current_command() -> CutsceneCommand: return _current_command @@ -31,3 +38,7 @@ func load_cutscene(new_cutscene: Cutscene) -> void: func _on_ui_dialogue_completed(): step() + +func _on_issued_command(command, _manager): + if command is WaitCommand: + _inner_timer = command.time diff --git a/Scripts/Levels/arena_level.gd b/Scripts/Levels/arena_level.gd index bb44b77..c77afe1 100644 --- a/Scripts/Levels/arena_level.gd +++ b/Scripts/Levels/arena_level.gd @@ -35,9 +35,10 @@ func _on_cutscene_finished(cutscene_name: String): func _on_cutscene_manager_issued_command(command: CutsceneCommand, manager: CutsceneManager): - if command is TurnCharacterCommand: + if command is TurnCharacterCommand or command is LookAtTargetCommand: var character = manager.get_node(command.character) # TODO: We need to set a common class for character nodes. + var face_direction = command.get_direction(manager) assert(character is CharacterBody2D and character.has_method("set_animation_direction")) - character.set_animation_direction(command.get_direction()) + character.set_animation_direction(face_direction) manager.step() diff --git a/Scripts/hiro_ai.gd b/Scripts/hiro_ai.gd index ac30ec7..29155a7 100644 --- a/Scripts/hiro_ai.gd +++ b/Scripts/hiro_ai.gd @@ -28,6 +28,11 @@ var attack_counter_limit = 0 var wants_to_melee = false +# Cutscene movement +var movement_scripted_by: CutsceneManager = null +var movement_scripted_target: Vector2 +var movement_scripted_speed = 0.0 + signal got_hurt(new_health: int) signal attack_did_hit(other: Area2D, power: int, attack_direction: Vector2) signal defeated @@ -42,14 +47,25 @@ func set_animation_direction(facing_direction: Vector2): anim_tree.set("parameters/melee/1/blend_position", facing_direction) anim_tree.set("parameters/melee/2/blend_position", facing_direction) anim_tree.set("parameters/hurt/blend_position", facing_direction) + anim_tree.set("parameters/walk_cutscene/blend_position", facing_direction) func follow_player(speed: float): - var approach_direction = position.direction_to(player_character.position) + var approach_direction = global_position.direction_to(player_character.global_position) velocity = speed * approach_direction set_animation_direction(approach_direction) func _physics_process(_delta): move_and_slide() + +func _process(_delta): + if movement_scripted_by != null: + var distance_to_target = movement_scripted_target.distance_to(global_position) + if distance_to_target <= movement_scripted_speed/100.0: + global_position = movement_scripted_target + velocity = Vector2.ZERO + movement_scripted_by.step() + movement_scripted_by = null + anim_playback.travel("idle") func _on_player_attack_did_hit(other, attack_power: int, attack_direction: Vector2): if other.get_parent().get_instance_id() == get_instance_id() : @@ -236,3 +252,17 @@ func _on_victory_state_entered(): func _on_player_been_defeated(): state_machine.send_event("has_won") + + +func _on_cutscene_issued_command(command: CutsceneCommand, manager: CutsceneManager): + if command is MoveCharacterCommand: + var target_character = manager.get_node(command.target_character) + if target_character != self: + return + movement_scripted_target = command.target_vector if command.target_type == "Vector" else manager.get_node(command.target_node).global_position + var approach_direction = global_position.direction_to(movement_scripted_target) + set_animation_direction(approach_direction) + velocity = command.speed * approach_direction + movement_scripted_by = manager + movement_scripted_speed = command.speed + anim_playback.travel(command.animation_state) diff --git a/world/world.tscn b/world/world.tscn index e3cefab..de74510 100644 --- a/world/world.tscn +++ b/world/world.tscn @@ -137,7 +137,7 @@ scale = Vector2(8.83789, 4.22585) polygon = PackedVector2Array(158.522, 76.9076, 161.916, 75.961, 172.213, 75.961, 175.834, 76.671, 177.757, 78.5641, 179.341, 82.8236, 180.134, 85.8999, 180.134, 93.9456, 180.134, 114.06, 179.341, 117.373, 177.871, 119.739, 174.929, 120.922, 169.497, 120.922, 169.497, 123.525, 164.745, 123.525, 164.632, 120.922, 159.201, 120.922, 156.372, 120.213, 154.901, 117.373, 154.109, 113.587, 154.109, 94.1822, 154.109, 86.1365, 152.186, 83.0602, 152.412, 80.9304, 146.181, 70.3743, 139.513, 85.4266, 135.779, 90.8692, 147.66, 124.945, 187.367, 125.038, 195.514, 91.4351, 192.232, 66.1148, 173.676, 53.3363, 157.382, 53.8096, 152.404, 63.2751, 153.317, 81.6403, 154.109, 85.8999, 154.901, 83.2969, 156.485, 78.5641) [node name="HiroAI" parent="." node_paths=PackedStringArray("player_character") instance=ExtResource("5_r7nw4")] -position = Vector2(-1, 25) +position = Vector2(-1, 67) player_character = NodePath("../HiroPlayer") health = 400 attack_power = 10 @@ -181,6 +181,10 @@ texture_filter = 1 position = Vector2(285, -102) texture = ExtResource("16_cgyrp") +[node name="PositionMarkers" type="Node2D" parent="."] + +[node name="Marker1" type="Marker2D" parent="PositionMarkers"] + [node name="CutsceneManager" type="Node" parent="."] script = ExtResource("19_5yvrq") cutscene = ExtResource("20_elypl") @@ -196,4 +200,6 @@ cutscene = ExtResource("20_elypl") [connection signal="finished" from="CutsceneManager" to="." method="_on_cutscene_finished"] [connection signal="issued_command" from="CutsceneManager" to="." method="_on_cutscene_manager_issued_command"] [connection signal="issued_command" from="CutsceneManager" to="TextboxUI" method="_on_cutscene_command_issued"] +[connection signal="issued_command" from="CutsceneManager" to="HiroAI" method="_on_cutscene_issued_command"] +[connection signal="issued_command" from="CutsceneManager" to="CutsceneManager" method="_on_issued_command"] [connection signal="started" from="CutsceneManager" to="." method="_on_cutscene_started"]