From 9ed5528af0e4c97b2a566c1fc3d30510f0fa171a Mon Sep 17 00:00:00 2001 From: Bilal Kahraman Date: Sat, 14 Sep 2024 18:36:36 +0300 Subject: [PATCH] features - Weapon animations are done - Bot animation skeleton is prepared - MP5 assets added - Animator is removed because state is better approach - Texture manager is improved --- .gitattributes | 4 +- CMakeLists.txt | 1 + app/main.cpp | 2 +- assets/sprites/weapon/mp5/loaded/0.png | 3 + assets/sprites/weapon/mp5/loaded/1.png | 3 + assets/sprites/weapon/mp5/loaded/2.png | 3 + assets/sprites/weapon/mp5/loaded/3.png | 3 + assets/sprites/weapon/mp5/loaded/4.png | 3 + assets/sprites/weapon/mp5/loaded/5.png | 3 + assets/sprites/weapon/mp5/outofammo/0.png | 3 + assets/sprites/weapon/mp5/outofammo/1.png | 3 + assets/sprites/weapon/mp5/outofammo/2.png | 3 + assets/sprites/weapon/mp5/outofammo/3.png | 3 + assets/sprites/weapon/mp5/reload/0.png | 3 + assets/sprites/weapon/mp5/reload/1.png | 3 + assets/sprites/weapon/mp5/reload/10.png | 3 + assets/sprites/weapon/mp5/reload/11.png | 3 + assets/sprites/weapon/mp5/reload/12.png | 3 + assets/sprites/weapon/mp5/reload/13.png | 3 + assets/sprites/weapon/mp5/reload/14.png | 3 + assets/sprites/weapon/mp5/reload/15.png | 3 + assets/sprites/weapon/mp5/reload/2.png | 3 + assets/sprites/weapon/mp5/reload/3.png | 3 + assets/sprites/weapon/mp5/reload/4.png | 3 + assets/sprites/weapon/mp5/reload/5.png | 3 + assets/sprites/weapon/mp5/reload/6.png | 3 + assets/sprites/weapon/mp5/reload/7.png | 3 + assets/sprites/weapon/mp5/reload/8.png | 3 + assets/sprites/weapon/mp5/reload/9.png | 3 + project.drawio.png | Bin 37601 -> 131 bytes src/Animation/CMakeLists.txt | 2 +- src/Animation/include/Animation/animator.h | 38 ----- .../include/Animation/walk_animation.h | 41 ----- src/Animation/src/animator.cpp | 0 src/Animation/src/walk_animation.cpp | 26 --- src/Characters/CMakeLists.txt | 3 +- src/Characters/include/Characters/enemy.h | 19 ++- src/Characters/include/Characters/player.h | 12 +- src/Characters/src/enemy.cpp | 24 ++- src/Characters/src/player.cpp | 24 ++- src/Core/CMakeLists.txt | 1 + src/Core/src/game.cpp | 35 ++-- src/Core/src/scene.cpp | 4 +- src/Graphics/src/renderer.cpp | 19 ++- .../src/navigation_manager.cpp | 7 +- src/State/CMakeLists.txt | 33 ++++ src/State/include/State/enemy_state.h | 118 +++++++++++++ src/State/include/State/state.h | 64 +++++++ src/State/include/State/weapon_state.h | 82 +++++++++ src/State/src/enemy_state.cpp | 157 ++++++++++++++++++ src/State/src/weapon_state.cpp | 142 ++++++++++++++++ src/Strike/CMakeLists.txt | 9 +- src/Strike/include/Strike/shotgun.h | 42 ----- src/Strike/include/Strike/weapon.h | 34 +++- src/Strike/src/shotgun.cpp | 47 ------ src/Strike/src/weapon.cpp | 70 ++++++++ .../include/TextureManager/texture_manager.h | 6 + src/TextureManager/src/texture_manager.cpp | 98 +++++++---- 58 files changed, 946 insertions(+), 296 deletions(-) create mode 100644 assets/sprites/weapon/mp5/loaded/0.png create mode 100644 assets/sprites/weapon/mp5/loaded/1.png create mode 100644 assets/sprites/weapon/mp5/loaded/2.png create mode 100644 assets/sprites/weapon/mp5/loaded/3.png create mode 100644 assets/sprites/weapon/mp5/loaded/4.png create mode 100644 assets/sprites/weapon/mp5/loaded/5.png create mode 100644 assets/sprites/weapon/mp5/outofammo/0.png create mode 100644 assets/sprites/weapon/mp5/outofammo/1.png create mode 100644 assets/sprites/weapon/mp5/outofammo/2.png create mode 100644 assets/sprites/weapon/mp5/outofammo/3.png create mode 100644 assets/sprites/weapon/mp5/reload/0.png create mode 100644 assets/sprites/weapon/mp5/reload/1.png create mode 100644 assets/sprites/weapon/mp5/reload/10.png create mode 100644 assets/sprites/weapon/mp5/reload/11.png create mode 100644 assets/sprites/weapon/mp5/reload/12.png create mode 100644 assets/sprites/weapon/mp5/reload/13.png create mode 100644 assets/sprites/weapon/mp5/reload/14.png create mode 100644 assets/sprites/weapon/mp5/reload/15.png create mode 100644 assets/sprites/weapon/mp5/reload/2.png create mode 100644 assets/sprites/weapon/mp5/reload/3.png create mode 100644 assets/sprites/weapon/mp5/reload/4.png create mode 100644 assets/sprites/weapon/mp5/reload/5.png create mode 100644 assets/sprites/weapon/mp5/reload/6.png create mode 100644 assets/sprites/weapon/mp5/reload/7.png create mode 100644 assets/sprites/weapon/mp5/reload/8.png create mode 100644 assets/sprites/weapon/mp5/reload/9.png delete mode 100644 src/Animation/include/Animation/animator.h delete mode 100644 src/Animation/include/Animation/walk_animation.h delete mode 100644 src/Animation/src/animator.cpp delete mode 100644 src/Animation/src/walk_animation.cpp create mode 100644 src/State/CMakeLists.txt create mode 100644 src/State/include/State/enemy_state.h create mode 100644 src/State/include/State/state.h create mode 100644 src/State/include/State/weapon_state.h create mode 100644 src/State/src/enemy_state.cpp create mode 100644 src/State/src/weapon_state.cpp delete mode 100644 src/Strike/include/Strike/shotgun.h delete mode 100644 src/Strike/src/shotgun.cpp create mode 100644 src/Strike/src/weapon.cpp diff --git a/.gitattributes b/.gitattributes index 74b6958..be20bd9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ -*.png filter=lfs diff=lfs merge=lfs -text -*.ttf filter=lfs diff=lfs merge=lfs -text +**/*.png filter=lfs diff=lfs merge=lfs -text +**/*.ttf filter=lfs diff=lfs merge=lfs -text diff --git a/CMakeLists.txt b/CMakeLists.txt index e382f23..9bf535d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ add_subdirectory(src/Map) add_subdirectory(src/Math) add_subdirectory(src/NavigationManager) add_subdirectory(src/Strike) +add_subdirectory(src/State) add_subdirectory(src/TextureManager) add_subdirectory(src/TimeManager) add_subdirectory(src/Utility) diff --git a/app/main.cpp b/app/main.cpp index 452580b..53b159b 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -13,7 +13,7 @@ int main() { using namespace wolfenstein; - GeneralConfig config(800, 600, 0, 50, 120, 15.0, ToRadians(60.0), false); + GeneralConfig config(800, 600, 0, 30, 120, 15.0, ToRadians(60.0), false); Game game(config); game.Run(); diff --git a/assets/sprites/weapon/mp5/loaded/0.png b/assets/sprites/weapon/mp5/loaded/0.png new file mode 100644 index 0000000..f32d7fe --- /dev/null +++ b/assets/sprites/weapon/mp5/loaded/0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2972b13dee076e38d6393eef2e814e4494bb31e5046045cdaa4bf17057423f72 +size 20814 diff --git a/assets/sprites/weapon/mp5/loaded/1.png b/assets/sprites/weapon/mp5/loaded/1.png new file mode 100644 index 0000000..b6b67a0 --- /dev/null +++ b/assets/sprites/weapon/mp5/loaded/1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f177db7c745a9fc4a6f879b8dcbbf860079e996d995b4b8ae10020db4247b4d5 +size 27104 diff --git a/assets/sprites/weapon/mp5/loaded/2.png b/assets/sprites/weapon/mp5/loaded/2.png new file mode 100644 index 0000000..5531938 --- /dev/null +++ b/assets/sprites/weapon/mp5/loaded/2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e57e246c6d6db6bbed576327d4ccb99607b22aa0c12825b3733668ed5c00f552 +size 30849 diff --git a/assets/sprites/weapon/mp5/loaded/3.png b/assets/sprites/weapon/mp5/loaded/3.png new file mode 100644 index 0000000..0be2a6f --- /dev/null +++ b/assets/sprites/weapon/mp5/loaded/3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1cce8f9473605a0717ce0b53eb222fd5cc1347538210a838b8b13ecfbdb8b6f5 +size 17995 diff --git a/assets/sprites/weapon/mp5/loaded/4.png b/assets/sprites/weapon/mp5/loaded/4.png new file mode 100644 index 0000000..02cee7f --- /dev/null +++ b/assets/sprites/weapon/mp5/loaded/4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d88d115184d391a3b9446e8bbcd254c5605d0598830e6b1534146bef9749a666 +size 20211 diff --git a/assets/sprites/weapon/mp5/loaded/5.png b/assets/sprites/weapon/mp5/loaded/5.png new file mode 100644 index 0000000..1c9d993 --- /dev/null +++ b/assets/sprites/weapon/mp5/loaded/5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81e6c781a19e204dfc916440ac1fb512f511c8640d2d9d60af3597d863ced338 +size 20944 diff --git a/assets/sprites/weapon/mp5/outofammo/0.png b/assets/sprites/weapon/mp5/outofammo/0.png new file mode 100644 index 0000000..f32d7fe --- /dev/null +++ b/assets/sprites/weapon/mp5/outofammo/0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2972b13dee076e38d6393eef2e814e4494bb31e5046045cdaa4bf17057423f72 +size 20814 diff --git a/assets/sprites/weapon/mp5/outofammo/1.png b/assets/sprites/weapon/mp5/outofammo/1.png new file mode 100644 index 0000000..0be2a6f --- /dev/null +++ b/assets/sprites/weapon/mp5/outofammo/1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1cce8f9473605a0717ce0b53eb222fd5cc1347538210a838b8b13ecfbdb8b6f5 +size 17995 diff --git a/assets/sprites/weapon/mp5/outofammo/2.png b/assets/sprites/weapon/mp5/outofammo/2.png new file mode 100644 index 0000000..02cee7f --- /dev/null +++ b/assets/sprites/weapon/mp5/outofammo/2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d88d115184d391a3b9446e8bbcd254c5605d0598830e6b1534146bef9749a666 +size 20211 diff --git a/assets/sprites/weapon/mp5/outofammo/3.png b/assets/sprites/weapon/mp5/outofammo/3.png new file mode 100644 index 0000000..1c9d993 --- /dev/null +++ b/assets/sprites/weapon/mp5/outofammo/3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81e6c781a19e204dfc916440ac1fb512f511c8640d2d9d60af3597d863ced338 +size 20944 diff --git a/assets/sprites/weapon/mp5/reload/0.png b/assets/sprites/weapon/mp5/reload/0.png new file mode 100644 index 0000000..4dbbc91 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abcc3fa70080008634635dc9c17865bbdf6efce496c3fcda5cc039deab220bd1 +size 21526 diff --git a/assets/sprites/weapon/mp5/reload/1.png b/assets/sprites/weapon/mp5/reload/1.png new file mode 100644 index 0000000..9cddf50 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:559030e6f1fc5dc3b32407a14446c5e02bc4aff07c95ede1030d0a241ea9a1d6 +size 22108 diff --git a/assets/sprites/weapon/mp5/reload/10.png b/assets/sprites/weapon/mp5/reload/10.png new file mode 100644 index 0000000..ad49a4d --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:891e981f16e541063f5dcaf7751ed282bb7f55b47e083f8c0544f148569ef14d +size 18647 diff --git a/assets/sprites/weapon/mp5/reload/11.png b/assets/sprites/weapon/mp5/reload/11.png new file mode 100644 index 0000000..0573849 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/11.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:03402104ed670a25073717e0be3cee6eae0e6ca5f63eb7c94a3744a065aae8b0 +size 17797 diff --git a/assets/sprites/weapon/mp5/reload/12.png b/assets/sprites/weapon/mp5/reload/12.png new file mode 100644 index 0000000..1c9d993 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/12.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81e6c781a19e204dfc916440ac1fb512f511c8640d2d9d60af3597d863ced338 +size 20944 diff --git a/assets/sprites/weapon/mp5/reload/13.png b/assets/sprites/weapon/mp5/reload/13.png new file mode 100644 index 0000000..543f6da --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/13.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28bc613d407dd0fe57c62472901907f16f8b3430e7b737b679cc13c5bde17fe2 +size 16640 diff --git a/assets/sprites/weapon/mp5/reload/14.png b/assets/sprites/weapon/mp5/reload/14.png new file mode 100644 index 0000000..4f97dcb --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/14.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eab4100bf12e4e87be92ee17eb05814345b81e4260899559cfe152e10542139a +size 9097 diff --git a/assets/sprites/weapon/mp5/reload/15.png b/assets/sprites/weapon/mp5/reload/15.png new file mode 100644 index 0000000..1b81cdf --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/15.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e483b528bc71015ecf144039d4a2c2a4dfcd75ace1ec4d1eb87d2762c6217a3 +size 3958 diff --git a/assets/sprites/weapon/mp5/reload/2.png b/assets/sprites/weapon/mp5/reload/2.png new file mode 100644 index 0000000..b9e3800 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e39b7649bb2d525af478a4a35e55347f6e3a95b34d526106d71a5ce54ddd28e6 +size 26888 diff --git a/assets/sprites/weapon/mp5/reload/3.png b/assets/sprites/weapon/mp5/reload/3.png new file mode 100644 index 0000000..f9d8072 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f3addf8a9bad55479ac61f286be7a534a1050006363d5f382a49f311182737c +size 26504 diff --git a/assets/sprites/weapon/mp5/reload/4.png b/assets/sprites/weapon/mp5/reload/4.png new file mode 100644 index 0000000..31510cb --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f41025bcb2b0331435e503ba8745572b70fdc0b5613d01b4272a7b8fb635b6d8 +size 19678 diff --git a/assets/sprites/weapon/mp5/reload/5.png b/assets/sprites/weapon/mp5/reload/5.png new file mode 100644 index 0000000..4d65318 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e68cf4a0a763cb25be50174d50a20542cd0b16c701d895ac1124a6063dbc39f3 +size 15410 diff --git a/assets/sprites/weapon/mp5/reload/6.png b/assets/sprites/weapon/mp5/reload/6.png new file mode 100644 index 0000000..c66f4dd --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/6.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb41f8d2d38825181104b692907972ba941c4f3ee6c249ed06888c62496a025f +size 15211 diff --git a/assets/sprites/weapon/mp5/reload/7.png b/assets/sprites/weapon/mp5/reload/7.png new file mode 100644 index 0000000..a949e72 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/7.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16d63fe417b0c37919763652975bb81f0e99de2dbab2c16ac9764a9bc29649f5 +size 15726 diff --git a/assets/sprites/weapon/mp5/reload/8.png b/assets/sprites/weapon/mp5/reload/8.png new file mode 100644 index 0000000..ba7afd0 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:998dd1f9898c41445dc6a2940a6b69cc3f6898e7be98d9ded51f147e729f9874 +size 15391 diff --git a/assets/sprites/weapon/mp5/reload/9.png b/assets/sprites/weapon/mp5/reload/9.png new file mode 100644 index 0000000..95f2db0 --- /dev/null +++ b/assets/sprites/weapon/mp5/reload/9.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3fb9bceac20122707e4b762a5b5ecad69ff3e013d98c1624cc40fa6e3ce814f2 +size 18526 diff --git a/project.drawio.png b/project.drawio.png index 5b3107a8747d8809426ae04372a09e79379a62fe..08d50f25ffa71b9ab4e4a6ef3f7cedc572abfa9a 100644 GIT binary patch literal 131 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 diff --git a/src/Animation/CMakeLists.txt b/src/Animation/CMakeLists.txt index bd5e601..e2f3ec9 100644 --- a/src/Animation/CMakeLists.txt +++ b/src/Animation/CMakeLists.txt @@ -2,8 +2,8 @@ add_library( animation STATIC src/time_based_single_animation.cpp - src/walk_animation.cpp ) target_include_directories(animation PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) + diff --git a/src/Animation/include/Animation/animator.h b/src/Animation/include/Animation/animator.h deleted file mode 100644 index 0ffe26d..0000000 --- a/src/Animation/include/Animation/animator.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @file animator.h - * @author Bilal Kahraman (kahramannbilal@gmail.com) - * @brief - * @version 0.1 - * @date 2024-08-26 - * - * @copyright Copyright (c) 2024 - * - */ - -#ifndef ANIMATION_INCLUDE_ANIMATION_ANIMATOR_H_ -#define ANIMATION_INCLUDE_ANIMATION_ANIMATOR_H_ - -#include "Animation/animation.h" -#include -#include - -namespace wolfenstein { - -class Animator -{ - public: - Animator(); - ~Animator() = default; - - void AddAnimation(std::shared_ptr animation); - void Update(const double& delta_time); - void Reset(); - int GetCurrentFrame() const; - - private: - std::vector> animations; -}; - -} // namespace wolfenstein - -#endif // ANIMATION_INCLUDE_ANIMATION_ANIMATOR_H_ diff --git a/src/Animation/include/Animation/walk_animation.h b/src/Animation/include/Animation/walk_animation.h deleted file mode 100644 index c2bfae4..0000000 --- a/src/Animation/include/Animation/walk_animation.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file state_based_animation.h - * @author Bilal Kahraman (kahramannbilal@gmail.com) - * @brief - * @version 0.1 - * @date 2024-08-26 - * - * @copyright Copyright (c) 2024 - * - */ - -#ifndef ANIMATION_INCLUDE_ANIMATION_STATE_BASED_ANIMATION_H_ -#define ANIMATION_INCLUDE_ANIMATION_STATE_BASED_ANIMATION_H_ - -#include "Animation/animation.h" -#include -#include - -namespace wolfenstein { - -class WalkAnimation : public IAnimation -{ - public: - WalkAnimation(const std::vector& tex_ids, const double step_size); - ~WalkAnimation() = default; - - void Update(const double& delta_time) override; - void Reset() override; - - int GetCurrentFrame() const override; - - private: - std::vector tex_ids; - int current_frame; - double step_size; - double counter; -}; - -} // namespace wolfenstein - -#endif // ANIMATION_INCLUDE_ANIMATION_STATE_BASED_ANIMATION_H_ diff --git a/src/Animation/src/animator.cpp b/src/Animation/src/animator.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/Animation/src/walk_animation.cpp b/src/Animation/src/walk_animation.cpp deleted file mode 100644 index c9e6889..0000000 --- a/src/Animation/src/walk_animation.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "Animation/walk_animation.h" - -namespace wolfenstein { - -WalkAnimation::WalkAnimation(const std::vector& tex_ids, - const double step_size) - : tex_ids(tex_ids), current_frame(1), step_size(step_size), counter(0) {} - -void WalkAnimation::Update(const double& delta_time) { - counter += delta_time; - if (counter > step_size) { - current_frame = (current_frame + 1) % tex_ids.size(); - counter = 0; - } -} - -void WalkAnimation::Reset() { - current_frame = 1; - counter = 0; -} - -int WalkAnimation::GetCurrentFrame() const { - return tex_ids[current_frame]; -} - -} // namespace wolfenstein diff --git a/src/Characters/CMakeLists.txt b/src/Characters/CMakeLists.txt index 6c54425..0e13dea 100644 --- a/src/Characters/CMakeLists.txt +++ b/src/Characters/CMakeLists.txt @@ -15,6 +15,7 @@ target_link_libraries( collision_manager animation SDL2 - shotgun + weapon + enemy_state ) diff --git a/src/Characters/include/Characters/enemy.h b/src/Characters/include/Characters/enemy.h index 7ced346..f3c4e6c 100644 --- a/src/Characters/include/Characters/enemy.h +++ b/src/Characters/include/Characters/enemy.h @@ -12,21 +12,25 @@ #ifndef CHARACTERS_INCLUDE_ENEMY_H_ #define CHARACTERS_INCLUDE_ENEMY_H_ -#include "Animation/walk_animation.h" #include "Characters/character.h" #include "GameObjects/game_object.h" #include "Math/vector.h" +#include "State/enemy_state.h" +#include namespace wolfenstein { -class Enemy : public ICharacter, public IGameObject +class Enemy : public ICharacter, + public IGameObject, + public std::enable_shared_from_this { public: - explicit Enemy(CharacterConfig config, double width, double height, - WalkAnimation animation); + explicit Enemy(CharacterConfig config, std::shared_ptr> state, + double width, double height); ~Enemy() = default; - + void Init(); void Update(double delta_time) override; + void TransitionTo(std::shared_ptr> state); void SetPose(const vector2d& pose) override; void SetPosition(Position2D position) override; @@ -42,16 +46,17 @@ class Enemy : public ICharacter, public IGameObject void SetNextPose(vector2d pose); private: + Enemy() = default; void Move(double delta_time); Position2D position_; double rotation_speed_; double translation_speed_; - std::string id_; + std::shared_ptr> state_; double width; double height; + std::string id_; vector2d next_pose; - WalkAnimation animation; }; } // namespace wolfenstein diff --git a/src/Characters/include/Characters/player.h b/src/Characters/include/Characters/player.h index f95a53e..ce597c2 100644 --- a/src/Characters/include/Characters/player.h +++ b/src/Characters/include/Characters/player.h @@ -14,7 +14,7 @@ #include "Characters/character.h" #include "GameObjects/game_object.h" -#include "Strike/shotgun.h" +#include "Strike/weapon.h" #include #include @@ -35,15 +35,15 @@ class Player : public ICharacter, public IGameObject void SetPosition(Position2D position) override; Position2D GetPosition() const override; std::string GetId() const override; - int GetTextureId() const override { return shotgun_->GetTextureId(); } - double GetWidth() const override { return width_; } - double GetHeight() const override { return height_; } + int GetTextureId() const override; + double GetWidth() const override; + double GetHeight() const override; void SubscribeToPlayerPosition(std::function subscriber); private: void Move(double delta_time); void Rotate(double delta_time); - void Shoot(); + void ShootAndReload(); Position2D position_; double rotation_speed_; @@ -51,7 +51,7 @@ class Player : public ICharacter, public IGameObject double width_{0.4}; double height_{1.0}; std::string id_; - std::shared_ptr shotgun_; + std::shared_ptr weapon_; std::vector> player_position_subscribers_; }; diff --git a/src/Characters/src/enemy.cpp b/src/Characters/src/enemy.cpp index 2502ca9..e4ca58a 100644 --- a/src/Characters/src/enemy.cpp +++ b/src/Characters/src/enemy.cpp @@ -2,27 +2,33 @@ #include "CollisionManager/collision_manager.h" #include "Math/vector.h" #include "Utility/uuid_generator.h" +#include namespace wolfenstein { -Enemy::Enemy(CharacterConfig config, double width, double height, - WalkAnimation animation) +Enemy::Enemy(CharacterConfig config, std::shared_ptr> state, + double width, double height) : position_(config.initial_position), rotation_speed_(config.rotation_speed), translation_speed_(config.translation_speed), + state_(state), width(width), height(height), - animation(animation) { - id_ = UuidGenerator::GetInstance().GenerateUuid().bytes(); + id_(UuidGenerator::GetInstance().GenerateUuid().bytes()) {} + +void Enemy::Init() { + state_->SetContext(shared_from_this()); +} + +void Enemy::TransitionTo(std::shared_ptr> state) { + state_ = state; + state_->SetContext(shared_from_this()); } void Enemy::Update(double delta_time) { + state_->Update(delta_time); if (next_pose != position_.pose) { Move(delta_time); - animation.Update(delta_time); - } - else { - animation.Reset(); } } @@ -69,7 +75,7 @@ void Enemy::SetNextPose(vector2d pose) { } int Enemy::GetTextureId() const { - return animation.GetCurrentFrame(); + return state_->GetCurrentFrame(); } double Enemy::GetWidth() const { diff --git a/src/Characters/src/player.cpp b/src/Characters/src/player.cpp index 614788c..6ae18b6 100644 --- a/src/Characters/src/player.cpp +++ b/src/Characters/src/player.cpp @@ -11,11 +11,12 @@ Player::Player(CharacterConfig& config) rotation_speed_(config.rotation_speed), translation_speed_(config.translation_speed) { id_ = UuidGenerator::GetInstance().GenerateUuid().bytes(); - shotgun_ = std::make_shared(); + weapon_ = std::make_shared("mp5"); + weapon_->Init(); } void Player::Update(double delta_time) { - Shoot(); + ShootAndReload(); Move(delta_time); Rotate(delta_time); for (auto& subscriber : player_position_subscribers_) { @@ -47,6 +48,16 @@ std::string Player::GetId() const { return id_; } +int Player::GetTextureId() const { + return weapon_->GetTextureId(); +} +double Player::GetWidth() const { + return width_; +} +double Player::GetHeight() const { + return height_; +} + void Player::SubscribeToPlayerPosition( std::function updator) { player_position_subscribers_.push_back(updator); @@ -101,9 +112,14 @@ void Player::Rotate(double delta_time) { } } -void Player::Shoot() { +void Player::ShootAndReload() { if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON_LMASK) { - shotgun_->Attack(); + weapon_->Attack(); + } + // If R is pressed, reload + const Uint8* keystate = SDL_GetKeyboardState(NULL); + if (keystate[SDL_SCANCODE_R]) { + weapon_->Reload(); } } diff --git a/src/Core/CMakeLists.txt b/src/Core/CMakeLists.txt index fedd7a7..98642f6 100644 --- a/src/Core/CMakeLists.txt +++ b/src/Core/CMakeLists.txt @@ -40,4 +40,5 @@ target_link_libraries( SDL2 SDL2_image SDL2_ttf + enemy_state ) diff --git a/src/Core/src/game.cpp b/src/Core/src/game.cpp index c1c9ada..bf98007 100644 --- a/src/Core/src/game.cpp +++ b/src/Core/src/game.cpp @@ -1,16 +1,18 @@ #include "Core/game.h" +// #include "Animation/animator.h" #include "Animation/time_based_single_animation.h" -#include "Animation/walk_animation.h" #include "Characters/enemy.h" #include "GameObjects/dynamic_object.h" #include "GameObjects/static_object.h" #include "Graphics/renderer.h" #include "Math/vector.h" #include "NavigationManager/navigation_manager.h" +#include "State/enemy_state.h" #include "TextureManager/texture_manager.h" #include "TimeManager/time_manager.h" #include #include +#include #include namespace wolfenstein { @@ -53,7 +55,7 @@ void Game::Init() { scene_->SetPlayer(player_); - // PrepareEnemies(); + PrepareEnemies(); PrepareDynamicObjects(); PrepareStaticObjects(); @@ -115,20 +117,15 @@ void Game::Run() { void Game::PrepareEnemies() { auto caco_demon = std::make_shared( - CharacterConfig(Position2D({8, 7}, 1.50), 0.8, 0.4), 0.4, 0.8, - WalkAnimation(TextureManager::GetInstance().GetTextureCollection( - "caco_demon_walk"), - 0.2)); + CharacterConfig(Position2D({13.5, 2.5}, 1.50), 0.8, 0.4), + std::make_shared("caco_demon"), 0.4, 0.8); + auto soldier = std::make_shared( - CharacterConfig(Position2D({9, 7}, 1.50), 0.8, 0.4), 0.3, 0.6, - WalkAnimation( - TextureManager::GetInstance().GetTextureCollection("soldier_walk"), - 0.2)); + CharacterConfig(Position2D({9, 7}, 1.50), 0.8, 0.4), + std::make_shared("soldier"), 0.3, 0.6); auto cyber_demon = std::make_shared( - CharacterConfig(Position2D({23.0, 4}, 1.50), 0.8, 0.4), 0.5, 1.0, - WalkAnimation(TextureManager::GetInstance().GetTextureCollection( - "cyber_demon_walk"), - 0.2)); + CharacterConfig(Position2D({23.0, 4}, 1.50), 0.8, 0.4), + std::make_shared("cyber_demon"), 0.5, 1.0); scene_->AddObject(caco_demon); scene_->AddObject(soldier); scene_->AddObject(cyber_demon); @@ -139,8 +136,6 @@ void Game::PrepareDynamicObjects() { TextureManager::GetInstance().GetTextureCollection("green_light"), 0.1); const auto animation_red_light = TBSAnimation( TextureManager::GetInstance().GetTextureCollection("red_light"), 0.1); - const auto animation_flame = TBSAnimation( - TextureManager::GetInstance().GetTextureCollection("flame"), 0.1); scene_->AddObject(std::make_shared( vector2d(12.1, 8.15), @@ -161,17 +156,11 @@ void Game::PrepareDynamicObjects() { scene_->AddObject(std::make_shared( vector2d(12.1, 10.9), std::make_shared(animation_green_light), 0.2, 0.9)); - scene_->AddObject(std::make_shared( - vector2d(14.0, 1.5), - std::make_shared(animation_flame), 0.2, 0.9)); } -void Game::PrepareStaticObjects() -{ +void Game::PrepareStaticObjects() { scene_->AddObject( std::make_shared(vector2d(14.5, 9), 8, 0.2, 0.5)); - scene_->AddObject( - std::make_shared(vector2d(14.5, 10), 96, 0.2, 0.8)); } } // namespace wolfenstein diff --git a/src/Core/src/scene.cpp b/src/Core/src/scene.cpp index fbc7d79..4de3d3c 100644 --- a/src/Core/src/scene.cpp +++ b/src/Core/src/scene.cpp @@ -7,7 +7,9 @@ namespace wolfenstein { void Scene::AddObject(std::shared_ptr object) { objects.push_back(object); if (object->GetObjectType() == ObjectType::CHARACTER_ENEMY) { - enemies.push_back(std::dynamic_pointer_cast(object)); + auto enemy = std::dynamic_pointer_cast(object); + enemy->Init(); + enemies.push_back(enemy); } } diff --git a/src/Graphics/src/renderer.cpp b/src/Graphics/src/renderer.cpp index bd5443e..22481d6 100644 --- a/src/Graphics/src/renderer.cpp +++ b/src/Graphics/src/renderer.cpp @@ -204,8 +204,13 @@ void Renderer::RenderWeapon(const std::shared_ptr& player_ptr, const auto crosshair_height = crosshair_texture.height; const auto crosshair_width = crosshair_texture.width; SDL_Rect crosshair_src_rect{0, 0, crosshair_width, crosshair_height}; - SDL_Rect crosshair_dest_rect{config_.width / 2 - 20, - config_.height / 2 - 20, 40, 40}; + const double crosshair_ratio = + static_cast(crosshair_height) / crosshair_width; + const int crosshair_width_slice = config_.width / 40; + const int crosshair_height_slice = crosshair_width_slice * crosshair_ratio; + SDL_Rect crosshair_dest_rect{config_.width / 2 - crosshair_width_slice / 2, + config_.height / 2 - crosshair_height_slice / 2, + crosshair_width_slice, crosshair_height_slice}; render_queue.push({6, crosshair_src_rect, crosshair_dest_rect, 0.0}); auto texture_id = player_ptr->GetTextureId(); @@ -213,11 +218,13 @@ void Renderer::RenderWeapon(const std::shared_ptr& player_ptr, TextureManager::GetInstance().GetTexture(texture_id).height; const auto texture_width = TextureManager::GetInstance().GetTexture(texture_id).width; - const auto width_slice = config_.width / 6; - const auto height_slice = config_.height / 3; + const double ratio = static_cast(texture_height) / texture_width; + const int width_slice = config_.width / 1.3; + const int height_slice = width_slice * ratio; SDL_Rect src_rect{0, 0, texture_width, texture_height}; - SDL_Rect dest_rect{3 * width_slice - width_slice / 2, 2 * height_slice, - width_slice, height_slice}; + SDL_Rect dest_rect{config_.width / 2 - width_slice / 2 + 100, + config_.height - height_slice, width_slice, + height_slice}; render_queue.push({texture_id, src_rect, dest_rect, 0.0}); } diff --git a/src/NavigationManager/src/navigation_manager.cpp b/src/NavigationManager/src/navigation_manager.cpp index c5ee549..bd96e79 100644 --- a/src/NavigationManager/src/navigation_manager.cpp +++ b/src/NavigationManager/src/navigation_manager.cpp @@ -16,7 +16,7 @@ NavigationManager& NavigationManager::GetInstance() { void NavigationManager::InitManager(std::shared_ptr map) { map_ = map; - path_planner_ = std::make_shared(0.6, 8); + path_planner_ = std::make_shared(0.6, 4); } //@Note apply caching mechanism later @@ -42,15 +42,16 @@ vector2d NavigationManager::FindPath(Position2D start, Position2D end, std::vector path_vector; path.erase(path.begin()); for (auto node : path) { - path_vector.push_back(FromNode(node) * res); + path_vector.push_back(FromNode(node) * res + vector2d{0.25, 0.25}); } paths_[id] = path_vector; if (path_vector.empty()) { return start.pose; } - auto next = path_vector.front(); path_vector.erase(path_vector.begin()); + auto next = path_vector.front(); + return next; } diff --git a/src/State/CMakeLists.txt b/src/State/CMakeLists.txt new file mode 100644 index 0000000..57f6095 --- /dev/null +++ b/src/State/CMakeLists.txt @@ -0,0 +1,33 @@ +add_library( + enemy_state + STATIC + src/enemy_state.cpp +) +target_include_directories( + enemy_state + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include +) +target_link_libraries( + enemy_state + PUBLIC + character + texture_manager +) + +add_library( + weapon_state + STATIC + src/weapon_state.cpp +) +target_include_directories( + weapon_state + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include +) +target_link_libraries( + weapon_state + PUBLIC + weapon + texture_manager +) \ No newline at end of file diff --git a/src/State/include/State/enemy_state.h b/src/State/include/State/enemy_state.h new file mode 100644 index 0000000..f65d663 --- /dev/null +++ b/src/State/include/State/enemy_state.h @@ -0,0 +1,118 @@ +/** + * @file enemy_state.h + * @author Bilal Kahraman (kahramannbilal@gmail.com) + * @brief + * @version 0.1 + * @date 2024-09-05 + * + * @copyright Copyright (c) 2024 + * + */ + +#ifndef STATE_INCLUDE_STATE_ENEMY_STATE_H_ +#define STATE_INCLUDE_STATE_ENEMY_STATE_H_ + +#include "State/state.h" + +namespace wolfenstein { + +class Enemy; + +class IdleState : public State +{ + public: + IdleState(const std::string bot_name); + ~IdleState(); + + void Update(const double& delta_time) override; + void Reset() override; + int GetCurrentFrame() const override; + + private: + std::string bot_name_; + int current_frame; + double counter; + double interval; + double animation_speed_; + std::vector textures; +}; + +class WalkState : public State +{ + public: + WalkState(const std::string bot_name); + ~WalkState(); + + void Update(const double& delta_time) override; + void Reset() override; + int GetCurrentFrame() const override; + + private: + std::string bot_name_; + int current_frame; + double counter; + double interval; + double animation_speed_; + std::vector textures; +}; + +class AttackState : public State +{ + public: + AttackState(const std::string bot_name); + ~AttackState(); + + void Update(const double& delta_time) override; + void Reset() override; + int GetCurrentFrame() const override; + + private: + std::string bot_name_; + int current_frame; + double counter; + double interval; + double animation_speed_; + std::vector textures; +}; + +class PainState : public State +{ + public: + PainState(const std::string bot_name); + ~PainState(); + + void Update(const double& delta_time) override; + void Reset() override; + int GetCurrentFrame() const override; + + private: + std::string bot_name_; + int current_frame; + double counter; + double interval; + double animation_speed_; + std::vector textures; +}; + +class DeathState : public State +{ + public: + DeathState(const std::string bot_name); + ~DeathState(); + + void Update(const double& delta_time) override; + void Reset() override; + int GetCurrentFrame() const override; + + private: + std::string bot_name_; + int current_frame; + double counter; + double interval; + double animation_speed_; + std::vector textures; +}; + +} // namespace wolfenstein + +#endif // STATE_INCLUDE_STATE_ENEMY_STATE_H_ \ No newline at end of file diff --git a/src/State/include/State/state.h b/src/State/include/State/state.h new file mode 100644 index 0000000..5e59364 --- /dev/null +++ b/src/State/include/State/state.h @@ -0,0 +1,64 @@ +/** + * @file state.h + * @author Bilal Kahraman (kahramannbilal@gmail.com) + * @brief + * @version 0.1 + * @date 2024-09-05 + * + * @copyright Copyright (c) 2024 + * + */ + +#ifndef STATE_INCLUDE_STATE_STATE_H_ +#define STATE_INCLUDE_STATE_STATE_H_ + +#include +#include +#include +#include + +namespace wolfenstein { + +template +class State +{ + public: + virtual ~State() = default; + void SetContext(std::shared_ptr context) { context_ = context; } + virtual void Update(const double& delta_time) = 0; + virtual void Reset() = 0; + virtual int GetCurrentFrame() const = 0; + + protected: + std::shared_ptr context_; + std::unordered_map> + 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> + weapon_data_{{"mp5", + {{"loaded", "mp5_loaded"}, + {"outofammo", "mp5_outofammo"}, + {"reload", "mp5_reload"}}}}; +}; + +} // namespace wolfenstein + +#endif // STATE_INCLUDE_STATE_STATE_H_ diff --git a/src/State/include/State/weapon_state.h b/src/State/include/State/weapon_state.h new file mode 100644 index 0000000..8a184ff --- /dev/null +++ b/src/State/include/State/weapon_state.h @@ -0,0 +1,82 @@ +/** + * @file weapon_state.h + * @author Bilal Kahraman (kahramannbilal@gmail.com) + * @brief + * @version 0.1 + * @date 2024-09-06 + * + * @copyright Copyright (c) 2024 + * + */ + +#ifndef STATE_INCLUDE_STATE_WEAPON_STATE_H_ +#define STATE_INCLUDE_STATE_WEAPON_STATE_H_ + +#include "Animation/time_based_single_animation.h" +#include "State/state.h" +#include + +namespace wolfenstein { + +class Weapon; + +class LoadedState : public State +{ + public: + LoadedState(const std::string weapon_name); + ~LoadedState(); + + void Update(const double& delta_time) override; + void Reset() override; + int GetCurrentFrame() const override; + + private: + void AttackAnimation(); + std::string weapon_name_; + double animation_speed_; + bool cooldown_; + double last_attack_time_; + std::shared_ptr animation_; +}; + +class OutOfAmmoState : public State +{ + public: + OutOfAmmoState(const std::string weapon_name); + ~OutOfAmmoState(); + + void Update(const double& delta_time) override; + void Reset() override; + int GetCurrentFrame() const override; + + private: + void NoAttackAnimation(); + std::string weapon_name_; + double animation_speed_; + bool cooldown_; + double last_attack_time_; + std::shared_ptr animation_; +}; + +class ReloadingState : public State +{ + public: + ReloadingState(const std::string weapon_name); + ~ReloadingState(); + + void Update(const double& delta_time) override; + void Reset() override; + int GetCurrentFrame() const override; + + private: + void ReloadAnimation(); + std::string weapon_name_; + double animation_speed_; + bool cooldown_; + double last_attack_time_; + std::shared_ptr animation_; +}; + +} // namespace wolfenstein + +#endif // STATE_INCLUDE_STATE_WEAPON_STATE_H_ diff --git a/src/State/src/enemy_state.cpp b/src/State/src/enemy_state.cpp new file mode 100644 index 0000000..ba60860 --- /dev/null +++ b/src/State/src/enemy_state.cpp @@ -0,0 +1,157 @@ +#include "State/enemy_state.h" +#include "Characters/enemy.h" +#include "TextureManager/texture_manager.h" +#include +namespace wolfenstein { + +IdleState::IdleState(const std::string bot_name) + : bot_name_(bot_name), current_frame(0), counter(0), interval(0) { + animation_speed_ = 0.3; + textures = TextureManager::GetInstance().GetTextureCollection( + enemy_data_[bot_name_]["idle"]); +} + +IdleState::~IdleState() {} + +void IdleState::Update(const double& delta_time) { + counter += delta_time; + if (counter > animation_speed_) { + current_frame = (current_frame + 1) % textures.size(); + counter = 0; + } + interval += delta_time; + if (interval > 5) { + context_->TransitionTo(std::make_shared(bot_name_)); + } +} + +void IdleState::Reset() { + current_frame = 0; + counter = 0; +} + +int IdleState::GetCurrentFrame() const { + return textures[current_frame]; +} + +WalkState::WalkState(const std::string bot_name) + : bot_name_(bot_name), current_frame(0), counter(0), interval(0) { + animation_speed_ = 0.3; + textures = TextureManager::GetInstance().GetTextureCollection( + enemy_data_[bot_name_]["walk"]); +} + +WalkState::~WalkState() {} + +void WalkState::Update(const double& delta_time) { + counter += delta_time; + if (counter > animation_speed_) { + current_frame = (current_frame + 1) % textures.size(); + counter = 0; + } + interval += delta_time; + if (interval > 5) { + context_->TransitionTo(std::make_shared(bot_name_)); + } +} + +void WalkState::Reset() { + current_frame = 0; + counter = 0; +} + +int WalkState::GetCurrentFrame() const { + return textures[current_frame]; +} + +AttackState::AttackState(const std::string bot_name) + : bot_name_(bot_name), current_frame(0), counter(0), interval(0) { + animation_speed_ = 0.3; + textures = TextureManager::GetInstance().GetTextureCollection( + enemy_data_[bot_name_]["attack"]); +} + +AttackState::~AttackState() {} + +void AttackState::Update(const double& delta_time) { + counter += delta_time; + if (counter > animation_speed_) { + current_frame = (current_frame + 1) % textures.size(); + counter = 0; + } + interval += delta_time; + if (interval > 5) { + context_->TransitionTo(std::make_shared(bot_name_)); + } +} + +void AttackState::Reset() { + current_frame = 0; + counter = 0; +} + +int AttackState::GetCurrentFrame() const { + return textures[current_frame]; +} + +PainState::PainState(const std::string bot_name) + : bot_name_(bot_name), current_frame(0), counter(0), interval(0) { + animation_speed_ = 0.3; + textures = TextureManager::GetInstance().GetTextureCollection( + enemy_data_[bot_name_]["pain"]); +} + +PainState::~PainState() {} + +void PainState::Update(const double& delta_time) { + counter += delta_time; + if (counter > animation_speed_) { + current_frame = (current_frame + 1) % textures.size(); + counter = 0; + } + interval += delta_time; + if (interval > 5) { + context_->TransitionTo(std::make_shared(bot_name_)); + } +} + +void PainState::Reset() { + current_frame = 0; + counter = 0; +} + +int PainState::GetCurrentFrame() const { + return textures[current_frame]; +} + +DeathState::DeathState(const std::string bot_name) + : bot_name_(bot_name), current_frame(0), counter(0), interval(0) { + animation_speed_ = 0.3; + textures = TextureManager::GetInstance().GetTextureCollection( + enemy_data_[bot_name_]["death"]); +} + +DeathState::~DeathState() {} + +void DeathState::Update(const double& delta_time) { + counter += delta_time; + if (counter > animation_speed_) { + current_frame = (current_frame + 1) % textures.size(); + counter = 0; + } + interval += delta_time; + if (interval > 5) { + context_->TransitionTo(std::make_shared(bot_name_)); + } +} + +void DeathState::Reset() { + current_frame = 0; + counter = 0; +} + +int DeathState::GetCurrentFrame() const { + return textures[current_frame]; +} + +} // namespace wolfenstein diff --git a/src/State/src/weapon_state.cpp b/src/State/src/weapon_state.cpp new file mode 100644 index 0000000..8e9bd89 --- /dev/null +++ b/src/State/src/weapon_state.cpp @@ -0,0 +1,142 @@ +#include "State/weapon_state.h" +#include "Strike/weapon.h" +#include "TextureManager/texture_manager.h" +#include "TimeManager/time_manager.h" +#include +#include +#include + +namespace wolfenstein { + +LoadedState::LoadedState(const std::string weapon_name) + : weapon_name_(weapon_name), cooldown_(false), last_attack_time_(0) { + animation_speed_ = 0.3; + auto textures = TextureManager::GetInstance().GetTextureCollection( + weapon_data_[weapon_name_]["loaded"]); + animation_ = std::make_shared( + textures, animation_speed_ / textures.size()); +} + +LoadedState::~LoadedState() {} + +void LoadedState::Update(const double& delta_time) { + if (!cooldown_) { + cooldown_ = true; + last_attack_time_ = TimeManager::GetInstance().GetCurrentTime(); + std::thread attack_thread(&LoadedState::AttackAnimation, this); + attack_thread.detach(); + } +} + +// BUG: Segmentation fault if game closes while the thread is running +void LoadedState::AttackAnimation() { + auto attack_time = last_attack_time_; + auto current_time = TimeManager::GetInstance().GetCurrentTime(); + while (current_time - last_attack_time_ < animation_speed_) { + auto time_elapsed = current_time - attack_time; + animation_->Update(time_elapsed); + attack_time = current_time; + current_time = TimeManager::GetInstance().GetCurrentTime(); + } + animation_->Reset(); + context_->decreaseAmmo(); + cooldown_ = false; + if (context_->getAmmo() == 0) { + context_->TransitionTo(std::make_shared(weapon_name_)); + } +} + +void LoadedState::Reset() { + animation_->Reset(); +} + +int LoadedState::GetCurrentFrame() const { + return animation_->GetCurrentFrame(); +} + +OutOfAmmoState::OutOfAmmoState(const std::string weapon_name) + : weapon_name_(weapon_name), cooldown_(false), last_attack_time_(0) { + animation_speed_ = 0.2; + auto textures = TextureManager::GetInstance().GetTextureCollection( + weapon_data_[weapon_name_]["outofammo"]); + animation_ = std::make_shared( + textures, animation_speed_ / textures.size()); +} + +OutOfAmmoState::~OutOfAmmoState() {} + +void OutOfAmmoState::Update(const double& delta_time) { + + if (!cooldown_) { + cooldown_ = true; + last_attack_time_ = TimeManager::GetInstance().GetCurrentTime(); + std::thread attack_thread(&OutOfAmmoState::NoAttackAnimation, this); + attack_thread.detach(); + } +} + +// BUG: Segmentation fault if game closes while the thread is running +void OutOfAmmoState::NoAttackAnimation() { + auto attack_time = last_attack_time_; + auto current_time = TimeManager::GetInstance().GetCurrentTime(); + while (current_time - last_attack_time_ < animation_speed_) { + auto time_elapsed = current_time - attack_time; + animation_->Update(time_elapsed); + attack_time = current_time; + current_time = TimeManager::GetInstance().GetCurrentTime(); + } + animation_->Reset(); + cooldown_ = false; +} + +void OutOfAmmoState::Reset() { + animation_->Reset(); +} + +int OutOfAmmoState::GetCurrentFrame() const { + return animation_->GetCurrentFrame(); +} + +ReloadingState::ReloadingState(const std::string weapon_name) + : weapon_name_(weapon_name), cooldown_(false), last_attack_time_(0) { + animation_speed_ = 1.0; + auto textures = TextureManager::GetInstance().GetTextureCollection( + weapon_data_[weapon_name_]["reload"]); + animation_ = std::make_shared( + textures, animation_speed_ / textures.size()); +} + +ReloadingState::~ReloadingState() {} + +void ReloadingState::Update(const double& delta_time) { + if (!cooldown_) { + cooldown_ = true; + last_attack_time_ = TimeManager::GetInstance().GetCurrentTime(); + std::thread attack_thread(&ReloadingState::ReloadAnimation, this); + attack_thread.detach(); + } +} + +// BUG: Segmentation fault if game closes while the thread is running +void ReloadingState::ReloadAnimation() { + auto attack_time = last_attack_time_; + auto current_time = TimeManager::GetInstance().GetCurrentTime(); + while (current_time - last_attack_time_ < animation_speed_) { + auto time_elapsed = current_time - attack_time; + animation_->Update(time_elapsed); + attack_time = current_time; + current_time = TimeManager::GetInstance().GetCurrentTime(); + } + context_->reloadFinished(); + context_->TransitionTo(std::make_shared(weapon_name_)); +} + +void ReloadingState::Reset() { + animation_->Reset(); +} + +int ReloadingState::GetCurrentFrame() const { + return animation_->GetCurrentFrame(); +} + +} // namespace wolfenstein diff --git a/src/Strike/CMakeLists.txt b/src/Strike/CMakeLists.txt index e814080..0a93d66 100644 --- a/src/Strike/CMakeLists.txt +++ b/src/Strike/CMakeLists.txt @@ -1,16 +1,17 @@ add_library( - shotgun + weapon STATIC - src/shotgun.cpp + src/weapon.cpp ) -target_include_directories(shotgun PUBLIC +target_include_directories(weapon PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) target_link_libraries( - shotgun + weapon PUBLIC animation time_manager texture_manager + weapon_state ) diff --git a/src/Strike/include/Strike/shotgun.h b/src/Strike/include/Strike/shotgun.h deleted file mode 100644 index 1fbfb6d..0000000 --- a/src/Strike/include/Strike/shotgun.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file shotgun.h - * @author Bilal Kahraman (kahramannbilal@gmail.com) - * @brief - * @version 0.1 - * @date 2024-08-29 - * - * @copyright Copyright (c) 2024 - * - */ - -#ifndef STRIKE_INCLUDE_STRIKE_SHOTGUN_H -#define STRIKE_INCLUDE_STRIKE_SHOTGUN_H - -#include "Animation/time_based_single_animation.h" -#include "Strike/weapon.h" -#include - -namespace wolfenstein { - -class Shotgun : public IWeapon -{ - public: - Shotgun(); - ~Shotgun() = default; - - void Attack() override; - int GetTextureId() const; - - private: - void AttackAnimation(); - double attack_speed_; - double attack_damage_; - std::shared_ptr animation_; - - bool cooldown_; - double last_attack_time_; -}; - -} // namespace wolfenstein - -#endif // STRIKE_INCLUDE_STRIKE_SHOTGUN_H diff --git a/src/Strike/include/Strike/weapon.h b/src/Strike/include/Strike/weapon.h index 9ca57c0..84d1a89 100644 --- a/src/Strike/include/Strike/weapon.h +++ b/src/Strike/include/Strike/weapon.h @@ -12,14 +12,42 @@ #ifndef STRIKE_INCLUDE_STRIKE_WEAPON_H #define STRIKE_INCLUDE_STRIKE_WEAPON_H +#include "State/weapon_state.h" +#include "Strike/strike.h" +#include +#include namespace wolfenstein { -class IWeapon +struct WeaponConfig +{ + std::string weapon_name; + double attack_speed; + double attack_damage; + size_t ammo_capacity; +}; + +class Weapon : public IStrike, public std::enable_shared_from_this { public: - virtual ~IWeapon() = default; + Weapon(std::string weapon_name); + ~Weapon(); + void Init(); + + void Attack() override; + int GetTextureId() const; + void TransitionTo(std::shared_ptr> state); + void decreaseAmmo(); + size_t getAmmo() const; + std::string getWeaponName() const; + void Reload(); + void reloadFinished(); + + private: + WeaponConfig weapon_config_; - virtual void Attack() = 0; + bool cooldown_; + bool reloading_; + std::shared_ptr> state_; }; } // namespace wolfenstein diff --git a/src/Strike/src/shotgun.cpp b/src/Strike/src/shotgun.cpp deleted file mode 100644 index 934219e..0000000 --- a/src/Strike/src/shotgun.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "Strike/shotgun.h" -#include "TextureManager/texture_manager.h" -#include "TimeManager/time_manager.h" -#include -#include - -namespace wolfenstein { - -Shotgun::Shotgun() : attack_speed_(0.7), attack_damage_(10) { - auto tex_ids = - TextureManager::GetInstance().GetTextureCollection("shotgun"); - animation_ = - std::make_shared(tex_ids, attack_speed_ / tex_ids.size()); - cooldown_ = false; -} - -int Shotgun::GetTextureId() const { - return animation_->GetCurrentFrame(); -} - -void Shotgun::Attack() { - // If the weapon is not in cooldown, attack and set the cooldown true - if (!cooldown_) { - cooldown_ = true; - last_attack_time_ = TimeManager::GetInstance().GetCurrentTime(); - - // Create a new thread to play the attack animation - // Use attack speed to calculate the time to wait - std::thread attack_thread(&Shotgun::AttackAnimation, this); - attack_thread.detach(); - } -} -// BUG: Segmentation fault if game closes while the thread is running -void Shotgun::AttackAnimation() { - auto attack_time = last_attack_time_; - auto current_time = TimeManager::GetInstance().GetCurrentTime(); - while (current_time - last_attack_time_ < attack_speed_) { - auto time_elapsed = current_time - attack_time; - animation_->Update(time_elapsed); - attack_time = current_time; - current_time = TimeManager::GetInstance().GetCurrentTime(); - } - animation_->Reset(); - cooldown_ = false; -} - -} // namespace wolfenstein diff --git a/src/Strike/src/weapon.cpp b/src/Strike/src/weapon.cpp new file mode 100644 index 0000000..52e1a85 --- /dev/null +++ b/src/Strike/src/weapon.cpp @@ -0,0 +1,70 @@ +#include "Strike/weapon.h" +#include "State/weapon_state.h" +#include + +namespace wolfenstein { + +namespace { +auto GetWeaponConfig = [](const std::string& weapon_name) -> WeaponConfig { + if (weapon_name == "mp5") { + return {"mp5", 0.2, 10, 10}; + } + else { + return {"Doesn't exist", -1, -1, 0}; + } +}; +} // namespace + +Weapon::Weapon(std::string weapon_name) + : weapon_config_(GetWeaponConfig(weapon_name)), + cooldown_(false), + reloading_(false) { + state_ = std::make_shared(weapon_config_.weapon_name); +} + +Weapon::~Weapon() {} + +void Weapon::Init() { + state_->SetContext(shared_from_this()); +} + +void Weapon::Attack() { + state_->Update(0.0); +} + +int Weapon::GetTextureId() const { + return state_->GetCurrentFrame(); +} + +void Weapon::TransitionTo(std::shared_ptr> state) { + state_ = state; + state_->SetContext(shared_from_this()); +} + +void Weapon::decreaseAmmo() { + weapon_config_.ammo_capacity--; +} + +size_t Weapon::getAmmo() const { + return weapon_config_.ammo_capacity; +} + +std::string Weapon::getWeaponName() const { + return weapon_config_.weapon_name; +} + +void Weapon::Reload() { + if (!reloading_) { + reloading_ = true; + TransitionTo( + std::make_shared(weapon_config_.weapon_name)); + state_->Update(0.0); + } +} + +void Weapon::reloadFinished() { + reloading_ = false; + weapon_config_.ammo_capacity = 10; +} + +} // namespace wolfenstein \ No newline at end of file diff --git a/src/TextureManager/include/TextureManager/texture_manager.h b/src/TextureManager/include/TextureManager/texture_manager.h index 6a1eec0..6919151 100644 --- a/src/TextureManager/include/TextureManager/texture_manager.h +++ b/src/TextureManager/include/TextureManager/texture_manager.h @@ -13,6 +13,7 @@ #define TEXTURE_MANAGER_INCLUDE_TEXTURE_MANAGER_H #include +#include #include #include #include @@ -45,11 +46,16 @@ class TextureManager private: TextureManager() = default; + void LoadStaticTextures(); + void LoadSpriteTextures(); + void LoadNpcTextures(); + void LoadWeaponTextures(); static TextureManager* instance_; std::unordered_map textures_; std::unordered_map> texture_collections_; SDL_Renderer* renderer_; + size_t texture_count_; }; } // namespace wolfenstein diff --git a/src/TextureManager/src/texture_manager.cpp b/src/TextureManager/src/texture_manager.cpp index 5b981c4..5f988bc 100644 --- a/src/TextureManager/src/texture_manager.cpp +++ b/src/TextureManager/src/texture_manager.cpp @@ -15,7 +15,33 @@ TextureManager& TextureManager::GetInstance() { void TextureManager::InitManager(SDL_Renderer* renderer) { renderer_ = renderer; + texture_count_ = 0; + LoadStaticTextures(); + LoadSpriteTextures(); + LoadNpcTextures(); + LoadWeaponTextures(); +} + +void TextureManager::LoadTexture(uint16_t texture_id, + const std::string& texture_path) { + Texture texture; + texture.texture = IMG_LoadTexture(renderer_, texture_path.c_str()); + SDL_QueryTexture(texture.texture, nullptr, nullptr, &texture.width, + &texture.height); + textures_[texture_id] = texture; +} + +Texture TextureManager::GetTexture(uint16_t texture_id) { + return textures_[texture_id]; +} + +std::vector TextureManager::GetTextureCollection( + const std::string& collection_name) { + return texture_collections_[collection_name]; +} + +void TextureManager::LoadStaticTextures() { // Static textures std::string texture_path = std::string(RESOURCE_DIR) + "textures/"; LoadTexture(0, texture_path + "sky.png"); @@ -26,8 +52,9 @@ void TextureManager::InitManager(SDL_Renderer* renderer) { LoadTexture(5, texture_path + "5.png"); LoadTexture(6, texture_path + "crosshair.png"); LoadTexture(7, texture_path + "solid_black.png"); - LoadTexture(96, texture_path + "col1a0.png"); +} +void TextureManager::LoadSpriteTextures() { // Static sprites std::string sprite_path = std::string(RESOURCE_DIR) + "sprites/"; LoadTexture(8, sprite_path + "static_sprites/candlebra.png"); @@ -43,12 +70,9 @@ void TextureManager::InitManager(SDL_Renderer* renderer) { LoadTexture(15, sprite_path + "animated_sprites/red_light/2.png"); LoadTexture(16, sprite_path + "animated_sprites/red_light/3.png"); texture_collections_["red_light"] = {13, 14, 15, 16}; - LoadTexture(97, sprite_path + "animated_sprites/flame/0.png"); - LoadTexture(98, sprite_path + "animated_sprites/flame/1.png"); - LoadTexture(99, sprite_path + "animated_sprites/flame/2.png"); - LoadTexture(100, sprite_path + "animated_sprites/flame/3.png"); - texture_collections_["flame"] = {97, 98, 99, 100}; +} +void TextureManager::LoadNpcTextures() { // Npc sprites std::string npc_path = std::string(RESOURCE_DIR) + "sprites/npc/"; // Caco demon Attack @@ -158,33 +182,45 @@ void TextureManager::InitManager(SDL_Renderer* renderer) { LoadTexture(88, npc_path + "soldier/walk/2.png"); LoadTexture(89, npc_path + "soldier/walk/3.png"); texture_collections_["soldier_walk"] = {86, 87, 88, 89}; - // Weapon sprites - std::string weapon_path = std::string(RESOURCE_DIR) + "sprites/weapon/"; - LoadTexture(90, weapon_path + "shotgun/0.png"); - LoadTexture(91, weapon_path + "shotgun/1.png"); - LoadTexture(92, weapon_path + "shotgun/2.png"); - LoadTexture(93, weapon_path + "shotgun/3.png"); - LoadTexture(94, weapon_path + "shotgun/4.png"); - LoadTexture(95, weapon_path + "shotgun/5.png"); - texture_collections_["shotgun"] = {90, 91, 92, 93, 94, 95}; } -void TextureManager::LoadTexture(uint16_t texture_id, - const std::string& texture_path) { - Texture texture; - texture.texture = IMG_LoadTexture(renderer_, texture_path.c_str()); - SDL_QueryTexture(texture.texture, nullptr, nullptr, &texture.width, - &texture.height); - textures_[texture_id] = texture; -} - -Texture TextureManager::GetTexture(uint16_t texture_id) { - return textures_[texture_id]; -} - -std::vector TextureManager::GetTextureCollection( - const std::string& collection_name) { - return texture_collections_[collection_name]; +void TextureManager::LoadWeaponTextures() { + const auto weapon_path = std::string(RESOURCE_DIR) + "sprites/weapon/"; + // MP5 sprites + // Loaded + LoadTexture(90, weapon_path + "/mp5/loaded/" + "0.png"); + LoadTexture(91, weapon_path + "/mp5/loaded/" + "1.png"); + LoadTexture(92, weapon_path + "/mp5/loaded/" + "2.png"); + LoadTexture(93, weapon_path + "/mp5/loaded/" + "3.png"); + LoadTexture(94, weapon_path + "/mp5/loaded/" + "4.png"); + LoadTexture(95, weapon_path + "/mp5/loaded/" + "5.png"); + texture_collections_["mp5_loaded"] = {90, 91, 92, 93, 94, 95}; + // outofammo + LoadTexture(96, weapon_path + "/mp5/outofammo/" + "0.png"); + LoadTexture(97, weapon_path + "/mp5/outofammo/" + "1.png"); + LoadTexture(98, weapon_path + "/mp5/outofammo/" + "2.png"); + LoadTexture(99, weapon_path + "/mp5/outofammo/" + "3.png"); + texture_collections_["mp5_outofammo"] = {96, 97, 98, 99}; + // reload + LoadTexture(100, weapon_path + "/mp5/reload/" + "0.png"); + LoadTexture(101, weapon_path + "/mp5/reload/" + "1.png"); + LoadTexture(102, weapon_path + "/mp5/reload/" + "2.png"); + LoadTexture(103, weapon_path + "/mp5/reload/" + "3.png"); + LoadTexture(104, weapon_path + "/mp5/reload/" + "4.png"); + LoadTexture(105, weapon_path + "/mp5/reload/" + "5.png"); + LoadTexture(106, weapon_path + "/mp5/reload/" + "6.png"); + LoadTexture(107, weapon_path + "/mp5/reload/" + "7.png"); + LoadTexture(108, weapon_path + "/mp5/reload/" + "8.png"); + LoadTexture(109, weapon_path + "/mp5/reload/" + "9.png"); + LoadTexture(110, weapon_path + "/mp5/reload/" + "10.png"); + LoadTexture(111, weapon_path + "/mp5/reload/" + "11.png"); + LoadTexture(112, weapon_path + "/mp5/reload/" + "12.png"); + LoadTexture(113, weapon_path + "/mp5/reload/" + "13.png"); + LoadTexture(114, weapon_path + "/mp5/reload/" + "14.png"); + LoadTexture(115, weapon_path + "/mp5/reload/" + "15.png"); + texture_collections_["mp5_reload"] = {100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115}; } } // namespace wolfenstein