From c7f076682044496f914f0bd1d22f2d68ac913bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9au?= <theau.baton@etu.univ-amu.fr> Date: Mon, 20 Jan 2025 20:05:25 +0100 Subject: [PATCH] Start event system --- source/game/Game.cpp | 21 +++++----- source/game/back/GameObject.hpp | 22 ++++++++++- source/game/back/message/Behavior.cpp | 18 +++++++++ source/game/back/message/Behavior.hpp | 29 ++++++++++++++ source/game/back/message/StatsAlterator.cpp | 31 +++++++++++++++ source/game/back/message/StatsAlterator.hpp | 21 ++++++++++ source/game/back/object/Enemy.cpp | 39 ++++++++++++++++--- source/game/back/object/Enemy.hpp | 13 +++++-- source/game/back/object/Level.cpp | 20 ++++++++-- source/game/back/object/Level.hpp | 16 +++++--- source/game/back/object/Player.cpp | 37 +++++++++++++++--- source/game/back/object/Player.hpp | 13 +++++-- source/kernel/back/component/Physical.hpp | 4 +- source/kernel/front/Kernel.cpp | 19 +++++++++ source/kernel/front/Kernel.hpp | 3 ++ .../kernel/front/component/physic/Fixed.cpp | 4 +- .../kernel/front/component/physic/Fixed.hpp | 2 +- .../front/component/physic/FixedArray.cpp | 4 +- .../front/component/physic/FixedArray.hpp | 2 +- .../kernel/front/component/physic/Movable.cpp | 4 +- .../kernel/front/component/physic/Movable.hpp | 2 +- .../kernel/front/resolver/PhysicResolver.cpp | 4 +- 22 files changed, 277 insertions(+), 51 deletions(-) create mode 100644 source/game/back/message/Behavior.cpp create mode 100644 source/game/back/message/Behavior.hpp create mode 100644 source/game/back/message/StatsAlterator.cpp create mode 100644 source/game/back/message/StatsAlterator.hpp diff --git a/source/game/Game.cpp b/source/game/Game.cpp index badff2f..0b838bb 100644 --- a/source/game/Game.cpp +++ b/source/game/Game.cpp @@ -5,6 +5,7 @@ #include <game/back/object/Player.hpp> #include <game/back/object/Enemy.hpp> +#include <game/back/object/Level.hpp> #include <game/object/Test.hpp> #include <game/utility/FrameCouter.hpp> @@ -28,25 +29,25 @@ namespace megu::game { Player player(16, 16, 16, 16, path); Enemy enemy(64, 64, 16, 16, path); - - player.setup(kernel); - enemy.setup(kernel); - std::cout << "..." << std::endl; + Level level("STZ"); + level.add(&player); + level.add(&enemy); + - player.apply(kernel); - enemy.apply(kernel); + player.setup(kernel, level); + player.apply(kernel); - //kernel.remove(&object); + enemy.setup(kernel, level); + enemy.apply(kernel); + + std::cout << "..." << std::endl; while(window.isOpen()) { counter.count(Window::Time()); window.pollEvents(); kernel.step(); } - - player.destroy(kernel); - enemy.destroy(kernel); } catch(std::exception & error) { std::cerr << "[Error] : " << error.what() << std::endl; diff --git a/source/game/back/GameObject.hpp b/source/game/back/GameObject.hpp index 29ec8a7..d587ea1 100644 --- a/source/game/back/GameObject.hpp +++ b/source/game/back/GameObject.hpp @@ -1,12 +1,30 @@ #pragma once #include <kernel/front/Kernel.hpp> +#include <game/back/message/Behavior.hpp> namespace megu::game { + class Level; + class GameObject { public: - virtual void setup(kernel::Kernel &) = 0; - virtual void destroy(kernel::Kernel &) = 0; + virtual void setup(kernel::Kernel &, Level &) = 0; + virtual void destroy(kernel::Kernel &, Level &) = 0; virtual void apply(kernel::Kernel &) = 0; }; + + class GameProps : public GameObject { + public: + GameProps(kernel::Prop * prop) + : _props(prop) {} + + virtual void on(const Behavior &) = 0; + virtual std::optional<Behavior> on() const = 0; + + inline kernel::Prop * get() {return this->_props;} + + private: + kernel::Prop * _props; + + }; } \ No newline at end of file diff --git a/source/game/back/message/Behavior.cpp b/source/game/back/message/Behavior.cpp new file mode 100644 index 0000000..8fe8d2e --- /dev/null +++ b/source/game/back/message/Behavior.cpp @@ -0,0 +1,18 @@ +#include "Behavior.hpp" + +namespace megu::game { + Behavior::Behavior(const kernel::Prop & author, uint32_t type) + : _type(type), _stats(author) {} + + uint32_t Behavior::get(uint32_t key) const { + return this->_stats.get(key); + } + + void Behavior::set(uint32_t key, uint32_t value) { + this->_stats.set(key, value); + } + + uint32_t Behavior::operator&(const uint32_t & type) const { + return this->_type & type; + } +} \ No newline at end of file diff --git a/source/game/back/message/Behavior.hpp b/source/game/back/message/Behavior.hpp new file mode 100644 index 0000000..6a6dce2 --- /dev/null +++ b/source/game/back/message/Behavior.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "StatsAlterator.hpp" + +namespace megu::game { + class Behavior { + public: + enum Type : uint32_t { + SOLID = 1, + DAMAGE = 2, + }; + + Behavior() = delete; + Behavior(const kernel::Prop &, uint32_t); + + uint32_t get(uint32_t) const; + void set(uint32_t, uint32_t); + + + uint32_t operator&(const uint32_t &) const; + + private: + uint32_t _type; + StatsAlterator _stats; + }; +} + + + \ No newline at end of file diff --git a/source/game/back/message/StatsAlterator.cpp b/source/game/back/message/StatsAlterator.cpp new file mode 100644 index 0000000..4ea9589 --- /dev/null +++ b/source/game/back/message/StatsAlterator.cpp @@ -0,0 +1,31 @@ +#include "StatsAlterator.hpp" + +namespace megu::game { + StatsAlterator::StatsAlterator(const kernel::Prop & author) + : _author(author) {} + + uint32_t StatsAlterator::get(uint32_t key) const { + if(this->_stats.contains(key)) { + return this->_stats.at(key); + } + return 0; + } + + void StatsAlterator::set(uint32_t key, uint32_t value) { + this->_stats[key] = value; + } + + const uint32_t & StatsAlterator::operator[](const uint32_t & key) const { + if(this->_stats.contains(key)) { + return this->_stats.at(key); + } + throw std::runtime_error("Cannot get stats value"); + } + + uint32_t & StatsAlterator::operator[](const uint32_t & key) { + if(this->_stats.contains(key)) { + return this->_stats.at(key); + } + throw std::runtime_error("Cannot get stats value"); + } +} \ No newline at end of file diff --git a/source/game/back/message/StatsAlterator.hpp b/source/game/back/message/StatsAlterator.hpp new file mode 100644 index 0000000..f8ceaf5 --- /dev/null +++ b/source/game/back/message/StatsAlterator.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include <kernel/front/props/Props.hpp> + +namespace megu::game { + class StatsAlterator { + public: + StatsAlterator() = delete; + StatsAlterator(const kernel::Prop &); + + uint32_t get(uint32_t) const; + void set(uint32_t, uint32_t); + + const uint32_t & operator[](const uint32_t &) const; + uint32_t & operator[](const uint32_t &); + + private: + std::map<uint32_t, uint32_t> _stats; + const kernel::Prop & _author; + }; +} \ No newline at end of file diff --git a/source/game/back/object/Enemy.cpp b/source/game/back/object/Enemy.cpp index f635637..b8f416a 100644 --- a/source/game/back/object/Enemy.cpp +++ b/source/game/back/object/Enemy.cpp @@ -4,7 +4,7 @@ namespace megu::game { Enemy::Enemy(float x, float y, float w, float h, std::filesystem::path & path) - : kernel::PropsDynamic(this->_sprite, this->_movable), _sprite(path), _movable(x, y, w, h) { + : kernel::PropsDynamic(this->_sprite, this->_movable), GameProps(this), _sprite(path), _movable(x, y, w, h) { this->_sprite.setPosition({x, y}); } @@ -13,21 +13,48 @@ namespace megu::game { this->_movable.move(x, y); } - void Enemy::setup(kernel::Kernel &) { + void Enemy::setup(kernel::Kernel & kernel, Level & level) { this->_sprite.setFrame({0.f, 0.f, 51.f, 98.f}); this->_sprite.setSize({51.f, 98.f}); - this->_movable.setCollideLambda([this](kernel::Kernel & kernel, const kernel::PhysicEngine &, const megu::kernel::Physical<kernel::PhysicEngine> &, double) { - std::cout << "Enemy Collide !" << std::endl; - kernel.remove(this); + this->_movable.setCollideLambda([this, &level](kernel::Kernel &, kernel::PhysicEngine &, Identifiable & id, kernel::Physical<kernel::PhysicEngine> & comp, double) { + auto event = level.get(id)->on(); + if(event.has_value()) { + this->on(event.value()); + } }); } - void Enemy::destroy(kernel::Kernel &) { + void Enemy::on(const Behavior & event) { + if(event & Behavior::Type::SOLID) { + this->onSolide(event); + } + + if(event & Behavior::Type::DAMAGE) { + this->onDamage(event); + } + } + + std::optional<Behavior> Enemy::on() const { + Behavior b(*this, Behavior::DAMAGE); + b.set(0, 10); + + return b; + } + + void Enemy::destroy(kernel::Kernel & kernel, Level & level) { } void Enemy::apply(kernel::Kernel & kernel) { kernel.add(this); } + + void Enemy::onDamage(const Behavior &) { + std::cout << "Enemy Got Damage !" << std::endl; + } + + void Enemy::onSolide(const Behavior &) { + std::cout << "Enemy Got Solide !" << std::endl; + } } \ No newline at end of file diff --git a/source/game/back/object/Enemy.hpp b/source/game/back/object/Enemy.hpp index f3d240d..7de2824 100644 --- a/source/game/back/object/Enemy.hpp +++ b/source/game/back/object/Enemy.hpp @@ -2,19 +2,26 @@ #include <game/back/GameObject.hpp> #include <kernel/front/props/PropsDynamic.hpp> +#include <game/back/object/Level.hpp> namespace megu::game { - class Enemy : public kernel::PropsDynamic, public GameObject { + class Enemy : public kernel::PropsDynamic, public GameProps { public: Enemy(float, float, float, float, std::filesystem::path &); void move(float, float); - void setup(kernel::Kernel &) override; - void destroy(kernel::Kernel &) override; + void setup(kernel::Kernel &, Level &) override; + void destroy(kernel::Kernel &, Level &) override; void apply(kernel::Kernel &) override; + void on(const Behavior &) override; + std::optional<Behavior> on() const override; + + void onDamage(const Behavior &); + void onSolide(const Behavior &); + private: kernel::Sprite _sprite; kernel::Movable _movable; diff --git a/source/game/back/object/Level.cpp b/source/game/back/object/Level.cpp index 844932b..8dc9f55 100644 --- a/source/game/back/object/Level.cpp +++ b/source/game/back/object/Level.cpp @@ -2,17 +2,29 @@ namespace megu::game { Level::Level(const std::string & name) - : _name(name) {} + : _name(name) {} + + GameProps * Level::get(Identifiable & id) const { + return this->_objecs.at(id.id()); + } + + void Level::add(GameProps * prop) { + this->_objecs.insert({prop->get()->id(), prop}); + } void Level::apply(kernel::Kernel & kernel) { for(auto & [id, prop] : this->_objecs) { - kernel.add(prop); + kernel.add(prop->get()); } } - void Level::destroy(kernel::Kernel & kernel) { + void Level::setup(kernel::Kernel & kernel, Level & level) { + + } + + void Level::destroy(kernel::Kernel & kernel, Level & level) { for(auto & [id, prop] : this->_objecs) { - kernel.remove(prop); + kernel.remove(prop->get()); } } } \ No newline at end of file diff --git a/source/game/back/object/Level.hpp b/source/game/back/object/Level.hpp index 7e7a1eb..3f047c9 100644 --- a/source/game/back/object/Level.hpp +++ b/source/game/back/object/Level.hpp @@ -5,17 +5,21 @@ namespace megu::game { class Level : public GameObject { - private: + public: Level(const std::string &); inline const std::string & name() const {return this->_name;} - + + void add(GameProps *); + + GameProps * get(Identifiable &) const; + virtual void apply(kernel::Kernel &) override final; - virtual void destroy(kernel::Kernel &) override final; + virtual void setup(kernel::Kernel &, Level &) override; + virtual void destroy(kernel::Kernel &, Level &) override final; - public: + private: std::string _name; - std::map<size_t, kernel::Prop *> _objecs; - + std::map<size_t, GameProps *> _objecs; }; } \ No newline at end of file diff --git a/source/game/back/object/Player.cpp b/source/game/back/object/Player.cpp index 6e01644..df16c72 100644 --- a/source/game/back/object/Player.cpp +++ b/source/game/back/object/Player.cpp @@ -1,10 +1,11 @@ #include "Player.hpp" #include <game/front/profile/PlayerKeys.hpp> +#include <game/back/object/Level.hpp> namespace megu::game { Player::Player(float x, float y, float w, float h, std::filesystem::path & path) - : kernel::PropsPlayable(this->_sprite, this->_movable), _sprite(path), _movable(x, y, w, h) { + : kernel::PropsPlayable(this->_sprite, this->_movable), GameProps(this), _sprite(path), _movable(x, y, w, h) { this->_sprite.setPosition({x, y}); } @@ -13,22 +14,48 @@ namespace megu::game { this->_movable.move(x, y); } - void Player::setup(kernel::Kernel & kernel) { + void Player::setup(kernel::Kernel & kernel, Level & level) { this->setControl(kernel.window(), new PlayerKeyProfile(*this)); this->_sprite.setFrame({0.f, 0.f, 51.f, 98.f}); this->_sprite.setSize({51.f, 98.f}); - this->_movable.setCollideLambda([](kernel::Kernel &, const kernel::PhysicEngine &, const megu::kernel::Physical<kernel::PhysicEngine> &, double) { - std::cout << "Player Collide !" << std::endl; + this->_movable.setCollideLambda([this, &level](kernel::Kernel &, kernel::PhysicEngine &, Identifiable & id, kernel::Physical<kernel::PhysicEngine> & comp, double) { + auto event = level.get(id)->on(); + if(event.has_value()) { + this->on(event.value()); + } }); } - void Player::destroy(kernel::Kernel &) { + void Player::on(const Behavior & event) { + if((event & Behavior::Type::SOLID) != 0) { + this->onSolide(event); + } + + if((event & Behavior::Type::DAMAGE) != 0) { + this->onDamage(event); + } + } + + std::optional<Behavior> Player::on() const { + return {}; + } + + void Player::destroy(kernel::Kernel & kernel, Level & level) { } void Player::apply(kernel::Kernel & kernel) { kernel.add(this); } + + void Player::onDamage(const Behavior & b) { + std::cout << "Player Got Damage !" << std::endl; + std::cout << "I take " << b.get(0) << " damage !" << std::endl; + } + + void Player::onSolide(const Behavior &) { + std::cout << "Player Got Solide !" << std::endl; + } } \ No newline at end of file diff --git a/source/game/back/object/Player.hpp b/source/game/back/object/Player.hpp index 74c7be8..8fa5dea 100644 --- a/source/game/back/object/Player.hpp +++ b/source/game/back/object/Player.hpp @@ -2,19 +2,26 @@ #include <kernel/front/props/PropsPlayable.hpp> #include <game/back/GameObject.hpp> +#include <game/back/object/Level.hpp> namespace megu::game { - class Player : public kernel::PropsPlayable, public GameObject { + class Player : public kernel::PropsPlayable, public GameProps { public: Player(float x, float y, float w, float h, std::filesystem::path &); void move(float, float); - void setup(kernel::Kernel &) override; - void destroy(kernel::Kernel &) override; + void setup(kernel::Kernel &, Level &) override; + void destroy(kernel::Kernel &, Level &) override; void apply(kernel::Kernel &) override; + void on(const Behavior &) override; + std::optional<Behavior> on() const override; + + void onDamage(const Behavior &); + void onSolide(const Behavior &); + private: kernel::Sprite _sprite; kernel::Movable _movable; diff --git a/source/kernel/back/component/Physical.hpp b/source/kernel/back/component/Physical.hpp index 3db5579..7828b34 100644 --- a/source/kernel/back/component/Physical.hpp +++ b/source/kernel/back/component/Physical.hpp @@ -9,8 +9,8 @@ namespace megu::kernel { template <class Pe> class Physical : public Component<Pe> { public: - virtual void on_collide(Kernel &, const Pe &, Physical &, double) = 0; + virtual void on_collide(Kernel &, Pe &, Identifiable &, Physical &, double) = 0; - using CollideLambda = std::function<void(Kernel &, const Pe &, const Physical &, double)>; + using CollideLambda = std::function<void(Kernel &, Pe &, Identifiable &, Physical &, double)>; }; } \ No newline at end of file diff --git a/source/kernel/front/Kernel.cpp b/source/kernel/front/Kernel.cpp index 8e66ea9..59c9428 100644 --- a/source/kernel/front/Kernel.cpp +++ b/source/kernel/front/Kernel.cpp @@ -54,4 +54,23 @@ namespace megu::kernel { this->_props.erase(props->id()); } + + Prop * Kernel::get(const Prop::Physical_Component & pc) { + for(auto & [id, props] : this->_props) { + if(props->getPhysicComponent()->id() == pc.id()) { + return props; + } + } + return nullptr; + } + + + Prop * Kernel::get(const Prop::Graphical_Component & gc) { + for(auto & [id, props] : this->_props) { + if(props->getGraphicComponent()->id() == gc.id()) { + return props; + } + } + return nullptr; + } } \ No newline at end of file diff --git a/source/kernel/front/Kernel.hpp b/source/kernel/front/Kernel.hpp index e7e7f04..0593c91 100644 --- a/source/kernel/front/Kernel.hpp +++ b/source/kernel/front/Kernel.hpp @@ -29,6 +29,9 @@ namespace megu::kernel { inline Window & window() {return this->_window;} + Prop * get(const Prop::Physical_Component &); + Prop * get(const Prop::Graphical_Component &); + private: Window & _window; diff --git a/source/kernel/front/component/physic/Fixed.cpp b/source/kernel/front/component/physic/Fixed.cpp index 8964777..a887afd 100644 --- a/source/kernel/front/component/physic/Fixed.cpp +++ b/source/kernel/front/component/physic/Fixed.cpp @@ -12,9 +12,9 @@ namespace megu::kernel { } } - void Fixed::on_collide(Kernel & kernel, const PhysicEngine & engine, Physical & physical, double time) { + void Fixed::on_collide(Kernel & kernel, PhysicEngine & engine, Identifiable & id, Physical & physical, double time) { if(this->_collide != nullptr) { - this->_collide(kernel, engine, physical, time); + this->_collide(kernel, engine, id, physical, time); } } diff --git a/source/kernel/front/component/physic/Fixed.hpp b/source/kernel/front/component/physic/Fixed.hpp index 232084a..7ef7041 100644 --- a/source/kernel/front/component/physic/Fixed.hpp +++ b/source/kernel/front/component/physic/Fixed.hpp @@ -13,7 +13,7 @@ namespace megu::kernel { Fixed(float x, float y, float w, float h); void update_physic(double) const override; - void on_collide(Kernel &, const PhysicEngine &, Physical &, double) override; + void on_collide(Kernel &, PhysicEngine &, Identifiable &, Physical &, double) override; void apply(Kernel & k, PhysicEngine &) override; void unapply(Kernel & k, PhysicEngine &) override; diff --git a/source/kernel/front/component/physic/FixedArray.cpp b/source/kernel/front/component/physic/FixedArray.cpp index 5e5602d..a0b61a7 100644 --- a/source/kernel/front/component/physic/FixedArray.cpp +++ b/source/kernel/front/component/physic/FixedArray.cpp @@ -22,11 +22,11 @@ namespace megu::kernel { this->_tangibles.erase(position); } - void FixedArray::on_collide(Kernel & kernel, const PhysicEngine & engine, Physical & physical, double time) { + void FixedArray::on_collide(Kernel & kernel, PhysicEngine & engine, Identifiable & id, Physical & physical, double time) { auto & tangible = engine.get(physical); for(auto & [position, fixed] : this->_tangibles) { if(fixed.isColliding(tangible)) { - physical.on_collide(kernel, engine, fixed, time); + physical.on_collide(kernel, engine, id, fixed, time); } } } diff --git a/source/kernel/front/component/physic/FixedArray.hpp b/source/kernel/front/component/physic/FixedArray.hpp index 9f04d44..73f1dae 100644 --- a/source/kernel/front/component/physic/FixedArray.hpp +++ b/source/kernel/front/component/physic/FixedArray.hpp @@ -20,7 +20,7 @@ namespace megu::kernel { void setUpdateLambda(UpdateLambda); void update_physic(double) const override; - void on_collide(Kernel &, const PhysicEngine &, Physical &, double) override; + void on_collide(Kernel &, PhysicEngine &, Identifiable &, Physical &, double) override; void apply(Kernel & k, PhysicEngine &) override; void unapply(Kernel & k, PhysicEngine &) override; diff --git a/source/kernel/front/component/physic/Movable.cpp b/source/kernel/front/component/physic/Movable.cpp index ac592e6..df0eef5 100644 --- a/source/kernel/front/component/physic/Movable.cpp +++ b/source/kernel/front/component/physic/Movable.cpp @@ -10,9 +10,9 @@ namespace megu::kernel { } } - void Movable::on_collide(Kernel & kernel, const PhysicEngine & engine, Physical & physical, double time) { + void Movable::on_collide(Kernel & kernel, PhysicEngine & engine, Identifiable & id, Physical & physical, double time) { if(this->_collide != nullptr) { - this->_collide(kernel, engine, physical, time); + this->_collide(kernel, engine, id, physical, time); } } diff --git a/source/kernel/front/component/physic/Movable.hpp b/source/kernel/front/component/physic/Movable.hpp index f1cd9ff..bdb94e6 100644 --- a/source/kernel/front/component/physic/Movable.hpp +++ b/source/kernel/front/component/physic/Movable.hpp @@ -13,7 +13,7 @@ namespace megu::kernel { Movable(float x, float y, float w, float h); void update_physic(double) override; - void on_collide(Kernel &, const PhysicEngine &, Physical &, double) override; + void on_collide(Kernel &, PhysicEngine &, Identifiable &, Physical &, double) override; void apply(Kernel & k, PhysicEngine &) override; void unapply(Kernel & k, PhysicEngine &) override; diff --git a/source/kernel/front/resolver/PhysicResolver.cpp b/source/kernel/front/resolver/PhysicResolver.cpp index f2b5431..593ab0a 100644 --- a/source/kernel/front/resolver/PhysicResolver.cpp +++ b/source/kernel/front/resolver/PhysicResolver.cpp @@ -1,5 +1,7 @@ #include "PhysicResolver.hpp" +#include <kernel/front/Kernel.hpp> + namespace megu::kernel { void PhysicResolver::resolve(Kernel & kernel, PhysicEngine & engine, double time) { auto & collisions = engine.get().collision(); @@ -9,7 +11,7 @@ namespace megu::kernel { auto target_comp = this->get(collision.target()); if(source_comp.has_value() && target_comp.has_value()) { - source_comp.value().get().on_collide(kernel, engine, target_comp.value().get(), time); + source_comp.value().get().on_collide(kernel, engine, *kernel.get(target_comp.value()), target_comp.value(), time); } } -- GitLab