Skip to content

Commit

Permalink
Improve weapon state transition (#11)
Browse files Browse the repository at this point in the history
- Introduce state type
- Introduce transition request and interrupt
- Introduce OnContextSet to get context values
- Introduce destroyed flag to cleanup thread
  • Loading branch information
bilalkah authored Sep 18, 2024
1 parent c15aade commit f79930a
Show file tree
Hide file tree
Showing 15 changed files with 346 additions and 142 deletions.
3 changes: 3 additions & 0 deletions scripts/install_deps.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# install build-essential
sudo apt install build-essential cmake g++ gcc -y;

#install sdl2
sudo apt install libsdl2-dev libsdl2-2.0-0 -y;

Expand Down
5 changes: 3 additions & 2 deletions src/Animation/include/Animation/time_based_single_animation.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ namespace wolfenstein {
class TBSAnimation : public IAnimation
{
public:
TBSAnimation(const std::vector<uint16_t>& tex_ids, const double animation_speed);
TBSAnimation(const std::vector<uint16_t>& textures,
const double animation_speed);
~TBSAnimation() = default;

void Update(const double& delta_time) override;
Expand All @@ -30,7 +31,7 @@ class TBSAnimation : public IAnimation
int GetCurrentFrame() const override;

private:
std::vector<uint16_t> tex_ids;
std::vector<uint16_t> textures;
int current_frame;
double animation_speed;
double counter;
Expand Down
8 changes: 4 additions & 4 deletions src/Animation/src/time_based_single_animation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

namespace wolfenstein {

TBSAnimation::TBSAnimation(const std::vector<uint16_t>& tex_ids,
TBSAnimation::TBSAnimation(const std::vector<uint16_t>& textures,
const double animation_speed)
: tex_ids(tex_ids),
: textures(textures),
current_frame(0),
animation_speed(animation_speed),
counter(0) {}

void TBSAnimation::Update(const double& delta_time) {
counter += delta_time;
if (counter > animation_speed) {
current_frame = (current_frame + 1) % tex_ids.size();
current_frame = (current_frame + 1) % textures.size();
counter = 0;
}
}
Expand All @@ -23,7 +23,7 @@ void TBSAnimation::Reset() {
}

int TBSAnimation::GetCurrentFrame() const {
return tex_ids[current_frame];
return textures[current_frame];
}

} // namespace wolfenstein
8 changes: 4 additions & 4 deletions src/Characters/include/Characters/enemy.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ class Enemy : public ICharacter,
public std::enable_shared_from_this<Enemy>
{
public:
explicit Enemy(CharacterConfig config, std::shared_ptr<State<Enemy>> state,
double width, double height);
explicit Enemy(CharacterConfig config, EnemyStatePtr state, double width,
double height);
~Enemy() = default;
void Init();
void Update(double delta_time) override;
void TransitionTo(std::shared_ptr<State<Enemy>> state);
void TransitionTo(EnemyStatePtr state);

void SetPose(const vector2d& pose) override;
void SetPosition(Position2D position) override;
Expand All @@ -52,7 +52,7 @@ class Enemy : public ICharacter,
Position2D position_;
double rotation_speed_;
double translation_speed_;
std::shared_ptr<State<Enemy>> state_;
EnemyStatePtr state_;
double width;
double height;
std::string id_;
Expand Down
2 changes: 1 addition & 1 deletion src/Characters/include/Characters/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Player : public ICharacter, public IGameObject
private:
void Move(double delta_time);
void Rotate(double delta_time);
void ShootAndReload();
void ShootOrReload();

Position2D position_;
double rotation_speed_;
Expand Down
4 changes: 2 additions & 2 deletions src/Characters/src/enemy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace wolfenstein {

Enemy::Enemy(CharacterConfig config, std::shared_ptr<State<Enemy>> state,
Enemy::Enemy(CharacterConfig config, EnemyStatePtr state,
double width, double height)
: position_(config.initial_position),
rotation_speed_(config.rotation_speed),
Expand All @@ -20,7 +20,7 @@ void Enemy::Init() {
state_->SetContext(shared_from_this());
}

void Enemy::TransitionTo(std::shared_ptr<State<Enemy>> state) {
void Enemy::TransitionTo(EnemyStatePtr state) {
state_ = state;
state_->SetContext(shared_from_this());
}
Expand Down
16 changes: 10 additions & 6 deletions src/Characters/src/player.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "Characters/player.h"
#include "CollisionManager/collision_manager.h"
#include "Math/vector.h"
#include "State/weapon_state.h"
#include "Utility/uuid_generator.h"
#include <SDL2/SDL.h>

Expand All @@ -12,11 +13,12 @@ Player::Player(CharacterConfig& config)
translation_speed_(config.translation_speed) {
id_ = UuidGenerator::GetInstance().GenerateUuid().bytes();
weapon_ = std::make_shared<Weapon>("mp5");
weapon_->Init();
WeaponStatePtr loaded_state = std::make_shared<LoadedState>("mp5");
weapon_->TransitionTo(loaded_state);
}

void Player::Update(double delta_time) {
ShootAndReload();
ShootOrReload();
Move(delta_time);
Rotate(delta_time);
for (auto& subscriber : player_position_subscribers_) {
Expand Down Expand Up @@ -112,15 +114,17 @@ void Player::Rotate(double delta_time) {
}
}

void Player::ShootAndReload() {
if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON_LMASK) {
weapon_->Attack();
}
void Player::ShootOrReload() {
// If R is pressed, reload
const Uint8* keystate = SDL_GetKeyboardState(NULL);
if (keystate[SDL_SCANCODE_R]) {
weapon_->Reload();
}

// If left mouse button is pressed, attack
if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON_LMASK) {
weapon_->Attack();
}
}

} // namespace wolfenstein
2 changes: 1 addition & 1 deletion src/Core/include/Core/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
#include "Camera/camera.h"
#include "Characters/player.h"
#include "CollisionManager/collision_manager.h"
#include "Graphics/renderer.h"
#include "Core/scene.h"
#include "Graphics/renderer.h"
#include "Map/map.h"
#include "Math/vector.h"
#include "TextureManager/texture_manager.h"
Expand Down
14 changes: 14 additions & 0 deletions src/State/include/State/enemy_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,19 @@
#define STATE_INCLUDE_STATE_ENEMY_STATE_H_

#include "State/state.h"
#include <vector>

namespace wolfenstein {

class Enemy;
typedef std::shared_ptr<State<Enemy>> EnemyStatePtr;

template <>
struct StateType<Enemy>
{
enum class Type { Idle, Walk, Attack, Pain, Death };
};
typedef StateType<Enemy>::Type EnemyStateType;

class IdleState : public State<Enemy>
{
Expand All @@ -27,6 +36,7 @@ class IdleState : public State<Enemy>
void Update(const double& delta_time) override;
void Reset() override;
int GetCurrentFrame() const override;
EnemyStateType GetType() const override;

private:
std::string bot_name_;
Expand All @@ -46,6 +56,7 @@ class WalkState : public State<Enemy>
void Update(const double& delta_time) override;
void Reset() override;
int GetCurrentFrame() const override;
EnemyStateType GetType() const override;

private:
std::string bot_name_;
Expand All @@ -65,6 +76,7 @@ class AttackState : public State<Enemy>
void Update(const double& delta_time) override;
void Reset() override;
int GetCurrentFrame() const override;
EnemyStateType GetType() const override;

private:
std::string bot_name_;
Expand All @@ -84,6 +96,7 @@ class PainState : public State<Enemy>
void Update(const double& delta_time) override;
void Reset() override;
int GetCurrentFrame() const override;
EnemyStateType GetType() const override;

private:
std::string bot_name_;
Expand All @@ -103,6 +116,7 @@ class DeathState : public State<Enemy>
void Update(const double& delta_time) override;
void Reset() override;
int GetCurrentFrame() const override;
EnemyStateType GetType() const override;

private:
std::string bot_name_;
Expand Down
41 changes: 11 additions & 30 deletions src/State/include/State/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,51 +12,32 @@
#ifndef STATE_INCLUDE_STATE_STATE_H_
#define STATE_INCLUDE_STATE_STATE_H_

#include <cstdint>
#include <memory>
#include <unordered_map>
#include <vector>

namespace wolfenstein {

template <typename T>
struct StateType;

template <typename T>
class State
{
public:
virtual ~State() = default;
void SetContext(std::shared_ptr<T> context) { context_ = context; }
void SetContext(std::shared_ptr<T> context) {
context_ = context;
OnContextSet();
};
virtual void OnContextSet() { /* Do nothing */ };
virtual void Update(const double& delta_time) = 0;
virtual void Reset() = 0;
virtual void TransitionRequest(
std::shared_ptr<State<T>>&) { /* Do nothing */ };
virtual int GetCurrentFrame() const = 0;
virtual StateType<T>::Type GetType() const = 0;

protected:
std::shared_ptr<T> context_;
std::unordered_map<std::string,
std::unordered_map<std::string, std::string>>
enemy_data_{{"soldier",
{{"idle", "soldier_idle"},
{"walk", "soldier_walk"},
{"attack", "soldier_attack"},
{"death", "soldier_death"},
{"pain", "soldier_pain"}}},
{"caco_demon",
{{"idle", "caco_demon_idle"},
{"walk", "caco_demon_walk"},
{"attack", "caco_demon_attack"},
{"death", "caco_demon_death"},
{"pain", "caco_demon_pain"}}},
{"cyber_demon",
{{"idle", "cyber_demon_idle"},
{"walk", "cyber_demon_walk"},
{"attack", "cyber_demon_attack"},
{"death", "cyber_demon_death"},
{"pain", "cyber_demon_pain"}}}};
std::unordered_map<std::string,
std::unordered_map<std::string, std::string>>
weapon_data_{{"mp5",
{{"loaded", "mp5_loaded"},
{"outofammo", "mp5_outofammo"},
{"reload", "mp5_reload"}}}};
};

} // namespace wolfenstein
Expand Down
36 changes: 30 additions & 6 deletions src/State/include/State/weapon_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,37 @@
namespace wolfenstein {

class Weapon;
typedef std::shared_ptr<State<Weapon>> WeaponStatePtr;

template <>
struct StateType<Weapon>
{
enum class Type { Loaded, OutOfAmmo, Reloading };
};
typedef StateType<Weapon>::Type WeaponStateType;

class LoadedState : public State<Weapon>
{
public:
LoadedState(const std::string weapon_name);
~LoadedState();

void Update(const double& delta_time) override;
void Update(const double&) override;
void Reset() override;
void OnContextSet() override;
void TransitionRequest(std::shared_ptr<State<Weapon>>& state) override;
int GetCurrentFrame() const override;
WeaponStateType GetType() const override;

private:
void AttackAnimation();
std::string weapon_name_;
double last_attack_time_;
double animation_speed_;
bool cooldown_;
double last_attack_time_;
bool interrupt_;
bool destroyed_;
WeaponStatePtr requested_state_;
std::shared_ptr<TBSAnimation> animation_;
};

Expand All @@ -45,16 +59,22 @@ class OutOfAmmoState : public State<Weapon>
OutOfAmmoState(const std::string weapon_name);
~OutOfAmmoState();

void Update(const double& delta_time) override;
void Update(const double&) override;
void Reset() override;
void OnContextSet() override;
void TransitionRequest(std::shared_ptr<State<Weapon>>& state) override;
int GetCurrentFrame() const override;
WeaponStateType GetType() const override;

private:
void NoAttackAnimation();
std::string weapon_name_;
double last_attack_time_;
double animation_speed_;
bool cooldown_;
double last_attack_time_;
bool interrupt_;
bool destroyed_;
WeaponStatePtr requested_state_;
std::shared_ptr<TBSAnimation> animation_;
};

Expand All @@ -64,16 +84,20 @@ class ReloadingState : public State<Weapon>
ReloadingState(const std::string weapon_name);
~ReloadingState();

void Update(const double& delta_time) override;
void Update(const double&) override;
void Reset() override;
void OnContextSet() override;
int GetCurrentFrame() const override;
WeaponStateType GetType() const override;

private:
void ReloadAnimation();
std::string weapon_name_;
double last_attack_time_;
double animation_speed_;
bool cooldown_;
double last_attack_time_;
bool interrupt_;
bool destroyed_;
std::shared_ptr<TBSAnimation> animation_;
};

Expand Down
Loading

0 comments on commit f79930a

Please sign in to comment.