Add more cutscene commands

This commit is contained in:
Mario Martínez 2024-10-07 18:22:39 +02:00
parent 142a24a895
commit 077d367a7f
10 changed files with 146 additions and 27 deletions

View file

@ -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")])

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -11,5 +11,5 @@ var _directions = [
Vector2.RIGHT
]
func get_direction() -> Vector2:
func get_direction(_manager: CutsceneManager) -> Vector2:
return _directions[facing_direction]

View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -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)

View file

@ -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"]