mirror of
https://github.com/Nimac0/SDL_Minigame
synced 2026-01-12 15:53:42 +00:00
Compare commits
7 Commits
e0c35aa690
...
7a3c845c40
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a3c845c40 | |||
| 0695c6cacb | |||
| 3c5d56de6b | |||
| adaed679af | |||
| 325f6e8e8d | |||
| a9e754dd4f | |||
| d66d860cdc |
2
extern/SDL
vendored
2
extern/SDL
vendored
@ -1 +1 @@
|
|||||||
Subproject commit e027b85cc457556071cbb2f3f1bcf8803c1bc001
|
Subproject commit f6864924f76e1a0b4abaefc76ae2ed22b1a8916e
|
||||||
@ -92,8 +92,8 @@ public:
|
|||||||
{
|
{
|
||||||
T* c(new T(std::forward<TArgs>(mArgs)...));
|
T* c(new T(std::forward<TArgs>(mArgs)...));
|
||||||
c->entity = this;
|
c->entity = this;
|
||||||
std::unique_ptr<Component> uPtr{ c };
|
std::shared_ptr<Component> uPtr{ c };
|
||||||
this->components.emplace_back(std::move(uPtr));
|
this->components.at(getComponentTypeID<T>()) = std::move(uPtr);
|
||||||
|
|
||||||
componentArray[getComponentTypeID<T>()] = c;
|
componentArray[getComponentTypeID<T>()] = c;
|
||||||
componentBitSet[getComponentTypeID<T>()] = true;
|
componentBitSet[getComponentTypeID<T>()] = true;
|
||||||
@ -108,10 +108,15 @@ public:
|
|||||||
return *static_cast<T*>(ptr);
|
return *static_cast<T*>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T> std::shared_ptr<T> getComponentAsPointer() const
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<T>(components.at(getComponentTypeID<T>()));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Manager& manager;
|
Manager& manager;
|
||||||
bool active = true;
|
bool active = true;
|
||||||
std::vector<std::unique_ptr<Component>> components;
|
std::array<std::shared_ptr<Component>, MAX_COMPONENTS> components;
|
||||||
|
|
||||||
ComponentArray componentArray = {};
|
ComponentArray componentArray = {};
|
||||||
ComponentBitSet componentBitSet;
|
ComponentBitSet componentBitSet;
|
||||||
|
|||||||
21
include/EventManager.h
Normal file
21
include/EventManager.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "SDL3/SDL_events.h"
|
||||||
|
#include "SDL3/SDL_init.h"
|
||||||
|
|
||||||
|
typedef std::function<SDL_AppResult(SDL_EventType, SDL_Event* const)> EventListener;
|
||||||
|
|
||||||
|
class EventManager {
|
||||||
|
public:
|
||||||
|
EventManager();
|
||||||
|
|
||||||
|
void registerListener(EventListener listener, std::initializer_list<Uint32> eventTypes);
|
||||||
|
SDL_AppResult handleEvent(SDL_Event* const event);
|
||||||
|
private:
|
||||||
|
std::map<Uint32, std::vector<EventListener>> eventListeners = std::map<Uint32, std::vector<EventListener>>();
|
||||||
|
};
|
||||||
@ -7,15 +7,20 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "EventManager.h"
|
||||||
|
#include "InteractionManager.h"
|
||||||
#include "Manager.h"
|
#include "Manager.h"
|
||||||
|
#include "SDL3/SDL_events.h"
|
||||||
|
#include "SDL3/SDL_init.h"
|
||||||
#include "Vector2D.h"
|
#include "Vector2D.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
|
#include "InputManager.h"
|
||||||
#include "RenderManager.h"
|
#include "RenderManager.h"
|
||||||
#include "ConfigLoader.h"
|
#include "ConfigLoader.h"
|
||||||
|
#include "PickupManager.h"
|
||||||
|
|
||||||
typedef std::function<void()> gamefunction;
|
typedef std::function<void()> gamefunction;
|
||||||
|
|
||||||
class AssetManager;
|
|
||||||
class CollisionHandler;
|
class CollisionHandler;
|
||||||
class TextureManager;
|
class TextureManager;
|
||||||
class SoundManager;
|
class SoundManager;
|
||||||
@ -30,7 +35,7 @@ public:
|
|||||||
|
|
||||||
SDL_AppResult init();
|
SDL_AppResult init();
|
||||||
|
|
||||||
void handleEvents();
|
SDL_AppResult handleEvent(SDL_Event* event);
|
||||||
void update(Uint64 frameTime);
|
void update(Uint64 frameTime);
|
||||||
void render();
|
void render();
|
||||||
void clean();
|
void clean();
|
||||||
@ -41,12 +46,15 @@ public:
|
|||||||
/* static */ SDL_Renderer* renderer = nullptr;
|
/* static */ SDL_Renderer* renderer = nullptr;
|
||||||
/* static */ SDL_Event event;
|
/* static */ SDL_Event event;
|
||||||
/* static */ CollisionHandler* collisionHandler;
|
/* static */ CollisionHandler* collisionHandler;
|
||||||
/* static */ AssetManager* assets;
|
/* static */ PickupManager* pickupManager;
|
||||||
/* static */ TextureManager* textureManager;
|
/* static */ TextureManager* textureManager;
|
||||||
/* static */ SoundManager* soundManager;
|
/* static */ SoundManager* soundManager;
|
||||||
|
/* static */ InputManager* inputManager;
|
||||||
|
RenderManager* renderManager;
|
||||||
|
EventManager* eventManager;
|
||||||
|
InteractionManager* interactionManager;
|
||||||
|
|
||||||
Manager manager;
|
Manager manager;
|
||||||
RenderManager renderManager;
|
|
||||||
Map* map; // game specific, might not be needed for all types of games
|
Map* map; // game specific, might not be needed for all types of games
|
||||||
|
|
||||||
ConfigLoader* config;
|
ConfigLoader* config;
|
||||||
|
|||||||
139
include/InputManager.h
Normal file
139
include/InputManager.h
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL3/SDL_events.h>
|
||||||
|
#include <SDL3/SDL_init.h>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class InputManager {
|
||||||
|
public:
|
||||||
|
enum class EventType {
|
||||||
|
KeyDown,
|
||||||
|
KeyUp
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Key
|
||||||
|
{
|
||||||
|
UP,
|
||||||
|
DOWN,
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
SPACE,
|
||||||
|
ENTER,
|
||||||
|
ESCAPE,
|
||||||
|
TAB,
|
||||||
|
BACKSPACE,
|
||||||
|
DELETE,
|
||||||
|
HOME,
|
||||||
|
END,
|
||||||
|
PAGE_UP,
|
||||||
|
PAGE_DOWN,
|
||||||
|
INSERT,
|
||||||
|
CAPS_LOCK,
|
||||||
|
LEFT_SHIFT,
|
||||||
|
RIGHT_SHIFT,
|
||||||
|
LEFT_CTRL,
|
||||||
|
RIGHT_CTRL,
|
||||||
|
LEFT_ALT,
|
||||||
|
RIGHT_ALT,
|
||||||
|
F1,
|
||||||
|
F2,
|
||||||
|
F3,
|
||||||
|
F4,
|
||||||
|
F5,
|
||||||
|
F6,
|
||||||
|
F7,
|
||||||
|
F8,
|
||||||
|
F9,
|
||||||
|
F10,
|
||||||
|
F11,
|
||||||
|
F12,
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
E,
|
||||||
|
F,
|
||||||
|
G,
|
||||||
|
H,
|
||||||
|
I,
|
||||||
|
J,
|
||||||
|
K,
|
||||||
|
L,
|
||||||
|
M,
|
||||||
|
N,
|
||||||
|
O,
|
||||||
|
P,
|
||||||
|
Q,
|
||||||
|
R,
|
||||||
|
S,
|
||||||
|
T,
|
||||||
|
U,
|
||||||
|
V,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
NUM_0,
|
||||||
|
NUM_1,
|
||||||
|
NUM_2,
|
||||||
|
NUM_3,
|
||||||
|
NUM_4,
|
||||||
|
NUM_5,
|
||||||
|
NUM_6,
|
||||||
|
NUM_7,
|
||||||
|
NUM_8,
|
||||||
|
NUM_9,
|
||||||
|
LEFT_BRACKET,
|
||||||
|
RIGHT_BRACKET,
|
||||||
|
SEMICOLON,
|
||||||
|
APOSTROPHE,
|
||||||
|
COMMA,
|
||||||
|
PERIOD,
|
||||||
|
SLASH,
|
||||||
|
BACKSLASH,
|
||||||
|
GRAVE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InputAction {
|
||||||
|
std::string name;
|
||||||
|
std::vector<Key> bindings;
|
||||||
|
std::function<void(bool)> callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
InputManager();
|
||||||
|
~InputManager();
|
||||||
|
|
||||||
|
void init(); // see if necessary
|
||||||
|
void processEvents();
|
||||||
|
void registerAction(const std::string& actionName, const std::vector<Key>& keys, std::function<void(bool)> callback, const std::string& context);
|
||||||
|
|
||||||
|
void setActiveContext(const std::string& context);
|
||||||
|
std::string getActiveContext() const;
|
||||||
|
|
||||||
|
//void rebindAction(const std::string& actionName, const std::vector<Key>& newBindings, const std::string& context);
|
||||||
|
//void removeBindings(const std::string& actionName, const std::string& context);
|
||||||
|
//std::vector<Key> getBindings(const std::string& actionName, const std::string& context) const;
|
||||||
|
std::vector<InputAction*> getActionsByKey(const Key key) const;
|
||||||
|
|
||||||
|
SDL_AppResult handleEvent(SDL_EventType type, SDL_Event* const event);
|
||||||
|
|
||||||
|
void initKeyMap();
|
||||||
|
private:
|
||||||
|
// TODO: flesh this out to avoid loops in process actions
|
||||||
|
// additionally to actionsByContext, not instead
|
||||||
|
std::map<std::string, std::map<Key, std::vector<InputAction*>>> actionsByContextAndKey;
|
||||||
|
|
||||||
|
std::map<Key, SDL_Scancode> keyMap;
|
||||||
|
std::string activeContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, InputManager::Key key);
|
||||||
|
std::ostream& operator<<(std::ostream& os, const InputManager::InputAction& action);
|
||||||
|
std::ostream& operator<<(std::ostream& os, const InputManager::InputAction* action);
|
||||||
|
std::ostream& operator<<(std::ostream& os, const std::vector<InputManager::InputAction>& actions);
|
||||||
|
std::ostream& operator<<(std::ostream& os, const std::vector<InputManager::InputAction*>& actions);
|
||||||
28
include/InteractionComponent.h
Normal file
28
include/InteractionComponent.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Component.h"
|
||||||
|
#include "InteractionListener.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class InteractionComponent : public Component, public InteractionListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructor for the InteractionComponent.
|
||||||
|
* @param callback A function to be called when an interaction event is triggered. void* actor, void* data are passed to the callback function from InteractionEventdataStruct.
|
||||||
|
*/
|
||||||
|
InteractionComponent(std::function<void(void*,void*)> callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal function to be called when an interaction event is triggered.
|
||||||
|
*/
|
||||||
|
void interact(void* actor, void* data) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal function to use as reference for targeting.
|
||||||
|
*/
|
||||||
|
std::shared_ptr<Vector2D> getPosition() override;
|
||||||
|
private:
|
||||||
|
std::function<void(void*,void*)> interactionCallback;
|
||||||
|
};
|
||||||
28
include/InteractionEventdataStruct.h
Normal file
28
include/InteractionEventdataStruct.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Entity.h"
|
||||||
|
#include "InteractionListener.h"
|
||||||
|
#include "InteractionManager.h"
|
||||||
|
#include "Vector2D.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Struct to hold data for interaction events.
|
||||||
|
* This struct is used to pass data to the interaction manager when an interaction event is triggered.
|
||||||
|
*/
|
||||||
|
struct InteractionEventdataStruct {
|
||||||
|
/// Arbitray data to pass to the interaction listener. Can for example be an Entity ptr to represent the actor.
|
||||||
|
void* actor;
|
||||||
|
/// The data to pass to the interaction listener. Can be any type of pointer.
|
||||||
|
void* data;
|
||||||
|
/// The target of the interaction, e.g. InteractionComponent of an Entity. Is required if strategy is set to 0 (none)
|
||||||
|
std::weak_ptr<InteractionListener> target = std::weak_ptr<InteractionListener>();
|
||||||
|
/// Coordinates from which to base targeting on. Is required if strategy is not set to 0 (none)
|
||||||
|
std::shared_ptr<Vector2D> targetingReference = nullptr;
|
||||||
|
/// required without explicit target, defaults to none
|
||||||
|
/// @sa InteractionManager::TargetingStrategy
|
||||||
|
uint8_t strategy = 0; // int since enum would be impossibling user defined targetingStrategies
|
||||||
|
|
||||||
|
void triggerEvent();
|
||||||
|
};
|
||||||
17
include/InteractionListener.h
Normal file
17
include/InteractionListener.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Vector2D.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class InteractionListener {
|
||||||
|
public:
|
||||||
|
InteractionListener() { };
|
||||||
|
virtual ~InteractionListener() { };
|
||||||
|
|
||||||
|
virtual void interact(void* actor, void* data) = 0;
|
||||||
|
virtual std::shared_ptr<Vector2D> getPosition() // required for targeting strategy, return null to only allow explicit targeting
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
35
include/InteractionManager.h
Normal file
35
include/InteractionManager.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "InteractionListener.h"
|
||||||
|
|
||||||
|
#include "SDL3/SDL_events.h"
|
||||||
|
#include "SDL3/SDL_init.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
// TODO: ranges concept to avoid to<vector> in cpp
|
||||||
|
typedef std::function<std::shared_ptr<InteractionListener>(Vector2D*, std::vector<std::shared_ptr<InteractionListener>>)> TargetingFunc;
|
||||||
|
|
||||||
|
class InteractionManager {
|
||||||
|
public:
|
||||||
|
InteractionManager();
|
||||||
|
InteractionManager (const InteractionManager&) = delete;
|
||||||
|
InteractionManager& operator= (const InteractionManager&) = delete;
|
||||||
|
|
||||||
|
enum class TargetingStrategy : uint8_t {
|
||||||
|
none = 0,
|
||||||
|
closest,
|
||||||
|
manhattenDistance
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_AppResult handleInteract(SDL_EventType type, SDL_Event* const event);
|
||||||
|
void registerListener(std::weak_ptr<InteractionListener> listener);
|
||||||
|
uint8_t registerTargetingFunc(TargetingFunc func);
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector<std::weak_ptr<InteractionListener>> listeners;
|
||||||
|
std::array<TargetingFunc, 256> targetingFuncs;
|
||||||
|
};
|
||||||
@ -3,15 +3,15 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
|
|
||||||
class PowerupComponent : public Component
|
class PickupComponent : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new Powerup Component object
|
* @brief Construct a new Powerup Component object
|
||||||
* @param func The function to be called when the powerup is picked up
|
* @param func The function to be called when the powerup is picked up
|
||||||
*/
|
*/
|
||||||
PowerupComponent(std::function<void (Entity*)> func);
|
PickupComponent(std::function<void (Entity*)> func);
|
||||||
~PowerupComponent() {};
|
~PickupComponent() {};
|
||||||
|
|
||||||
void update(uint_fast16_t diffTime) override;
|
void update(uint_fast16_t diffTime) override;
|
||||||
|
|
||||||
@ -11,25 +11,16 @@
|
|||||||
class Vector2D;
|
class Vector2D;
|
||||||
class Manager;
|
class Manager;
|
||||||
|
|
||||||
enum class PowerupType
|
class PickupManager
|
||||||
{
|
|
||||||
HEART,
|
|
||||||
WALKINGSPEED,
|
|
||||||
SHOOTINGSPEED
|
|
||||||
};
|
|
||||||
|
|
||||||
class AssetManager
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AssetManager(Manager* manager);
|
PickupManager(Manager* manager);
|
||||||
~AssetManager();
|
~PickupManager();
|
||||||
|
|
||||||
void createPowerup(Vector2D pos, std::function<void (Entity*)> pickupFunc, Textures texture);
|
void createPowerup(Vector2D pos, std::function<void (Entity*)> pickupFunc, Textures texture);
|
||||||
|
|
||||||
Vector2D calculateSpawnPosition();
|
Vector2D calculateSpawnPosition();
|
||||||
PowerupType calculateType();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -7,7 +7,7 @@ class RenderObject
|
|||||||
public:
|
public:
|
||||||
virtual void draw() = 0;
|
virtual void draw() = 0;
|
||||||
|
|
||||||
RenderObject(int zIndex, RenderManager& renderManager);
|
RenderObject(int zIndex, RenderManager* renderManager);
|
||||||
~RenderObject();
|
~RenderObject();
|
||||||
|
|
||||||
int getZIndex() { return this->zIndex; };
|
int getZIndex() { return this->zIndex; };
|
||||||
@ -23,5 +23,5 @@ private:
|
|||||||
int zIndex = 0;
|
int zIndex = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RenderManager& renderManager;
|
RenderManager* renderManager;
|
||||||
};
|
};
|
||||||
@ -40,6 +40,11 @@ private:
|
|||||||
const char* path; //!< empty string if texture has a texture enum value, otherwise the path of the texture
|
const char* path; //!< empty string if texture has a texture enum value, otherwise the path of the texture
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
//debug
|
||||||
|
Textures getTexture() { return this->textureEnum; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SpriteComponent(Textures texture, int zIndex);
|
SpriteComponent(Textures texture, int zIndex);
|
||||||
SpriteComponent(Textures texture, int xOffset, int yOffset, int zIndex);
|
SpriteComponent(Textures texture, int xOffset, int yOffset, int zIndex);
|
||||||
SpriteComponent(const char* path, int xOffset, int yOffset, int zIndex);
|
SpriteComponent(const char* path, int xOffset, int yOffset, int zIndex);
|
||||||
|
|||||||
@ -83,9 +83,15 @@ class TextureManager
|
|||||||
*/
|
*/
|
||||||
SDL_Texture* loadMapTileTexture(const char* path);
|
SDL_Texture* loadMapTileTexture(const char* path);
|
||||||
|
|
||||||
|
std::string getTexturePath(Textures texture) {
|
||||||
|
return this->texture_references.at(texture);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDL_ScaleMode scaleMode = SDL_SCALEMODE_NEAREST;
|
SDL_ScaleMode scaleMode = SDL_SCALEMODE_NEAREST;
|
||||||
Manager* manager;
|
Manager* manager;
|
||||||
std::map<Textures, SDL_Texture*> texture_cache;
|
std::map<Textures, SDL_Texture*> texture_cache;
|
||||||
std::map<std::string, SDL_Texture*> mapTile_texture_cache;
|
std::map<std::string, SDL_Texture*> mapTile_texture_cache;
|
||||||
|
|
||||||
|
std::map<Textures, std::string> texture_references;
|
||||||
};
|
};
|
||||||
7
include/VEGO_Event.h
Normal file
7
include/VEGO_Event.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
|
||||||
|
namespace vego {
|
||||||
|
extern Uint32 VEGO_Event_Interaction;
|
||||||
|
}
|
||||||
@ -6,7 +6,9 @@
|
|||||||
|
|
||||||
void Entity::update(uint_fast16_t diffTime) const
|
void Entity::update(uint_fast16_t diffTime) const
|
||||||
{
|
{
|
||||||
for (auto const& c : components) c->update(diffTime);
|
for (auto const& c : components)
|
||||||
|
if (c)
|
||||||
|
c->update(diffTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Entity::hasGroup(Group mGroup)
|
bool Entity::hasGroup(Group mGroup)
|
||||||
|
|||||||
44
src/EventManager.cpp
Normal file
44
src/EventManager.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "EventManager.h"
|
||||||
|
#include "SDL3/SDL_events.h"
|
||||||
|
#include "SDL3/SDL_init.h"
|
||||||
|
#include "SDL3/SDL_stdinc.h"
|
||||||
|
#include "VEGO_Event.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <ranges>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
Uint32 vego::VEGO_Event_Interaction;
|
||||||
|
|
||||||
|
EventManager::EventManager()
|
||||||
|
{
|
||||||
|
/// \TODO: from c++26 you (should be able to) can get the amount of name values in an enum
|
||||||
|
vego::VEGO_Event_Interaction = SDL_RegisterEvents(1); // TODO: error handling
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EventManager::registerListener(EventListener listener, std::initializer_list<Uint32> eventTypes)
|
||||||
|
{
|
||||||
|
std::ranges::for_each(eventTypes.begin(), eventTypes.end(), [this, &listener](const Uint32& eventType) {
|
||||||
|
if (!this->eventListeners.contains(eventType)) {
|
||||||
|
this->eventListeners.insert({eventType, std::vector<EventListener>()});
|
||||||
|
}
|
||||||
|
this->eventListeners.at(eventType).emplace_back(listener);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_AppResult EventManager::handleEvent(SDL_Event* event)
|
||||||
|
{
|
||||||
|
SDL_EventType type = (SDL_EventType) event->type;
|
||||||
|
if (this->eventListeners.contains(type)) {
|
||||||
|
std::vector<SDL_AppResult> results;
|
||||||
|
for (auto& listener : this->eventListeners.at(type)) {
|
||||||
|
results.emplace_back(listener((SDL_EventType) event->type, event));
|
||||||
|
}
|
||||||
|
if (std::ranges::contains(results, SDL_APP_FAILURE))
|
||||||
|
return SDL_APP_FAILURE;
|
||||||
|
if (std::ranges::contains(results, SDL_APP_SUCCESS))
|
||||||
|
return SDL_APP_SUCCESS;
|
||||||
|
}
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
@ -1,10 +1,14 @@
|
|||||||
#include "GameInternal.h"
|
#include "GameInternal.h"
|
||||||
|
|
||||||
#include "CollisionHandler.h"
|
#include "CollisionHandler.h"
|
||||||
#include "AssetManager.h"
|
#include "EventManager.h"
|
||||||
|
#include "InputManager.h"
|
||||||
|
#include "InteractionManager.h"
|
||||||
#include "RenderManager.h"
|
#include "RenderManager.h"
|
||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
|
#include "SDL3/SDL_events.h"
|
||||||
#include "SDL3/SDL_init.h"
|
#include "SDL3/SDL_init.h"
|
||||||
|
#include "SDL3/SDL_oldnames.h"
|
||||||
#include "SoundManager.h"
|
#include "SoundManager.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "HealthComponent.h"
|
#include "HealthComponent.h"
|
||||||
@ -14,12 +18,13 @@
|
|||||||
#include "GameFactory.h"
|
#include "GameFactory.h"
|
||||||
|
|
||||||
#include <VEGO.h>
|
#include <VEGO.h>
|
||||||
|
#include <VEGO_Event.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "ConfigLoader.h"
|
#include "ConfigLoader.h"
|
||||||
|
|
||||||
GameInternal::GameInternal() :
|
GameInternal::GameInternal() :
|
||||||
manager(this),
|
manager(this),
|
||||||
renderManager(),
|
|
||||||
tiles(manager.getGroup((size_t)Entity::GroupLabel::MAPTILES)),
|
tiles(manager.getGroup((size_t)Entity::GroupLabel::MAPTILES)),
|
||||||
players(manager.getGroup((size_t)Entity::GroupLabel::PLAYERS)),
|
players(manager.getGroup((size_t)Entity::GroupLabel::PLAYERS)),
|
||||||
projectiles(manager.getGroup((size_t)Entity::GroupLabel::PROJECTILE)),
|
projectiles(manager.getGroup((size_t)Entity::GroupLabel::PROJECTILE)),
|
||||||
@ -39,10 +44,19 @@ SDL_AppResult GameInternal::init()
|
|||||||
|
|
||||||
json finalConfig = config->getFinalConfig();
|
json finalConfig = config->getFinalConfig();
|
||||||
|
|
||||||
GameInternal::assets = new AssetManager(&manager);
|
GameInternal::pickupManager = new PickupManager(&manager);
|
||||||
GameInternal::textureManager = new TextureManager(&manager);
|
GameInternal::textureManager = new TextureManager(&manager);
|
||||||
GameInternal::soundManager = new SoundManager();
|
GameInternal::soundManager = new SoundManager();
|
||||||
GameInternal::collisionHandler = new CollisionHandler(manager); // why does this use a referrence, but AssetManager a pointer?
|
GameInternal::collisionHandler = new CollisionHandler(manager); // why does this use a referrence, but AssetManager a pointer?
|
||||||
|
GameInternal::inputManager = new InputManager();
|
||||||
|
GameInternal::inputManager->initKeyMap();
|
||||||
|
|
||||||
|
GameInternal::renderManager = new RenderManager();
|
||||||
|
GameInternal::eventManager = new EventManager();
|
||||||
|
GameInternal::interactionManager = new InteractionManager();
|
||||||
|
|
||||||
|
this->eventManager->registerListener(std::bind_front(&InputManager::handleEvent, this->inputManager), { SDL_EVENT_KEY_DOWN, SDL_EVENT_KEY_UP });
|
||||||
|
this->eventManager->registerListener(std::bind_front(&InteractionManager::handleInteract, VEGO_Game().interactionManager), { vego::VEGO_Event_Interaction });
|
||||||
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (finalConfig.at("fullscreen"))
|
if (finalConfig.at("fullscreen"))
|
||||||
@ -112,18 +126,15 @@ SDL_AppResult GameInternal::init()
|
|||||||
return SDL_APP_CONTINUE;
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameInternal::handleEvents()
|
SDL_AppResult GameInternal::handleEvent(SDL_Event* event) {
|
||||||
{
|
SDL_AppResult result = this->eventManager->handleEvent(event);
|
||||||
SDL_PollEvent(&event);
|
|
||||||
|
|
||||||
switch (event.type)
|
if (event->type == SDL_EVENT_QUIT) {
|
||||||
{
|
this->clean();
|
||||||
case SDL_EVENT_QUIT: this->setRunning(false);
|
return result == SDL_APP_FAILURE ? SDL_APP_FAILURE : SDL_APP_SUCCESS;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameInternal::update(Uint64 frameTime)
|
void GameInternal::update(Uint64 frameTime)
|
||||||
@ -141,7 +152,7 @@ void GameInternal::update(Uint64 frameTime)
|
|||||||
void GameInternal::render()
|
void GameInternal::render()
|
||||||
{
|
{
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
this->renderManager.renderAll();
|
this->renderManager->renderAll();
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
303
src/InputManager.cpp
Normal file
303
src/InputManager.cpp
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
#include "InputManager.h"
|
||||||
|
#include "InteractionEventdataStruct.h"
|
||||||
|
#include "SDL3/SDL_events.h"
|
||||||
|
#include "SDL3/SDL_init.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include "SDL3/SDL_stdinc.h"
|
||||||
|
#include "VEGO.h"
|
||||||
|
#include "VEGO_Event.h"
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, InputManager::Key key) {
|
||||||
|
static const std::unordered_map<InputManager::Key, std::string> keyToString {
|
||||||
|
{InputManager::Key::UP, "UP"},
|
||||||
|
{InputManager::Key::DOWN, "DOWN"},
|
||||||
|
{InputManager::Key::LEFT, "LEFT"},
|
||||||
|
{InputManager::Key::RIGHT, "RIGHT"},
|
||||||
|
{InputManager::Key::SPACE, "SPACE"},
|
||||||
|
{InputManager::Key::ENTER, "ENTER"},
|
||||||
|
{InputManager::Key::ESCAPE, "ESCAPE"},
|
||||||
|
{InputManager::Key::TAB, "TAB"},
|
||||||
|
{InputManager::Key::BACKSPACE, "BACKSPACE"},
|
||||||
|
{InputManager::Key::DELETE, "DELETE"},
|
||||||
|
{InputManager::Key::HOME, "HOME"},
|
||||||
|
{InputManager::Key::END, "END"},
|
||||||
|
{InputManager::Key::PAGE_UP, "PAGE_UP"},
|
||||||
|
{InputManager::Key::PAGE_DOWN, "PAGE_DOWN"},
|
||||||
|
{InputManager::Key::INSERT, "INSERT"},
|
||||||
|
{InputManager::Key::CAPS_LOCK, "CAPS_LOCK"},
|
||||||
|
{InputManager::Key::LEFT_SHIFT, "LEFT_SHIFT"},
|
||||||
|
{InputManager::Key::RIGHT_SHIFT, "RIGHT_SHIFT"},
|
||||||
|
{InputManager::Key::LEFT_CTRL, "LEFT_CTRL"},
|
||||||
|
{InputManager::Key::RIGHT_CTRL, "RIGHT_CTRL"},
|
||||||
|
{InputManager::Key::LEFT_ALT, "LEFT_ALT"},
|
||||||
|
{InputManager::Key::RIGHT_ALT, "RIGHT_ALT"},
|
||||||
|
{InputManager::Key::F1, "F1"},
|
||||||
|
{InputManager::Key::F2, "F2"},
|
||||||
|
{InputManager::Key::F3, "F3"},
|
||||||
|
{InputManager::Key::F4, "F4"},
|
||||||
|
{InputManager::Key::F5, "F5"},
|
||||||
|
{InputManager::Key::F6, "F6"},
|
||||||
|
{InputManager::Key::F7, "F7"},
|
||||||
|
{InputManager::Key::F8, "F8"},
|
||||||
|
{InputManager::Key::F9, "F9"},
|
||||||
|
{InputManager::Key::F10, "F10"},
|
||||||
|
{InputManager::Key::F11, "F11"},
|
||||||
|
{InputManager::Key::F12, "F12"},
|
||||||
|
{InputManager::Key::A, "A"},
|
||||||
|
{InputManager::Key::B, "B"},
|
||||||
|
{InputManager::Key::C, "C"},
|
||||||
|
{InputManager::Key::D, "D"},
|
||||||
|
{InputManager::Key::E, "E"},
|
||||||
|
{InputManager::Key::F, "F"},
|
||||||
|
{InputManager::Key::G, "G"},
|
||||||
|
{InputManager::Key::H, "H"},
|
||||||
|
{InputManager::Key::I, "I"},
|
||||||
|
{InputManager::Key::J, "J"},
|
||||||
|
{InputManager::Key::K, "K"},
|
||||||
|
{InputManager::Key::L, "L"},
|
||||||
|
{InputManager::Key::M, "M"},
|
||||||
|
{InputManager::Key::N, "N"},
|
||||||
|
{InputManager::Key::O, "O"},
|
||||||
|
{InputManager::Key::P, "P"},
|
||||||
|
{InputManager::Key::Q, "Q"},
|
||||||
|
{InputManager::Key::R, "R"},
|
||||||
|
{InputManager::Key::S, "S"},
|
||||||
|
{InputManager::Key::T, "T"},
|
||||||
|
{InputManager::Key::U, "U"},
|
||||||
|
{InputManager::Key::V, "V"},
|
||||||
|
{InputManager::Key::W, "W"},
|
||||||
|
{InputManager::Key::X, "X"},
|
||||||
|
{InputManager::Key::Y, "Y"},
|
||||||
|
{InputManager::Key::Z, "Z"},
|
||||||
|
{InputManager::Key::NUM_0, "NUM_0"},
|
||||||
|
{InputManager::Key::NUM_1, "NUM_1"},
|
||||||
|
{InputManager::Key::NUM_2, "NUM_2"},
|
||||||
|
{InputManager::Key::NUM_3, "NUM_3"},
|
||||||
|
{InputManager::Key::NUM_4, "NUM_4"},
|
||||||
|
{InputManager::Key::NUM_5, "NUM_5"},
|
||||||
|
{InputManager::Key::NUM_6, "NUM_6"},
|
||||||
|
{InputManager::Key::NUM_7, "NUM_7"},
|
||||||
|
{InputManager::Key::NUM_8, "NUM_8"},
|
||||||
|
{InputManager::Key::NUM_9, "NUM_9"},
|
||||||
|
{InputManager::Key::LEFT_BRACKET, "LEFT_BRACKET"},
|
||||||
|
{InputManager::Key::RIGHT_BRACKET, "RIGHT_BRACKET"},
|
||||||
|
{InputManager::Key::SEMICOLON, "SEMICOLON"},
|
||||||
|
{InputManager::Key::APOSTROPHE, "APOSTROPHE"},
|
||||||
|
{InputManager::Key::COMMA, "COMMA"},
|
||||||
|
{InputManager::Key::PERIOD, "PERIOD"},
|
||||||
|
{InputManager::Key::SLASH, "SLASH"},
|
||||||
|
{InputManager::Key::BACKSLASH, "BACKSLASH"},
|
||||||
|
{InputManager::Key::GRAVE, "GRAVE"}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto it = keyToString.find(key);
|
||||||
|
if (it != keyToString.end()) {
|
||||||
|
os << it->second;
|
||||||
|
} else {
|
||||||
|
os << "UNKNOWN_KEY";
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const InputManager::InputAction& action) {
|
||||||
|
os << action.name << " with binding(s): ";
|
||||||
|
for (auto& binding : action.bindings) {
|
||||||
|
os << binding << ", ";
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const InputManager::InputAction* action) {
|
||||||
|
if (action) {
|
||||||
|
os << *action;
|
||||||
|
} else {
|
||||||
|
os << "NULL_ACTION";
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const std::vector<InputManager::InputAction>& actions) {
|
||||||
|
os << "Actions: ";
|
||||||
|
if (actions.empty()) {
|
||||||
|
os << "None";
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < actions.size(); ++i) {
|
||||||
|
os << actions[i];
|
||||||
|
if (i < actions.size() - 1) {
|
||||||
|
os << " | ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: find out why it doesnt work??
|
||||||
|
std::ostream& operator<<(std::ostream& os, const std::vector<InputManager::InputAction*>& actions) {
|
||||||
|
os << "Actions: ";
|
||||||
|
if (actions.empty()) {
|
||||||
|
os << "None";
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < actions.size(); ++i) {
|
||||||
|
if (actions[i]) {
|
||||||
|
os << *actions[i];
|
||||||
|
} else {
|
||||||
|
os << "NULL_ACTION";
|
||||||
|
}
|
||||||
|
if (i < actions.size() - 1) {
|
||||||
|
os << " | ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// overloads end --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
InputManager::InputManager() : activeContext("Default") {}
|
||||||
|
|
||||||
|
InputManager::~InputManager() {}
|
||||||
|
|
||||||
|
void InputManager::initKeyMap() {
|
||||||
|
keyMap = {
|
||||||
|
{Key::UP, SDL_SCANCODE_UP},
|
||||||
|
{Key::DOWN, SDL_SCANCODE_DOWN},
|
||||||
|
{Key::LEFT, SDL_SCANCODE_LEFT},
|
||||||
|
{Key::RIGHT, SDL_SCANCODE_RIGHT},
|
||||||
|
{Key::SPACE, SDL_SCANCODE_SPACE},
|
||||||
|
{Key::ENTER, SDL_SCANCODE_RETURN},
|
||||||
|
{Key::ESCAPE, SDL_SCANCODE_ESCAPE},
|
||||||
|
{Key::TAB, SDL_SCANCODE_TAB},
|
||||||
|
{Key::BACKSPACE, SDL_SCANCODE_BACKSPACE},
|
||||||
|
{Key::DELETE, SDL_SCANCODE_DELETE},
|
||||||
|
{Key::HOME, SDL_SCANCODE_HOME},
|
||||||
|
{Key::END, SDL_SCANCODE_END},
|
||||||
|
{Key::PAGE_UP, SDL_SCANCODE_PAGEUP},
|
||||||
|
{Key::PAGE_DOWN, SDL_SCANCODE_PAGEDOWN},
|
||||||
|
{Key::INSERT, SDL_SCANCODE_INSERT},
|
||||||
|
{Key::CAPS_LOCK, SDL_SCANCODE_CAPSLOCK},
|
||||||
|
{Key::LEFT_SHIFT, SDL_SCANCODE_LSHIFT},
|
||||||
|
{Key::RIGHT_SHIFT, SDL_SCANCODE_RSHIFT},
|
||||||
|
{Key::LEFT_CTRL, SDL_SCANCODE_LCTRL},
|
||||||
|
{Key::RIGHT_CTRL, SDL_SCANCODE_RCTRL},
|
||||||
|
{Key::LEFT_ALT, SDL_SCANCODE_LALT},
|
||||||
|
{Key::RIGHT_ALT, SDL_SCANCODE_RALT},
|
||||||
|
{Key::F1, SDL_SCANCODE_F1},
|
||||||
|
{Key::F2, SDL_SCANCODE_F2},
|
||||||
|
{Key::F3, SDL_SCANCODE_F3},
|
||||||
|
{Key::F4, SDL_SCANCODE_F4},
|
||||||
|
{Key::F5, SDL_SCANCODE_F5},
|
||||||
|
{Key::F6, SDL_SCANCODE_F6},
|
||||||
|
{Key::F7, SDL_SCANCODE_F7},
|
||||||
|
{Key::F8, SDL_SCANCODE_F8},
|
||||||
|
{Key::F9, SDL_SCANCODE_F9},
|
||||||
|
{Key::F10, SDL_SCANCODE_F10},
|
||||||
|
{Key::F11, SDL_SCANCODE_F11},
|
||||||
|
{Key::F12, SDL_SCANCODE_F12},
|
||||||
|
{Key::A, SDL_SCANCODE_A},
|
||||||
|
{Key::B, SDL_SCANCODE_B},
|
||||||
|
{Key::C, SDL_SCANCODE_C},
|
||||||
|
{Key::D, SDL_SCANCODE_D},
|
||||||
|
{Key::E, SDL_SCANCODE_E},
|
||||||
|
{Key::F, SDL_SCANCODE_F},
|
||||||
|
{Key::G, SDL_SCANCODE_G},
|
||||||
|
{Key::H, SDL_SCANCODE_H},
|
||||||
|
{Key::I, SDL_SCANCODE_I},
|
||||||
|
{Key::J, SDL_SCANCODE_J},
|
||||||
|
{Key::K, SDL_SCANCODE_K},
|
||||||
|
{Key::L, SDL_SCANCODE_L},
|
||||||
|
{Key::M, SDL_SCANCODE_M},
|
||||||
|
{Key::N, SDL_SCANCODE_N},
|
||||||
|
{Key::O, SDL_SCANCODE_O},
|
||||||
|
{Key::P, SDL_SCANCODE_P},
|
||||||
|
{Key::Q, SDL_SCANCODE_Q},
|
||||||
|
{Key::R, SDL_SCANCODE_R},
|
||||||
|
{Key::S, SDL_SCANCODE_S},
|
||||||
|
{Key::T, SDL_SCANCODE_T},
|
||||||
|
{Key::U, SDL_SCANCODE_U},
|
||||||
|
{Key::V, SDL_SCANCODE_V},
|
||||||
|
{Key::W, SDL_SCANCODE_W},
|
||||||
|
{Key::X, SDL_SCANCODE_X},
|
||||||
|
{Key::Y, SDL_SCANCODE_Y},
|
||||||
|
{Key::Z, SDL_SCANCODE_Z},
|
||||||
|
{Key::NUM_0, SDL_SCANCODE_0},
|
||||||
|
{Key::NUM_1, SDL_SCANCODE_1},
|
||||||
|
{Key::NUM_2, SDL_SCANCODE_2},
|
||||||
|
{Key::NUM_3, SDL_SCANCODE_3},
|
||||||
|
{Key::NUM_4, SDL_SCANCODE_4},
|
||||||
|
{Key::NUM_5, SDL_SCANCODE_5},
|
||||||
|
{Key::NUM_6, SDL_SCANCODE_6},
|
||||||
|
{Key::NUM_7, SDL_SCANCODE_7},
|
||||||
|
{Key::NUM_8, SDL_SCANCODE_8},
|
||||||
|
{Key::NUM_9, SDL_SCANCODE_9},
|
||||||
|
{Key::LEFT_BRACKET, SDL_SCANCODE_LEFTBRACKET},
|
||||||
|
{Key::RIGHT_BRACKET, SDL_SCANCODE_RIGHTBRACKET},
|
||||||
|
{Key::SEMICOLON, SDL_SCANCODE_SEMICOLON},
|
||||||
|
{Key::APOSTROPHE, SDL_SCANCODE_APOSTROPHE},
|
||||||
|
{Key::COMMA, SDL_SCANCODE_COMMA},
|
||||||
|
{Key::PERIOD, SDL_SCANCODE_PERIOD},
|
||||||
|
{Key::SLASH, SDL_SCANCODE_SLASH},
|
||||||
|
{Key::BACKSLASH, SDL_SCANCODE_BACKSLASH},
|
||||||
|
{Key::GRAVE, SDL_SCANCODE_GRAVE}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputManager::registerAction(const std::string& actionName, const std::vector<Key>& keys, std::function<void(bool)> callback, const std::string& context) {
|
||||||
|
InputAction* storedAction = new InputAction{actionName, keys, callback};
|
||||||
|
for (const auto& key : keys) {
|
||||||
|
actionsByContextAndKey[context][key].emplace_back(storedAction);
|
||||||
|
}
|
||||||
|
std::cout << "Registered action: " << storedAction << " in context: " << context << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<InputManager::InputAction*> InputManager::getActionsByKey(const Key key) const {
|
||||||
|
std::vector<InputAction*> result;
|
||||||
|
|
||||||
|
for (const auto& [context, keyMap] : actionsByContextAndKey) {
|
||||||
|
auto it = keyMap.find(key);
|
||||||
|
if (it != keyMap.end()) {
|
||||||
|
result.insert(result.end(), it->second.begin(), it->second.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputManager::setActiveContext(const std::string& context) {
|
||||||
|
activeContext = context;
|
||||||
|
std::cout << "Active context set to: " << activeContext << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string InputManager::getActiveContext() const {
|
||||||
|
return activeContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_AppResult InputManager::handleEvent(SDL_EventType type, SDL_Event* const event) {
|
||||||
|
if (event->key.repeat) {
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
auto keyIt = std::ranges::find_if(keyMap, [&](const auto& pair)
|
||||||
|
{ return pair.second == event->key.scancode; });
|
||||||
|
|
||||||
|
if (keyIt != keyMap.end()) {
|
||||||
|
std::cout << "in != keymap.end" << std::endl;
|
||||||
|
|
||||||
|
Key pressedKey = keyIt->first;
|
||||||
|
auto keyActions = actionsByContextAndKey[activeContext];
|
||||||
|
auto it = keyActions.find(pressedKey);
|
||||||
|
if (it != keyActions.end()) {
|
||||||
|
for (auto& action : it->second) {
|
||||||
|
std::cout << "Action triggered: " << action->name << " in context: " << activeContext << std::endl;
|
||||||
|
action->callback(type == SDL_EVENT_KEY_UP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
22
src/InteractionComponent.cpp
Normal file
22
src/InteractionComponent.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "InteractionComponent.h"
|
||||||
|
|
||||||
|
#include "VEGO.h"
|
||||||
|
|
||||||
|
InteractionComponent::InteractionComponent(std::function<void(void*,void*)> callback) : interactionCallback(callback)
|
||||||
|
{
|
||||||
|
VEGO_Game().interactionManager->registerListener(this->entity->getComponentAsPointer<InteractionComponent>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractionComponent::interact(void* actor, void* data)
|
||||||
|
{
|
||||||
|
if (interactionCallback) {
|
||||||
|
interactionCallback(actor, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::shared_ptr<Vector2D> InteractionComponent::getPosition() // required for targeting strategy, return null to only allow explicit targeting
|
||||||
|
{
|
||||||
|
if (entity->hasComponent<TransformComponent>()) {
|
||||||
|
return std::make_shared<Vector2D>(entity->getComponent<TransformComponent>().position);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
16
src/InteractionEventdataStruct.cpp
Normal file
16
src/InteractionEventdataStruct.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include "InteractionEventdataStruct.h"
|
||||||
|
|
||||||
|
#include "VEGO.h"
|
||||||
|
#include "VEGO_Event.h"
|
||||||
|
|
||||||
|
void InteractionEventdataStruct::triggerEvent()
|
||||||
|
{
|
||||||
|
// TODO: if target is null && strategy is 0, error
|
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
SDL_zero(event);
|
||||||
|
event.type = vego::VEGO_Event_Interaction;
|
||||||
|
event.user.data1 = this;
|
||||||
|
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
}
|
||||||
90
src/InteractionManager.cpp
Normal file
90
src/InteractionManager.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "InteractionManager.h"
|
||||||
|
|
||||||
|
#include "InteractionEventdataStruct.h"
|
||||||
|
#include "InteractionListener.h"
|
||||||
|
#include "SDL3/SDL_init.h"
|
||||||
|
#include "VEGO_Event.h"
|
||||||
|
#include "Vector2D.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <ranges>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
InteractionManager::InteractionManager()
|
||||||
|
{
|
||||||
|
this->targetingFuncs.fill(nullptr);
|
||||||
|
this->targetingFuncs.at(static_cast<std::underlying_type<InteractionManager::TargetingStrategy>::type>(InteractionManager::TargetingStrategy::closest)) = [](Vector2D* reference, std::vector<std::shared_ptr<InteractionListener>> input) {
|
||||||
|
return std::shared_ptr<InteractionListener>();
|
||||||
|
};
|
||||||
|
this->targetingFuncs.at(static_cast<std::underlying_type<InteractionManager::TargetingStrategy>::type>(InteractionManager::TargetingStrategy::closest)) = [](Vector2D* reference, std::vector<std::shared_ptr<InteractionListener>> input) {
|
||||||
|
auto min = std::ranges::min_element(input, [&reference](std::shared_ptr<InteractionListener>& a, std::shared_ptr<InteractionListener>& b) {
|
||||||
|
std::shared_ptr<Vector2D> coordA = a->getPosition();
|
||||||
|
std::shared_ptr<Vector2D> coordB = b->getPosition();
|
||||||
|
|
||||||
|
if (coordB == nullptr) return true;
|
||||||
|
if (coordA == nullptr) return false;
|
||||||
|
|
||||||
|
return std::sqrt(std::pow(coordA->x - reference->x, 2) + std::pow(coordA->y - reference->y, 2)) < std::sqrt(std::pow(coordB->x - reference->x, 2) + std::pow(coordB->y - reference->y, 2));
|
||||||
|
});
|
||||||
|
return min == std::ranges::end(input) ? nullptr : *min;
|
||||||
|
};
|
||||||
|
this->targetingFuncs.at(static_cast<std::underlying_type<InteractionManager::TargetingStrategy>::type>(InteractionManager::TargetingStrategy::manhattenDistance)) = [](Vector2D* reference, std::vector<std::shared_ptr<InteractionListener>> input) {
|
||||||
|
auto min = std::ranges::min_element(input, [&reference](std::shared_ptr<InteractionListener>& a, std::shared_ptr<InteractionListener>& b) {
|
||||||
|
std::shared_ptr<Vector2D> coordA = a->getPosition();
|
||||||
|
std::shared_ptr<Vector2D> coordB = b->getPosition();
|
||||||
|
|
||||||
|
if (coordB == nullptr) return true;
|
||||||
|
if (coordA == nullptr) return false;
|
||||||
|
|
||||||
|
return (std::abs(coordA->x - reference->x) + std::abs(coordA->y - reference->y)) < (std::abs(coordB->x - reference->x) + std::abs(coordB->y - reference->y));
|
||||||
|
});
|
||||||
|
return min == std::ranges::end(input) ? nullptr : *min;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_AppResult InteractionManager::handleInteract(SDL_EventType type, SDL_Event* const event)
|
||||||
|
{
|
||||||
|
if (type != vego::VEGO_Event_Interaction) { // error handling
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
InteractionEventdataStruct* data = static_cast<InteractionEventdataStruct*>(event->user.data1);
|
||||||
|
|
||||||
|
std::shared_ptr<InteractionListener> listener = data->target.lock();
|
||||||
|
|
||||||
|
if (data->strategy != static_cast<std::underlying_type<InteractionManager::TargetingStrategy>::type>(InteractionManager::TargetingStrategy::none)) {
|
||||||
|
listener = this->targetingFuncs.at(data->strategy)(
|
||||||
|
data->targetingReference.get(),
|
||||||
|
this->listeners
|
||||||
|
| std::views::transform(&std::weak_ptr<InteractionListener>::lock)
|
||||||
|
| std::views::filter(&std::shared_ptr<InteractionListener>::operator bool)
|
||||||
|
| std::ranges::to<std::vector>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listener) {
|
||||||
|
listener->interact(data->actor, data->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_APP_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InteractionManager::registerListener(std::weak_ptr<InteractionListener> listener)
|
||||||
|
{
|
||||||
|
this->listeners.emplace_back(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t InteractionManager::registerTargetingFunc(TargetingFunc func)
|
||||||
|
{
|
||||||
|
auto it = std::ranges::find_if(this->targetingFuncs, [](const auto& func) {
|
||||||
|
return !func;
|
||||||
|
});
|
||||||
|
(*it) = func;
|
||||||
|
return std::distance(this->targetingFuncs.begin(), it);
|
||||||
|
}
|
||||||
@ -1,18 +1,22 @@
|
|||||||
#include "PowerupComponent.h"
|
#include "PickupComponent.h"
|
||||||
#include "GameInternal.h"
|
#include "GameInternal.h"
|
||||||
#include "CollisionHandler.h"
|
#include "CollisionHandler.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "HealthComponent.h"
|
#include "HealthComponent.h"
|
||||||
|
#include "SpriteComponent.h"
|
||||||
#include "StatEffectsComponent.h"
|
#include "StatEffectsComponent.h"
|
||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
|
#include "TextureManager.h"
|
||||||
|
#include "TransformComponent.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "VEGO.h"
|
||||||
|
|
||||||
PowerupComponent::PowerupComponent(std::function<void (Entity*)> func)
|
PickupComponent::PickupComponent(std::function<void (Entity*)> func)
|
||||||
{
|
{
|
||||||
this->pickupFunc = func;
|
this->pickupFunc = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerupComponent::update(uint_fast16_t diffTime)
|
void PickupComponent::update(uint_fast16_t diffTime)
|
||||||
{
|
{
|
||||||
Entity* player;
|
Entity* player;
|
||||||
if ((player = this->entity->getManager().getGame()->collisionHandler->getAnyIntersection<Entity*>(
|
if ((player = this->entity->getManager().getGame()->collisionHandler->getAnyIntersection<Entity*>(
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "AssetManager.h"
|
#include "PickupManager.h"
|
||||||
|
|
||||||
#include "TextureManager.h"
|
#include "TextureManager.h"
|
||||||
#include "SoundManager.h"
|
#include "SoundManager.h"
|
||||||
@ -12,17 +12,17 @@
|
|||||||
#include "Constants.h"
|
#include "Constants.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "Vector2D.h"
|
#include "Vector2D.h"
|
||||||
#include "PowerupComponent.h"
|
#include "PickupComponent.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <VEGO.h>
|
#include <VEGO.h>
|
||||||
|
|
||||||
#include "Textures.h"
|
#include "Textures.h"
|
||||||
|
|
||||||
AssetManager::AssetManager(Manager* manager) : man(manager) {}
|
PickupManager::PickupManager(Manager* manager) : man(manager) {}
|
||||||
|
|
||||||
AssetManager::~AssetManager() {}
|
PickupManager::~PickupManager() {}
|
||||||
|
|
||||||
void AssetManager::createPowerup(Vector2D pos, std::function<void (Entity*)> pickupFunc, Textures texture) {
|
void PickupManager::createPowerup(Vector2D pos, std::function<void (Entity*)> pickupFunc, Textures texture) {
|
||||||
|
|
||||||
auto& powerups(man->addEntity());
|
auto& powerups(man->addEntity());
|
||||||
powerups.addComponent<TransformComponent>(pos.x, pos.y, 32, 32, 1); //32x32 is standard size for objects
|
powerups.addComponent<TransformComponent>(pos.x, pos.y, 32, 32, 1); //32x32 is standard size for objects
|
||||||
@ -35,11 +35,11 @@ void AssetManager::createPowerup(Vector2D pos, std::function<void (Entity*)> pic
|
|||||||
}
|
}
|
||||||
|
|
||||||
powerups.addComponent<ColliderComponent>("powerup", 0.6f);
|
powerups.addComponent<ColliderComponent>("powerup", 0.6f);
|
||||||
powerups.addComponent<PowerupComponent>(pickupFunc);
|
powerups.addComponent<PickupComponent>(pickupFunc);
|
||||||
powerups.addGroup((size_t)Entity::GroupLabel::POWERUPS);
|
powerups.addGroup((size_t)Entity::GroupLabel::POWERUPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D AssetManager::calculateSpawnPosition()
|
Vector2D PickupManager::calculateSpawnPosition()
|
||||||
{
|
{
|
||||||
Vector2D spawnPos = Vector2D(-1, -1);
|
Vector2D spawnPos = Vector2D(-1, -1);
|
||||||
bool conflict = false;
|
bool conflict = false;
|
||||||
@ -63,9 +63,3 @@ Vector2D AssetManager::calculateSpawnPosition()
|
|||||||
}
|
}
|
||||||
return spawnPos;
|
return spawnPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerupType AssetManager::calculateType()
|
|
||||||
{
|
|
||||||
PowerupType type = PowerupType(rand() % 3);
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
#include "RenderObject.h"
|
#include "RenderObject.h"
|
||||||
#include "RenderManager.h"
|
#include "RenderManager.h"
|
||||||
|
|
||||||
RenderObject::RenderObject(int zIndex, RenderManager& renderManager) : zIndex(zIndex), renderManager(renderManager) {
|
RenderObject::RenderObject(int zIndex, RenderManager* renderManager) : zIndex(zIndex), renderManager(renderManager) {
|
||||||
renderManager.add(this);
|
renderManager->add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderObject::~RenderObject() {
|
RenderObject::~RenderObject() {
|
||||||
this->renderManager.remove(this);
|
this->renderManager->remove(this);
|
||||||
}
|
}
|
||||||
@ -6,7 +6,6 @@
|
|||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
|
|
||||||
#include "GameInternal.h"
|
#include "GameInternal.h"
|
||||||
#include "AssetManager.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mix_Music* SoundManager::loadMusic(const char* fileName)
|
Mix_Music* SoundManager::loadMusic(const char* fileName)
|
||||||
|
|||||||
@ -15,6 +15,9 @@ void TextureManager::addSingleTexture(Textures texture, const char* filePath) {
|
|||||||
|
|
||||||
SDL_SetTextureScaleMode(sdlTexture, this->scaleMode); // linear scaling results in blurry images
|
SDL_SetTextureScaleMode(sdlTexture, this->scaleMode); // linear scaling results in blurry images
|
||||||
this->texture_cache.emplace(texture, sdlTexture);
|
this->texture_cache.emplace(texture, sdlTexture);
|
||||||
|
if (filePath != nullptr) {
|
||||||
|
this->texture_references.emplace(texture, std::string(filePath));
|
||||||
|
}
|
||||||
std::cout << "Loaded texture at " << filePath << std::endl;
|
std::cout << "Loaded texture at " << filePath << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,9 @@ void TransformComponent::init()
|
|||||||
|
|
||||||
void TransformComponent::update(uint_fast16_t diffTime)
|
void TransformComponent::update(uint_fast16_t diffTime)
|
||||||
{
|
{
|
||||||
|
direction.x = direction.x > 0 ? 1 : direction.x < 0 ? -1 : 0;
|
||||||
|
direction.y = direction.y > 0 ? 1 : direction.y < 0 ? -1 : 0;
|
||||||
|
|
||||||
float multiplier = direction.x != 0 && direction.y != 0 ? 0.707 : 1; // normalizes vector; only works if directions are in increments of 45°
|
float multiplier = direction.x != 0 && direction.y != 0 ? 0.707 : 1; // normalizes vector; only works if directions are in increments of 45°
|
||||||
Vector2D positionChange(
|
Vector2D positionChange(
|
||||||
direction.x * this->getSpeed() * multiplier * diffTime * (1.f/1000),
|
direction.x * this->getSpeed() * multiplier * diffTime * (1.f/1000),
|
||||||
|
|||||||
@ -27,7 +27,7 @@ SDL_AppResult SDL_AppIterate(void *appstate) {
|
|||||||
return SDL_APP_SUCCESS;
|
return SDL_APP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
vego::game->handleEvents(); // bad
|
//vego::game->handleEvents(); // bad
|
||||||
|
|
||||||
Uint64 frameStart = SDL_GetTicks();
|
Uint64 frameStart = SDL_GetTicks();
|
||||||
|
|
||||||
@ -39,8 +39,9 @@ SDL_AppResult SDL_AppIterate(void *appstate) {
|
|||||||
return SDL_APP_CONTINUE;
|
return SDL_APP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// triggers upon every event
|
||||||
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
|
||||||
return SDL_APP_CONTINUE;
|
return vego::game->handleEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_AppQuit(void *appstate, SDL_AppResult result) {
|
void SDL_AppQuit(void *appstate, SDL_AppResult result) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user