Finish Hiro AI state machine
This commit is contained in:
parent
ebef60e8ee
commit
3016e63b23
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=76 format=3 uid="uid://dd2km6qhpdicx"]
|
||||
[gd_scene load_steps=80 format=3 uid="uid://dd2km6qhpdicx"]
|
||||
|
||||
[ext_resource type="Script" path="res://Scripts/hiro_ai.gd" id="1_inmen"]
|
||||
[ext_resource type="Texture2D" uid="uid://cm7tgomrcvq30" path="res://Hiro/Hiro Walk Sprite Cycle Line Up.png" id="2_ctdbh"]
|
||||
|
@ -7,6 +7,7 @@
|
|||
[ext_resource type="Script" path="res://addons/godot_state_charts/state_chart.gd" id="6_i4c04"]
|
||||
[ext_resource type="Script" path="res://addons/godot_state_charts/compound_state.gd" id="7_j4kqa"]
|
||||
[ext_resource type="Script" path="res://addons/godot_state_charts/atomic_state.gd" id="8_pqyhf"]
|
||||
[ext_resource type="Script" path="res://addons/godot_state_charts/expression_guard.gd" id="9_ak1rc"]
|
||||
[ext_resource type="Script" path="res://addons/godot_state_charts/transition.gd" id="9_la16b"]
|
||||
|
||||
[sub_resource type="Animation" id="Animation_04piu"]
|
||||
|
@ -519,7 +520,6 @@ tracks/3/keys = {
|
|||
[sub_resource type="Animation" id="Animation_ji461"]
|
||||
resource_name = "kick_east"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -609,7 +609,6 @@ tracks/6/keys = {
|
|||
[sub_resource type="Animation" id="Animation_cuaji"]
|
||||
resource_name = "kick_north"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -675,7 +674,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_hqga6"]
|
||||
resource_name = "kick_south"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -741,7 +739,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_s8xim"]
|
||||
resource_name = "kick_west"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -807,7 +804,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_o0diw"]
|
||||
resource_name = "punch_east_left"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -873,7 +869,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_ar6r3"]
|
||||
resource_name = "punch_east_rigth"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -939,7 +934,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_1e0v6"]
|
||||
resource_name = "punch_north_left"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -1005,7 +999,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_bwm5c"]
|
||||
resource_name = "punch_north_rigth"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -1071,7 +1064,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_qmuik"]
|
||||
resource_name = "punch_south_left"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -1137,7 +1129,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_bw220"]
|
||||
resource_name = "punch_south_rigth"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -1203,7 +1194,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_wjl2t"]
|
||||
resource_name = "punch_west_left"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -1269,7 +1259,6 @@ tracks/4/keys = {
|
|||
[sub_resource type="Animation" id="Animation_e4rxs"]
|
||||
resource_name = "punch_west_rigth"
|
||||
length = 0.266673
|
||||
loop_mode = 1
|
||||
step = 0.0666667
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
|
@ -1740,8 +1729,8 @@ advance_mode = 2
|
|||
advance_condition = &"melee"
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_l17k0"]
|
||||
switch_mode = 2
|
||||
advance_mode = 2
|
||||
advance_expression = "get(\"parameters/conditions/melee\") == false"
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_ln3pc"]
|
||||
switch_mode = 2
|
||||
|
@ -1759,7 +1748,7 @@ states/melee/position = Vector2(329, 224)
|
|||
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")]
|
||||
graph_offset = Vector2(-222, -37)
|
||||
graph_offset = Vector2(-228, 51)
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_vm050"]
|
||||
radius = 8.0
|
||||
|
@ -1770,6 +1759,18 @@ size = Vector2(13, 8)
|
|||
|
||||
[sub_resource type="CircleShape2D" id="CircleShape2D_md645"]
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_hxosv"]
|
||||
radius = 12.0
|
||||
height = 44.0
|
||||
|
||||
[sub_resource type="Resource" id="Resource_ri8lv"]
|
||||
script = ExtResource("9_ak1rc")
|
||||
expression = "melee_stage == 0"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_gtfv8"]
|
||||
script = ExtResource("9_ak1rc")
|
||||
expression = "melee_stage == 1"
|
||||
|
||||
[node name="HiroAI" type="CharacterBody2D"]
|
||||
y_sort_enabled = true
|
||||
collision_layer = 5
|
||||
|
@ -1830,6 +1831,14 @@ shape = SubResource("CircleShape2D_md645")
|
|||
disabled = true
|
||||
debug_color = Color(0.745098, 0.462745, 0, 0.419608)
|
||||
|
||||
[node name="Meleebox" type="Area2D" parent="."]
|
||||
collision_layer = 4
|
||||
|
||||
[node name="DetectionArea" type="CollisionShape2D" parent="Meleebox"]
|
||||
position = Vector2(0, -13)
|
||||
shape = SubResource("CapsuleShape2D_hxosv")
|
||||
debug_color = Color(0.784314, 0.423529, 0.27451, 0.419608)
|
||||
|
||||
[node name="StateMachine" type="Node" parent="."]
|
||||
script = ExtResource("6_i4c04")
|
||||
|
||||
|
@ -1846,15 +1855,83 @@ to = NodePath("../../Hurt")
|
|||
event = &"been_hurt"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="ToMelee" type="Node" parent="StateMachine/Root/Think"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Melee")
|
||||
event = &"will_melee"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="ToApproach" type="Node" parent="StateMachine/Root/Think"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Approach")
|
||||
event = &"wants_tomelee"
|
||||
guard = SubResource("Resource_ri8lv")
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="ToChase" type="Node" parent="StateMachine/Root/Think"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Chase")
|
||||
event = &"wants_tomelee"
|
||||
guard = SubResource("Resource_gtfv8")
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="Approach" type="Node" parent="StateMachine/Root"]
|
||||
script = ExtResource("8_pqyhf")
|
||||
|
||||
[node name="ToHurt" type="Node" parent="StateMachine/Root/Approach"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Hurt")
|
||||
event = &"been_hurt"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="ToMelee" type="Node" parent="StateMachine/Root/Approach"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Melee")
|
||||
event = &"will_melee"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="ToThink" type="Node" parent="StateMachine/Root/Approach"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Think")
|
||||
event = &"approach_complete"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="Chase" type="Node" parent="StateMachine/Root"]
|
||||
script = ExtResource("8_pqyhf")
|
||||
|
||||
[node name="ToHurt" type="Node" parent="StateMachine/Root/Chase"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Hurt")
|
||||
event = &"been_hurt"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="ToMelee" type="Node" parent="StateMachine/Root/Chase"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Melee")
|
||||
event = &"will_melee"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="ToThink" type="Node" parent="StateMachine/Root/Chase"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Think")
|
||||
event = &"melee_aborted"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="Melee" type="Node" parent="StateMachine/Root"]
|
||||
script = ExtResource("8_pqyhf")
|
||||
|
||||
[node name="ToHurt" type="Node" parent="StateMachine/Root/Melee"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Hurt")
|
||||
event = &"been_hurt"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="ToThink" type="Node" parent="StateMachine/Root/Melee"]
|
||||
script = ExtResource("9_la16b")
|
||||
to = NodePath("../../Think")
|
||||
event = &"melee_complete"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="Hurt" type="Node" parent="StateMachine/Root"]
|
||||
script = ExtResource("8_pqyhf")
|
||||
|
||||
|
@ -1889,6 +1966,21 @@ delay_in_seconds = "0.0"
|
|||
script = ExtResource("8_pqyhf")
|
||||
|
||||
[connection signal="animation_finished" from="AnimationTree" to="." method="_on_animation_tree_animation_finished"]
|
||||
[connection signal="body_entered" from="Meleebox" to="." method="_on_meleebox_body_entered"]
|
||||
[connection signal="body_exited" from="Meleebox" to="." method="_on_meleebox_body_exited"]
|
||||
[connection signal="state_entered" from="StateMachine/Root/Think" to="." method="_on_think_state_entered"]
|
||||
[connection signal="state_processing" from="StateMachine/Root/Think" to="." method="_on_think_state_processing"]
|
||||
[connection signal="state_entered" from="StateMachine/Root/Approach" to="." method="_on_approach_state_entered"]
|
||||
[connection signal="state_exited" from="StateMachine/Root/Approach" to="." method="_on_approach_state_exited"]
|
||||
[connection signal="state_processing" from="StateMachine/Root/Approach" to="." method="_on_approach_state_processing"]
|
||||
[connection signal="taken" from="StateMachine/Root/Approach/ToThink" to="." method="_on_approach_to_think_taken"]
|
||||
[connection signal="state_entered" from="StateMachine/Root/Chase" to="." method="_on_chase_state_entered"]
|
||||
[connection signal="state_exited" from="StateMachine/Root/Chase" to="." method="_on_chase_state_exited"]
|
||||
[connection signal="state_processing" from="StateMachine/Root/Chase" to="." method="_on_chase_state_processing"]
|
||||
[connection signal="taken" from="StateMachine/Root/Chase/ToThink" to="." method="_on_chase_to_think_taken"]
|
||||
[connection signal="state_entered" from="StateMachine/Root/Melee" to="." method="_on_melee_state_entered"]
|
||||
[connection signal="state_exited" from="StateMachine/Root/Melee" to="." method="_on_melee_state_exited"]
|
||||
[connection signal="state_processing" from="StateMachine/Root/Melee" to="." method="_on_melee_state_processing"]
|
||||
[connection signal="state_entered" from="StateMachine/Root/Hurt" to="." method="_on_hurt_state_entered"]
|
||||
[connection signal="state_exited" from="StateMachine/Root/Hurt" to="." method="_on_hurt_state_exited"]
|
||||
[connection signal="state_entered" from="StateMachine/Root/HurtReposition" to="." method="_on_hurt_reposition_state_entered"]
|
||||
|
|
|
@ -2019,7 +2019,7 @@ states/melee/position = Vector2(329, 224)
|
|||
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")]
|
||||
graph_offset = Vector2(-222, -37)
|
||||
graph_offset = Vector2(-254, -71)
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_vm050"]
|
||||
radius = 8.0
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
class_name AICharacter
|
||||
extends CharacterBody2D
|
||||
|
||||
@export var player_character: PlayableCharacter
|
||||
@export var health = 100
|
||||
@export var KNOCKBACK_POWER = 50
|
||||
@export var KNOCKBACK_REPOSITION_POWER = 75
|
||||
@export var KNOCKBACK_RANDOMNESS = 50
|
||||
@export var MELEE_RADIUS = 75
|
||||
@onready var anim_tree: AnimationTree = $AnimationTree
|
||||
@onready var anim_playback: AnimationNodeStateMachinePlayback = anim_tree["parameters/playback"]
|
||||
@onready var state_machine: StateChart = $StateMachine
|
||||
|
||||
var timer = 0
|
||||
|
||||
# Getting hurt variables
|
||||
var attacked_from = Vector2.ZERO
|
||||
var received_damage = 0
|
||||
var hit_counter = 0
|
||||
|
||||
var wants_to_melee = false
|
||||
|
||||
signal _got_hurt(damage: int, attack_direction: Vector2)
|
||||
#signal defeated
|
||||
|
||||
func _ready():
|
||||
state_machine.set_expression_property("melee_stage", 0)
|
||||
|
||||
func set_animation_direction(facing_direction: Vector2):
|
||||
anim_tree.set("parameters/idle/blend_position", facing_direction)
|
||||
anim_tree.set("parameters/walk/blend_position", facing_direction)
|
||||
|
@ -22,6 +33,11 @@ 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)
|
||||
|
||||
func follow_player(speed: float):
|
||||
var approach_direction = position.direction_to(player_character.position)
|
||||
velocity = speed * approach_direction
|
||||
set_animation_direction(approach_direction)
|
||||
|
||||
func _physics_process(_delta):
|
||||
move_and_slide()
|
||||
|
@ -36,6 +52,27 @@ func _on_ai_got_hurt(attack_power: int, attack_direction: Vector2):
|
|||
received_damage = attack_power
|
||||
state_machine.send_event("been_hurt")
|
||||
|
||||
## Thinking state
|
||||
## Once some time passes out, do_thinking is called
|
||||
func _on_think_state_entered():
|
||||
timer = randf_range(3.0/60.0, 1.5)
|
||||
if timer <= 88.0/90.0:
|
||||
timer = timer * 0.75
|
||||
|
||||
func _on_think_state_processing(delta):
|
||||
timer -= delta
|
||||
if timer <= 0:
|
||||
do_thinking()
|
||||
|
||||
## This function actually determines what to do
|
||||
func do_thinking():
|
||||
var distance = position.distance_to(player_character.position)
|
||||
if distance > MELEE_RADIUS:
|
||||
state_machine.set_expression_property("melee_stage", 0)
|
||||
# melee attacks here
|
||||
else:
|
||||
state_machine.send_event("wants_tomelee")
|
||||
|
||||
func _on_hurt_state_entered():
|
||||
var facing_direction = attacked_from * -1
|
||||
health = health - received_damage
|
||||
|
@ -72,7 +109,8 @@ func _on_hurt_state_entered():
|
|||
elif attacked_from.y != 0:
|
||||
knockback_variance.x = randf_range(-1, 1) * KNOCKBACK_RANDOMNESS
|
||||
velocity = attacked_from * KNOCKBACK_POWER + knockback_variance
|
||||
print(velocity, knockback_variance)
|
||||
|
||||
state_machine.set_expression_property("melee_stage", 0)
|
||||
|
||||
func _on_hurt_state_exited():
|
||||
velocity = Vector2.ZERO
|
||||
|
@ -92,7 +130,68 @@ func _on_hurt_reposition_state_exited():
|
|||
func _on_animation_tree_animation_finished(anim_name):
|
||||
if anim_name.contains("hurt"):
|
||||
state_machine.send_event("hurt_complete")
|
||||
|
||||
elif (anim_name.contains("kick") or anim_name.contains("punch")):
|
||||
if wants_to_melee:
|
||||
anim_tree.set("parameters/conditions/melee", true)
|
||||
else:
|
||||
state_machine.send_event("melee_complete")
|
||||
|
||||
func _on_defeat_state_entered():
|
||||
queue_free()
|
||||
|
||||
## Aproaching
|
||||
func _on_approach_state_entered():
|
||||
follow_player(25)
|
||||
anim_tree.set("parameters/conditions/is_moving", true)
|
||||
timer = 1
|
||||
|
||||
func _on_approach_state_processing(delta):
|
||||
timer -= delta
|
||||
if timer < 0:
|
||||
state_machine.send_event("approach_complete")
|
||||
|
||||
|
||||
func _on_approach_state_exited():
|
||||
anim_tree.set("parameters/conditions/is_moving", false)
|
||||
velocity = Vector2.ZERO
|
||||
|
||||
|
||||
func _on_approach_to_think_taken():
|
||||
state_machine.set_expression_property("melee_stage", 1)
|
||||
|
||||
## Chasing
|
||||
func _on_chase_state_entered():
|
||||
anim_tree.set("parameters/conditions/is_moving", true)
|
||||
|
||||
func _on_chase_state_processing(_delta):
|
||||
follow_player(65)
|
||||
var distance = position.distance_to(player_character.position)
|
||||
if distance >= MELEE_RADIUS:
|
||||
state_machine.send_event("melee_aborted")
|
||||
|
||||
func _on_chase_state_exited():
|
||||
anim_tree.set("parameters/conditions/is_moving", false)
|
||||
velocity = Vector2.ZERO
|
||||
|
||||
func _on_chase_to_think_taken():
|
||||
state_machine.set_expression_property("melee_stage", 0)
|
||||
|
||||
## Melee
|
||||
func _on_meleebox_body_entered(body):
|
||||
if body == player_character:
|
||||
wants_to_melee = true
|
||||
state_machine.send_event("will_melee")
|
||||
|
||||
func _on_melee_state_entered():
|
||||
state_machine.set_expression_property("melee_stage", 0)
|
||||
anim_tree.set("parameters/conditions/melee", true)
|
||||
|
||||
func _on_meleebox_body_exited(body):
|
||||
if body == player_character:
|
||||
wants_to_melee = false
|
||||
|
||||
func _on_melee_state_processing(_delta):
|
||||
follow_player(0)
|
||||
|
||||
func _on_melee_state_exited():
|
||||
anim_tree.set("parameters/conditions/melee", false)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
class_name PlayableCharacter
|
||||
extends CharacterBody2D
|
||||
|
||||
@export var speed = 100
|
||||
|
|
|
@ -41,10 +41,8 @@ offset_bottom = 1099.0
|
|||
scale = Vector2(0.25, 0.25)
|
||||
initial_node_to_watch = NodePath("../HiroAI")
|
||||
|
||||
[node name="HiroAI" parent="." instance=ExtResource("5_r7nw4")]
|
||||
position = Vector2(135, 216)
|
||||
health = 500
|
||||
KNOCKBACK_POWER = 40
|
||||
KNOCKBACK_RANDOMNESS = 40
|
||||
[node name="HiroAI" parent="." node_paths=PackedStringArray("player_character") instance=ExtResource("5_r7nw4")]
|
||||
position = Vector2(135, 215)
|
||||
player_character = NodePath("../HiroPlayer")
|
||||
|
||||
[connection signal="attack_did_hit" from="HiroPlayer" to="HiroAI" method="_on_player_attack_did_hit"]
|
||||
|
|
Loading…
Reference in a new issue