feat: added hurt state for player

main
Sara 2024-12-10 20:05:13 +01:00
parent 2054474c01
commit c7b9f97b70
10 changed files with 58 additions and 37 deletions

Binary file not shown.

View File

@ -1,4 +1,4 @@
[gd_resource type="AnimationNodeBlendTree" load_steps=46 format=3 uid="uid://c7rxfpfy7vt1b"] [gd_resource type="AnimationNodeBlendTree" load_steps=48 format=3 uid="uid://c7rxfpfy7vt1b"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ukhqm"] [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ukhqm"]
animation = &"Aim" animation = &"Aim"
@ -15,6 +15,9 @@ animation = &"Aim"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_8rbkq"] [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_8rbkq"]
animation = &"Aim_Fire" animation = &"Aim_Fire"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_lg206"]
animation = &"Hit_backward"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ugv1e"] [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ugv1e"]
animation = &"RESET" animation = &"RESET"
@ -225,6 +228,10 @@ switch_mode = 2
advance_mode = 2 advance_mode = 2
advance_expression = "is_walking && walk_speed > 0.0" advance_expression = "is_walking && walk_speed > 0.0"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_0ppx7"]
switch_mode = 2
advance_mode = 2
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_7smdg"] [sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_7smdg"]
"states/Aim Down [aim]/node" = SubResource("AnimationNodeAnimation_ukhqm") "states/Aim Down [aim]/node" = SubResource("AnimationNodeAnimation_ukhqm")
"states/Aim Down [aim]/position" = Vector2(831.525, 251.767) "states/Aim Down [aim]/position" = Vector2(831.525, 251.767)
@ -233,6 +240,8 @@ advance_expression = "is_walking && walk_speed > 0.0"
states/End/position = Vector2(195.182, 94.3447) states/End/position = Vector2(195.182, 94.3447)
"states/Fire [aim]/node" = SubResource("AnimationNodeAnimation_8rbkq") "states/Fire [aim]/node" = SubResource("AnimationNodeAnimation_8rbkq")
"states/Fire [aim]/position" = Vector2(919.525, 14.954) "states/Fire [aim]/position" = Vector2(919.525, 14.954)
states/Hit/node = SubResource("AnimationNodeAnimation_lg206")
states/Hit/position = Vector2(689.503, 14.954)
"states/RESET To Aim/node" = SubResource("AnimationNodeAnimation_ugv1e") "states/RESET To Aim/node" = SubResource("AnimationNodeAnimation_ugv1e")
"states/RESET To Aim/position" = Vector2(755.258, 94.3447) "states/RESET To Aim/position" = Vector2(755.258, 94.3447)
states/Run/node = SubResource("AnimationNodeBlendTree_hmklb") states/Run/node = SubResource("AnimationNodeBlendTree_hmklb")
@ -244,7 +253,7 @@ states/Start/position = Vector2(572.26, 14.954)
"states/Stationary [turn]/position" = Vector2(572.26, 94.3447) "states/Stationary [turn]/position" = Vector2(572.26, 94.3447)
"states/Walk [turn]/node" = SubResource("AnimationNodeBlendTree_2mbyh") "states/Walk [turn]/node" = SubResource("AnimationNodeBlendTree_2mbyh")
"states/Walk [turn]/position" = Vector2(572.26, 258.767) "states/Walk [turn]/position" = Vector2(572.26, 258.767)
transitions = ["Aim [aim] [turn]", "Aim Down [aim]", SubResource("AnimationNodeStateMachineTransition_4lybd"), "Aim Down [aim]", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_5aafd"), "Aim [aim] [turn]", "Fire [aim]", SubResource("AnimationNodeStateMachineTransition_8f4gl"), "Fire [aim]", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_xnat3"), "Walk [turn]", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_12bos"), "Aim Down [aim]", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_n0ndr"), "Walk [turn]", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_0wc5e"), "Stationary [turn]", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_4hisb"), "Start", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_bmty6"), "Stationary [turn]", "RESET To Aim", SubResource("AnimationNodeStateMachineTransition_kyd6p"), "RESET To Aim", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_w5kob"), "Stationary [turn]", "Run", SubResource("AnimationNodeStateMachineTransition_g0i3x"), "Walk [turn]", "Run", SubResource("AnimationNodeStateMachineTransition_ocffv"), "Run", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_h0my5"), "Run", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_nymcr"), "Run", "Stab", SubResource("AnimationNodeStateMachineTransition_g5qf0"), "Stab", "Run", SubResource("AnimationNodeStateMachineTransition_27kmb"), "Stationary [turn]", "Stab", SubResource("AnimationNodeStateMachineTransition_4q0ot"), "Stab", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_h6ujc"), "Walk [turn]", "Stab", SubResource("AnimationNodeStateMachineTransition_3bu8l"), "Stab", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_cpibo")] transitions = ["Aim [aim] [turn]", "Aim Down [aim]", SubResource("AnimationNodeStateMachineTransition_4lybd"), "Aim Down [aim]", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_5aafd"), "Aim [aim] [turn]", "Fire [aim]", SubResource("AnimationNodeStateMachineTransition_8f4gl"), "Fire [aim]", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_xnat3"), "Walk [turn]", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_12bos"), "Aim Down [aim]", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_n0ndr"), "Walk [turn]", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_0wc5e"), "Stationary [turn]", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_4hisb"), "Start", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_bmty6"), "Stationary [turn]", "RESET To Aim", SubResource("AnimationNodeStateMachineTransition_kyd6p"), "RESET To Aim", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_w5kob"), "Stationary [turn]", "Run", SubResource("AnimationNodeStateMachineTransition_g0i3x"), "Walk [turn]", "Run", SubResource("AnimationNodeStateMachineTransition_ocffv"), "Run", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_h0my5"), "Run", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_nymcr"), "Run", "Stab", SubResource("AnimationNodeStateMachineTransition_g5qf0"), "Stab", "Run", SubResource("AnimationNodeStateMachineTransition_27kmb"), "Stationary [turn]", "Stab", SubResource("AnimationNodeStateMachineTransition_4q0ot"), "Stab", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_h6ujc"), "Walk [turn]", "Stab", SubResource("AnimationNodeStateMachineTransition_3bu8l"), "Stab", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_cpibo"), "Hit", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_0ppx7")]
graph_offset = Vector2(-87.4971, -116.108) graph_offset = Vector2(-87.4971, -116.108)
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_au62i"] [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_au62i"]

