From 0b82d1b42876879b28e51b4aa877a2fd5a7d246c Mon Sep 17 00:00:00 2001 From: tovjemam Date: Tue, 9 Sep 2025 01:00:51 +0200 Subject: [PATCH] Add simple player STM --- src/assets/animation.hpp | 1 + src/game/player.cpp | 90 +++++++++++++++++++++++++++++++++++++++- src/game/player.hpp | 24 +++++++++++ 3 files changed, 113 insertions(+), 2 deletions(-) diff --git a/src/assets/animation.hpp b/src/assets/animation.hpp index 494272d..6ef01f8 100644 --- a/src/assets/animation.hpp +++ b/src/assets/animation.hpp @@ -30,6 +30,7 @@ namespace assets size_t GetNumFrames() const { return num_frames_; } float GetTPS() const { return tps_; } + float GetDuration() const { return static_cast(num_frames_) / tps_; } size_t GetNumChannels() const { return channels_.size(); } const AnimationChannel& GetChannel(int index) const { return channels_[index]; } diff --git a/src/game/player.cpp b/src/game/player.cpp index 103e8d1..1e13186 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -19,8 +19,6 @@ game::Player::Player(World* world, size_t sector_idx, const glm::vec3& position) world->GetTimePtr() ); - vm_hands_.PlayAnim("knife_idle"); - light_trace_offset_ = glm::vec3(0.0f, 0.0f, 0.6f); } @@ -40,6 +38,8 @@ void game::Player::Update(float dt) { time_ += dt; + UpdateState(); + vm_node_.UpdateMatrix(); vm_hands_.Update(); @@ -195,3 +195,89 @@ glm::vec2 game::Player::GetBobbingOffset(float t, float amplitude) return offset; } + + +//// STATE MACHINE +struct PlayerStateTableEntry +{ + void (game::Player::*enter)(); + int (game::Player::*update)(); + void (game::Player::*exit)(); +}; + +void game::Player::UpdateState() +{ + static const PlayerStateTableEntry state_table[] = + { + // enter update exit + { nullptr, &game::Player::Update_Init, nullptr }, // PS_INIT + { &game::Player::Enter_Idle, &game::Player::Update_Idle, nullptr }, // PS_IDLE + { &game::Player::Enter_Attack, &game::Player::Update_Attack, nullptr }, // PS_ATTACK + }; + + int new_state = -1; + do + { + int new_state = (this->*state_table[state_].update)(); + + if (new_state >= 0) + { + if (auto exit_fun = state_table[state_].exit) + (this->*exit_fun)(); + + state_ = static_cast(new_state); + + if (auto enter_fun = state_table[state_].enter) + (this->*enter_fun)(); + } + } + while (new_state >= 0); +} + +// INIT + +int game::Player::Update_Init() +{ + return PS_IDLE; +} + +// IDLE + +void game::Player::Enter_Idle() +{ + vm_hands_.PlayAnim("knife_idle", ANIM_LOOP); +} + +int game::Player::Update_Idle() +{ + if (input_ & PI_ATTACK) + { + return PS_ATTACK; + } + + return -1; +} + +// ATTACK + +void game::Player::Enter_Attack() +{ + if (rand() % 2 == 0) + { + vm_hands_.PlayAnim("knife_attack1"); + } + else + { + vm_hands_.PlayAnim("knife_attack2"); + } +} + +int game::Player::Update_Attack() +{ + if (vm_hands_.AnimDone()) + { + return PS_IDLE; + } + + return -1; +} diff --git a/src/game/player.hpp b/src/game/player.hpp index b82e414..ea058fe 100644 --- a/src/game/player.hpp +++ b/src/game/player.hpp @@ -6,6 +6,13 @@ namespace game { + enum PlayerState + { + PS_INIT, + PS_IDLE, + PS_ATTACK, + }; + class Player : public Entity { using Super = Entity; @@ -32,6 +39,8 @@ namespace game TransformNode vm_node_; // Affected by bobbing MeshInstance vm_hands_; std::unique_ptr vm_weapon_; // Can be null + + PlayerState state_ = PS_INIT; public: Player(World* world, size_t sector_idx, const glm::vec3& position); @@ -51,6 +60,21 @@ namespace game private: static glm::vec2 GetBobbingOffset(float t, float amplitude); + // STATE MACHINE + + void UpdateState(); + + //void Enter_Init(); + int Update_Init(); + //void Exit_Init(); + + void Enter_Idle(); + int Update_Idle(); + //void Exit_Idle(); + + void Enter_Attack(); + int Update_Attack(); + //void Exit_Attack(); };