Implement Hiro player hurt and defeat, make Hiro player and AI share animation data
This commit is contained in:
parent
b909cbd9d7
commit
2f2ebd5426
1573
Hiro/hiro_ai.tscn
1573
Hiro/hiro_ai.tscn
File diff suppressed because it is too large
Load diff
1825
Hiro/hiro_animation.tres
Normal file
1825
Hiro/hiro_animation.tres
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,8 @@ extends CharacterBody2D
|
|||
|
||||
@export var player_character: PlayableCharacter
|
||||
@export var health = 100
|
||||
@export var KNOCKBACK_POWER = 50
|
||||
@export var attack_power = 30
|
||||
@export var KNOCKBACK_POWER = 40
|
||||
@export var KNOCKBACK_REPOSITION_POWER = 75
|
||||
@export var KNOCKBACK_RANDOMNESS = 50
|
||||
@export var MELEE_RADIUS = 75
|
||||
|
@ -17,10 +18,13 @@ var timer = 0
|
|||
var attacked_from = Vector2.ZERO
|
||||
var received_damage = 0
|
||||
var hit_counter = 0
|
||||
var attack_counter = 0
|
||||
var attack_counter_limit = 0
|
||||
|
||||
var wants_to_melee = false
|
||||
|
||||
signal _got_hurt(damage: int, attack_direction: Vector2)
|
||||
signal attack_did_hit(other: Area2D, power: int, attack_direction: Vector2)
|
||||
#signal defeated
|
||||
|
||||
func _ready():
|
||||
|
@ -50,6 +54,7 @@ func _on_player_attack_did_hit(other, attack_power: int, attack_direction: Vecto
|
|||
func _on_ai_got_hurt(attack_power: int, attack_direction: Vector2):
|
||||
attacked_from = attack_direction
|
||||
received_damage = attack_power
|
||||
$Attackbox/Collider.set_deferred("disabled", true)
|
||||
state_machine.send_event("been_hurt")
|
||||
|
||||
## Thinking state
|
||||
|
@ -69,7 +74,7 @@ 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
|
||||
# range attacks here
|
||||
else:
|
||||
state_machine.send_event("wants_tomelee")
|
||||
|
||||
|
@ -131,6 +136,8 @@ 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")):
|
||||
attack_counter = attack_counter + 1
|
||||
wants_to_melee = wants_to_melee and attack_counter < attack_counter_limit
|
||||
if wants_to_melee:
|
||||
var animation_rng = randf_range(0, 1)
|
||||
anim_tree.set("parameters/melee/blend_position", animation_rng)
|
||||
|
@ -185,6 +192,8 @@ func _on_meleebox_body_entered(body):
|
|||
state_machine.send_event("will_melee")
|
||||
|
||||
func _on_melee_state_entered():
|
||||
attack_counter = 0
|
||||
attack_counter_limit = randi_range(3, 5)
|
||||
anim_tree.set("parameters/conditions/melee", true)
|
||||
state_machine.set_expression_property("melee_stage", 0)
|
||||
|
||||
|
@ -197,3 +206,7 @@ func _on_melee_state_processing(_delta):
|
|||
|
||||
func _on_melee_state_exited():
|
||||
anim_tree.set("parameters/conditions/melee", false)
|
||||
|
||||
|
||||
func _on_attackbox_area_entered(area):
|
||||
attack_did_hit.emit(area, attack_power, anim_tree.get("parameters/melee/0/blend_position"))
|
||||
|
|
|
@ -1,23 +1,38 @@
|
|||
class_name PlayableCharacter
|
||||
extends CharacterBody2D
|
||||
|
||||
@export var health = 100
|
||||
@export var speed = 100
|
||||
@export var KNOCKBACK_POWER = 40
|
||||
@export var KNOCKBACK_RANDOMNESS = 50
|
||||
var last_dpad: Array[Vector2] = [Vector2.ZERO,Vector2.ZERO]
|
||||
const FACING_ANGLE_EPSILON = 15
|
||||
|
||||
var can_move = true
|
||||
|
||||
signal attack_did_hit(other: Area2D, power: int, attack_direction: Vector2)
|
||||
signal defeated
|
||||
|
||||
func _unhandled_input(event):
|
||||
if event.is_action_pressed("melee") and $AnimationTree.get("parameters/conditions/melee") == false:
|
||||
if event.is_action_pressed("melee") and can_move:
|
||||
var animation_rng = randf_range(0, 1)
|
||||
$AnimationTree.set("parameters/melee/blend_position", animation_rng)
|
||||
$AnimationTree.set("parameters/conditions/melee", true)
|
||||
can_move = false
|
||||
velocity = Vector2.ZERO
|
||||
|
||||
func _physics_process(_delta):
|
||||
get_input()
|
||||
move_and_slide()
|
||||
|
||||
func set_animation_direction(direction: Vector2):
|
||||
$AnimationTree.set("parameters/idle/blend_position", direction)
|
||||
$AnimationTree.set("parameters/walk/blend_position", direction)
|
||||
$AnimationTree.set("parameters/melee/0/blend_position", direction)
|
||||
$AnimationTree.set("parameters/melee/1/blend_position", direction)
|
||||
$AnimationTree.set("parameters/melee/2/blend_position", direction)
|
||||
$AnimationTree.set("parameters/hurt/blend_position", direction)
|
||||
|
||||
func xor(a:bool, b:bool):
|
||||
return a != b
|
||||
|
||||
|
@ -38,23 +53,18 @@ func get_input():
|
|||
if last_dpad[0] == Vector2.ZERO and input_direction != Vector2.ZERO:
|
||||
last_dpad[0] = input_direction
|
||||
|
||||
if $AnimationTree.get("parameters/conditions/melee") ==true:
|
||||
if not can_move:
|
||||
input_direction = Vector2.ZERO
|
||||
last_dpad[0] = Vector2.ZERO
|
||||
last_dpad[1] = Vector2.ZERO
|
||||
|
||||
|
||||
velocity = input_direction * speed
|
||||
last_dpad[1] = Vector2.ZERO
|
||||
else:
|
||||
velocity = input_direction * speed
|
||||
|
||||
if input_direction == Vector2.ZERO:
|
||||
$AnimationTree.set("parameters/conditions/is_moving", false)
|
||||
else:
|
||||
$AnimationTree.set("parameters/conditions/is_moving", true)
|
||||
$AnimationTree.set("parameters/idle/blend_position", last_dpad[0])
|
||||
$AnimationTree.set("parameters/walk/blend_position", last_dpad[0])
|
||||
$AnimationTree.set("parameters/melee/0/blend_position", last_dpad[0])
|
||||
$AnimationTree.set("parameters/melee/1/blend_position", last_dpad[0])
|
||||
$AnimationTree.set("parameters/melee/2/blend_position", last_dpad[0])
|
||||
set_animation_direction(last_dpad[0])
|
||||
|
||||
|
||||
func _on_attackbox_area_entered(area: Area2D):
|
||||
|
@ -64,3 +74,33 @@ func _on_attackbox_area_entered(area: Area2D):
|
|||
|
||||
func _on_hiro_dummy_defeated():
|
||||
print("Yaaaaay!!")
|
||||
|
||||
|
||||
func _on_enemy_attack_did_hit(other, power, attack_direction):
|
||||
if other.get_parent().get_instance_id() == get_instance_id() :
|
||||
$Attackbox/Collider.set_deferred("disabled", true)
|
||||
health = health - power
|
||||
can_move = false
|
||||
if health <= 0:
|
||||
print("Nooooooooooooo!!")
|
||||
defeated.emit()
|
||||
velocity = Vector2.ZERO
|
||||
else:
|
||||
var facing_direction = attack_direction * -1.0
|
||||
set_animation_direction(facing_direction)
|
||||
var knockback_variance = Vector2.ZERO
|
||||
if attack_direction.x != 0:
|
||||
knockback_variance.y = randf_range(-1, 1) * KNOCKBACK_RANDOMNESS
|
||||
elif attack_direction.y != 0:
|
||||
knockback_variance.x = randf_range(-1, 1) * KNOCKBACK_RANDOMNESS
|
||||
velocity = KNOCKBACK_POWER * attack_direction + knockback_variance
|
||||
|
||||
var playback: AnimationNodeStateMachinePlayback = $AnimationTree.get("parameters/playback")
|
||||
playback.travel("hurt")
|
||||
$AnimationTree.set("parameters/conditions/melee", false)
|
||||
|
||||
func _on_animation_tree_animation_finished(anim_name):
|
||||
if anim_name.contains("hurt") or anim_name.contains("kick") or anim_name.contains("punch"):
|
||||
can_move = true
|
||||
if anim_name.contains("kick") or anim_name.contains("punch"):
|
||||
$Attackbox/Collider.set_deferred("disabled", true)
|
||||
|
|
|
@ -44,5 +44,7 @@ initial_node_to_watch = NodePath("../HiroAI")
|
|||
[node name="HiroAI" parent="." node_paths=PackedStringArray("player_character") instance=ExtResource("5_r7nw4")]
|
||||
position = Vector2(135, 215)
|
||||
player_character = NodePath("../HiroPlayer")
|
||||
attack_power = 5
|
||||
|
||||
[connection signal="attack_did_hit" from="HiroPlayer" to="HiroAI" method="_on_player_attack_did_hit"]
|
||||
[connection signal="attack_did_hit" from="HiroAI" to="HiroPlayer" method="_on_enemy_attack_did_hit"]
|
||||
|
|
Loading…
Reference in a new issue