BIN
godot/models/character.glb (Stored with Git LFS)

Binary file not shown.

BIN
models/character.blend (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@ -32,61 +32,67 @@ void Enemy::chase_enter() {
} }
void Enemy::chase() { void Enemy::chase() {
bool const is_chasing{!this->agent->is_navigation_finished()}; bool const at_end{!this->agent->is_navigation_finished()};
this->anim_tree->set_lock_running(is_chasing); this->anim_tree->set_lock_running(at_end);
this->anim_tree->set_aim_weapon(!is_chasing); this->anim_tree->set_aim_weapon(!at_end);
if(is_chasing) { if(at_end) {
gd::Vector3 const global_pos{this->get_global_position()}; gd::Vector3 const global_pos{this->get_global_position()};
gd::Vector3 const target{global_pos * 2 - this->agent->get_next_path_position()}; gd::Vector3 const target{global_pos * 2 - this->agent->get_next_path_position()};
this->look_at({target.x, global_pos.y, target.z}); this->look_at({target.x, global_pos.y, target.z});
} } else if(this->get_global_position().distance_to(this->player->get_global_position()) >= this->agent->get_target_desired_distance())
if(this->get_global_position().distance_to(this->player->get_global_position()) >= this->agent->get_target_desired_distance())
this->chase_enter(); // repath this->chase_enter(); // repath
} }
Enemy::ActionFn Enemy::miss_enter() { Enemy::ActionFn Enemy::wait_line_of_sight() {
if(this->can_see_player)
return (ActionFn)&Enemy::take_aim;
else
return (ActionFn)&Enemy::wait_line_of_sight;
}
Enemy::ActionFn Enemy::take_aim() {
this->anim_tree->set_aim_weapon(true); this->anim_tree->set_aim_weapon(true);
return (ActionFn)&Enemy::miss; if(this->anim_tree->get_current_state().begins_with("Aim"))
return (ActionFn)&Enemy::hit;
else
return(ActionFn)&Enemy::take_aim;
} }
Enemy::ActionFn Enemy::miss() { Enemy::ActionFn Enemy::miss() {
if(this->anim_tree->get_current_state().begins_with("Fire") || this->anim_tree->get_fire_weapon()) // last shot still going
return (ActionFn)&Enemy::miss;
if(this->can_see_player) { if(this->can_see_player) {
gd::Basis const basis{this->get_global_basis()}; gd::Basis const basis{this->get_global_basis()};
this->look_at(this->get_global_position() * 2 - this->player->get_global_position() + basis.get_column(0)); this->look_at(this->get_global_position() * 2 - this->player->get_global_position() + basis.get_column(0) * 0.6f);
this->anim_tree->set_aim_weapon(true); this->anim_tree->set_aim_weapon(true);
this->anim_tree->set_fire_weapon(); this->anim_tree->set_fire_weapon();
if(this->anim_tree->get_fire_weapon()) { ++this->missed_shots;
gd::UtilityFunctions::print("!!! miss fired"); return (ActionFn)&Enemy::wait_end_of_shot;
return ++this->missed_shots > SHOTS_BEFORE_HIT ? (ActionFn)&Enemy::hit_enter : (ActionFn)&Enemy::miss_enter;
}
} else { } else {
this->chase(); this->chase();
} }
return (ActionFn)&Enemy::miss; return (ActionFn)&Enemy::miss;
} }
Enemy::ActionFn Enemy::hit_enter() {
this->anim_tree->set_aim_weapon(true);
return (ActionFn)&Enemy::hit;
}
Enemy::ActionFn Enemy::hit() { Enemy::ActionFn Enemy::hit() {
if(this->anim_tree->get_current_state().begins_with("Fire") || this->anim_tree->get_fire_weapon()) // last shot still going if(this->can_see_player) {
return (ActionFn)&Enemy::hit;
else if(this->can_see_player) {
this->look_at(this->get_global_position() * 2 - this->player->get_global_position()); this->look_at(this->get_global_position() * 2 - this->player->get_global_position());
this->anim_tree->set_aim_weapon(true); this->anim_tree->set_aim_weapon(true);
this->anim_tree->set_fire_weapon(); this->anim_tree->set_fire_weapon();
this->missed_shots = 0; this->missed_shots = 0;
return (ActionFn)&Enemy::miss_enter; return (ActionFn)&Enemy::wait_end_of_shot;
} else { } else {
this->chase(); this->chase();
} }
return (ActionFn)&Enemy::hit; return (ActionFn)&Enemy::hit;
} }
Enemy::ActionFn Enemy::wait_end_of_shot() {
if(this->anim_tree->get_current_state().begins_with("Fire") || this->anim_tree->get_fire_weapon()) // last shot still going
return (ActionFn)&Enemy::wait_end_of_shot;
else
return this->missed_shots >= SHOTS_BEFORE_HIT ? (ActionFn)&Enemy::hit : (ActionFn)&Enemy::miss;
}
void Enemy::_physics_process(double delta) { void Enemy::_physics_process(double delta) {
this->update_can_see_player(); this->update_can_see_player();
gd::Basis const basis{this->get_global_basis()}; gd::Basis const basis{this->get_global_basis()};
@ -95,7 +101,7 @@ void Enemy::_physics_process(double delta) {
basis.get_column(0) * motion.x + basis.get_column(0) * motion.x +
basis.get_column(1) * motion.y + basis.get_column(1) * motion.y +
basis.get_column(2) * motion.z basis.get_column(2) * motion.z
}); });\
this->move_and_slide(); this->move_and_slide();
} }
@ -107,7 +113,7 @@ void Enemy::damage() {
void Enemy::notice_player(Player *player) { void Enemy::notice_player(Player *player) {
this->player = player; this->player = player;
this->current_action_fn = (ActionFn)&Enemy::miss_enter; this->current_action_fn = (ActionFn)&Enemy::wait_line_of_sight;
} }
void Enemy::update_can_see_player() { void Enemy::update_can_see_player() {

View File

@ -19,12 +19,13 @@ public:
void update(); void update();
void chase_enter(); void chase_enter();
void chase(); void chase();
ActionFn miss_enter(); ActionFn wait_line_of_sight();
ActionFn take_aim();
ActionFn miss(); ActionFn miss();
ActionFn hit_enter();
ActionFn hit(); ActionFn hit();
ActionFn stab_enter(); ActionFn stab_enter();
ActionFn stab(); ActionFn stab();
ActionFn wait_end_of_shot();
virtual void _physics_process(double delta) override; virtual void _physics_process(double delta) override;
virtual void damage() override; virtual void damage() override;
@ -34,10 +35,10 @@ public:
void set_update_interval(float time); void set_update_interval(float time);
float get_update_interval() const; float get_update_interval() const;
private: private:
int const SHOTS_BEFORE_HIT{2}; int const SHOTS_BEFORE_HIT{1};
int missed_shots{0}; int missed_shots{0};
double update_interval{0.2}; double update_interval{0.4};
ActionFn current_action_fn{nullptr}; ActionFn current_action_fn{nullptr};
bool can_see_player{false}; bool can_see_player{false};
Player *player{nullptr}; Player *player{nullptr};

View File

@ -51,7 +51,7 @@ void Player::_physics_process(double delta [[maybe_unused]]) {
} }
void Player::damage() { void Player::damage() {
this->anim_tree->death_animation(); this->anim_tree->hit_animation();
} }
void Player::process_transform_camera(double delta) { void Player::process_transform_camera(double delta) {

View File

@ -111,6 +111,10 @@ bool PlayerAnimTree::get_stab() {
return is_set; return is_set;
} }
void PlayerAnimTree::hit_animation() {
this->fsm->start("Hit", true);
}
void PlayerAnimTree::death_animation() { void PlayerAnimTree::death_animation() {
this->set("parameters/DeathSeek/request", 0.f); this->set("parameters/DeathSeek/request", 0.f);
this->is_dead = true; this->is_dead = true;

View File

@ -36,6 +36,7 @@ public:
bool get_fire_weapon(); bool get_fire_weapon();
void set_stab(); void set_stab();
bool get_stab(); bool get_stab();
void hit_animation();
void death_animation(); void death_animation();
bool match_tags(Tags tags) const; bool match_tags(Tags tags) const;
gd::StringName const &get_current_state() const; gd::StringName const &get_current_state() const;