0
0
mirror of https://github.com/Nimac0/SDL_Minigame synced 2026-01-12 13:43:41 +00:00

Compare commits

...

13 Commits

Author SHA1 Message Date
ineslelin
247d6cc173 removed stray music test in GameInternal.cpp 2024-06-18 19:39:51 +02:00
ineslelin
c4c8be5829 Merge remote-tracking branch 'origin/separation-refactor' into ref/sound 2024-06-18 19:23:07 +02:00
58e2bb0d30 Merge branch 'ref/nicole' into separation-refactor 2024-06-14 00:46:19 +02:00
7ffda89c9d Merge branch 'ref/beni' into separation-refactor 2024-06-14 00:00:48 +02:00
8c5c5c7215 removed define marco 2024-06-13 23:22:21 +02:00
5182312887 implemented GameFactory to instance an implementation of game 2024-05-29 10:02:14 +02:00
68a3e48131 rename Game->GameInternal 2024-05-29 09:07:54 +02:00
Sara Varga
5dfe42195f Merge branch 'ref/sara' into separation-refactor 2024-05-27 18:31:25 +02:00
Sara Varga
aa83280b6a #32 KeyboardController: movement working
projectiles need adjustments
2024-05-26 22:54:50 +02:00
31d7f42a31 ref(Animations, ECS impl):
dehardcoded Animations and moved ECS implementation + moved select screen function to chickengame
2024-05-20 21:05:20 +02:00
1f27d24de3 ref(Healthcomp, Stateffects) 2024-05-02 23:50:28 +02:00
Sara Varga
2e7a1b45cf refactor: removed Components.h file
consisted of includes of all components -> components included when not necessary
TODO: had to add 3 component includes in Entity.h because of template function; move if possible
2024-05-01 13:47:42 +02:00
Sara Varga
5dc61e6230 refactor: moved input polling from KeyboardController to input class 2024-05-01 13:07:48 +02:00
36 changed files with 545 additions and 338 deletions

View File

@ -16,11 +16,5 @@ struct Animation
}
};
enum AnimationType //TODO enum class
{
IDLE = 0,
WALK = 1
};

View File

@ -1,13 +0,0 @@
#pragma once
#include "ECS.h"
#include "Component.h"
#include "Manager.h"
#include "Entity.h"
#include "TransformComponent.h"
#include "SpriteComponent.h"
#include "KeyboardController.h"
#include "ColliderComponent.h"
#include "TileComponent.h"
#include "ProjectileComponent.h"
#include "HealthComponent.h"

View File

@ -24,10 +24,6 @@ constexpr int MAP_SIZE_Y = 20;
constexpr int SPAWN_ATTEMPTS = 20;
constexpr int BUFF_DURATION = 240;
constexpr int BUFF_VALUE = 1;
constexpr int PLAY_LOOPED = -1;
constexpr int PLAY_ONCE = 0;

View File

@ -9,6 +9,13 @@
#include "ECS.h"
#include "Constants.h"
// TODO: remove here if possible
// temporary fix: addComponent function template doesnt know TransformComponent -> error undefined type
// #include "KeyboardController.h"
#include "InputComponent.h"
#include "TransformComponent.h"
#include "SpriteComponent.h"
class Manager;
class Component;

View File

@ -1,76 +1,18 @@
#pragma once
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <functional>
#include <vector>
class GameInternal;
#include "Manager.h"
#include "Vector2D.h"
#include "Entity.h"
typedef std::function<void()> gamefunction;
class AssetManager;
class CollisionHandler;
class TextureManager;
class SoundManager;
class Map;
namespace engine {
extern gamefunction init;
extern gamefunction update;
extern Game* game; // this is a temporary fix to remove artifacts of chicken_game from the engine while the API is not yet finalized
}
class Game
{
// TODO: add managers here
class Game {
public:
Game();
~Game();
virtual ~Game() {}
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
void selectCharacters(const char* &playerSprite, const char* &enemySprite);
virtual void init() = 0;
virtual void update() = 0;
void handleEvents();
void update();
void render();
void clean();
bool running() const;
/* static */ SDL_Renderer* renderer = nullptr;
/* static */ SDL_Event event;
/* static */ CollisionHandler* collisionHandler;
/* static */ AssetManager* assets;
/* static */ TextureManager* textureManager;
/* static */ SoundManager* soundManager;
// moved globals
Manager manager;
Map* map; // game specific, might not be needed for all types of games
Entity& player1;
Entity& player2;
Entity& wall;
std::vector<Entity*>& tiles;
std::vector<Entity*>& players;
std::vector<Entity*>& projectiles;
std::vector<Entity*>& hearts;
std::vector<Entity*>& powerups;
// end moved globals
void refreshPlayers();
Entity::TeamLabel getWinner() const;
void setWinner(Entity::TeamLabel winningTeam);
private:
int counter = 0;
bool isRunning = false;
SDL_Window* window;
Entity::TeamLabel winner;
GameInternal* gameInternal; //!< \deprecated
};
// game factory include to simplify imports in implementation
#include "GameFactory.h"

59
include/GameFactory.h Normal file
View File

@ -0,0 +1,59 @@
#pragma once
#include <cassert>
#include <iostream>
#include <map>
#include <functional>
#include <string>
#include "Game.h"
class GameInternal;
class GameFactory {
public:
using CreateFunc = std::function<Game*()>;
static GameFactory& instance() {
static GameFactory factory;
return factory;
}
/*Game* get() {
assert(this->gameInstance != nullptr);
return this->gameInstance;
}*/
/*Game* create(GameInternal* gameInternal) {
Game* game = this->gameInstance == nullptr ? this->creator() : this->gameInstance; // TODO: error handling
game->gameInternal = gameInternal;
this->gameInstance = game;
return game;
}*/
void registerClass(const std::string& className, CreateFunc createFunc) {
this->creators[className] = createFunc;
}
Game* create(const std::string& className, GameInternal* gameInternal) {
auto it = this->creators.find(className);
if (it != creators.end()) {
Game* game = it->second();
game->gameInternal = gameInternal;
return game;
}
return nullptr;
}
private:
CreateFunc creator;
std::map<std::string, CreateFunc> creators;
};
/*
#define REGISTER_GAME(className) \
static bool registered_##className = []() { \
GameFactory::instance().registerClass(#className, []() -> Game* { return new className; }); \
return true; \
}();
*/

68
include/GameInternal.h Normal file
View File

@ -0,0 +1,68 @@
#pragma once
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <functional>
#include <vector>
#include "Manager.h"
#include "Vector2D.h"
#include "Entity.h"
typedef std::function<void()> gamefunction;
class AssetManager;
class CollisionHandler;
class TextureManager;
class SoundManager;
class Map;
class Game;
class GameInternal
{
public:
GameInternal();
~GameInternal();
void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen);
void selectCharacters(const char* &playerSprite, const char* &enemySprite);
void handleEvents();
void update();
void render();
void clean();
bool isRunning() const;
void setRunning(bool running);
/* static */ SDL_Renderer* renderer = nullptr;
/* static */ SDL_Event event;
/* static */ CollisionHandler* collisionHandler;
/* static */ AssetManager* assets;
/* static */ TextureManager* textureManager;
/* static */ SoundManager* soundManager;
// moved globals
Manager manager;
Map* map; // game specific, might not be needed for all types of games
std::vector<Entity*>& tiles;
std::vector<Entity*>& players;
std::vector<Entity*>& projectiles;
std::vector<Entity*>& hearts;
std::vector<Entity*>& powerups;
// end moved globals
void refreshPlayers();
Entity::TeamLabel getWinner() const;
void setWinner(Entity::TeamLabel winningTeam);
private:
Game* gameInstance;
int counter = 0;
bool running = false;
SDL_Window* window;
Entity::TeamLabel winner;
};

View File

@ -0,0 +1,17 @@
#pragma once
#include "GameFactory.h"
namespace vego {
template<typename T>
class GameRegistryHelper {
public:
GameRegistryHelper(const std::string& className) {
static_assert(std::is_base_of<Game, T>::value, "Your class must inherit from Game");
GameFactory::instance().registerClass(
className,
[]() -> Game* { return new T; }
);
};
};
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <string>
#include "Direction.h"
#include "Component.h"
@ -9,7 +10,7 @@ class HealthComponent : public Component
{
public:
HealthComponent(int health, Direction side) : health(health), side(side) {}
HealthComponent(int health, Direction side, std::string healthTexture) : health(health), side(side), healthTexture(healthTexture) {}
~HealthComponent() {}
void modifyHealth(int health = -1);
@ -26,4 +27,5 @@ private:
int health;
Direction side;
std::string healthTexture;
};

107
include/InputComponent.h Normal file
View File

@ -0,0 +1,107 @@
#pragma once
#include <SDL.h>
#include <map>
#include "Component.h"
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
};
class InputComponent : public Component
{
public:
InputComponent();
~InputComponent();
void init() override;
void update() override;
// void pollEvents();
bool isKeyDown(Key key);
private:
const Uint8* m_keyStates;
SDL_Scancode mapKeyToSDL(Key key);
std::map<Key, SDL_Scancode> m_keyMappings;
void InitKeyMappings();
};

View File

@ -1,44 +0,0 @@
#pragma once
#include <SDL.h>
#include "Component.h"
#include "Vector2D.h"
#include "Constants.h"
#include "SoundManager.h"
class TransformComponent;
class SpriteComponent;
class KeyboardController : public Component
{
public:
TransformComponent* transform;
const uint8_t* keystates = SDL_GetKeyboardState(NULL);
SDL_Scancode up;
SDL_Scancode down;
SDL_Scancode left;
SDL_Scancode right;
SDL_Scancode fire;
SpriteComponent* sprite;
//for attack cooldown in between shots
uint32_t lastFireTime = 0;
uint32_t fireCooldown = 1000; //in ms can be adjusted to change possible attack-speed
KeyboardController() = default;
KeyboardController(SDL_Scancode up, SDL_Scancode down, SDL_Scancode left, SDL_Scancode right, SDL_Scancode fire, Vector2D fireVelocity);
~KeyboardController() = default;
void init() override;
void update() override;
void modifyAtkSpeed(int8_t modifier);
private:
//for creation of projectiles
TransformComponent* player; //for starting position of projectile
Vector2D fireVelocity; //decide source of projectile and flying direction
// SoundManager* soundEffect = Game::assets->getSound;
//SoundManager* soundEffect = new SoundManager();
};

View File

@ -9,11 +9,11 @@
#include "Constants.h"
#include "Entity.h"
class Game;
class GameInternal;
class Manager
{
public:
Manager(Game* game) : game(game) {};
Manager(GameInternal* game) : game(game) {};
void update();
void draw();
@ -29,10 +29,10 @@ public:
Entity& addEntity();
Game* getGame() { return this->game; };
GameInternal* getGame() { return this->game; };
private:
Game* game;
GameInternal* game;
std::vector<std::unique_ptr<Entity>> entities;
std::array<std::vector<Entity*>, MAX_GROUPS> entitiesByGroup;
std::array<std::vector<Entity*>, MAX_TEAMS> entitiesByTeam;

View File

@ -3,7 +3,7 @@
#include <map>
#include <string>
class Game;
class GameInternal;
class Map
{
public:
@ -21,6 +21,6 @@ public:
* \return Boolean for success
*
*/
static void loadMap(const char* path, int sizeX, int sizeY, Game* game, const std::map<int, std::pair<std::string, bool>>* textureDict /* backreference */);
static void addTile(unsigned long id, int x, int y, Game* game, const std::map<int, std::pair<std::string, bool>>* textureDict);
static void loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map<int, std::pair<std::string, bool>>* textureDict /* backreference */);
static void addTile(unsigned long id, int x, int y, GameInternal* game, const std::map<int, std::pair<std::string, bool>>* textureDict);
};

View File

@ -5,7 +5,7 @@
#include "Entity.h"
class Game;
class GameInternal;
class PopupWindow {

View File

@ -13,7 +13,9 @@
// THROW_EGG,
// };
class Game;
// class Game;
class GameInternal;
/*!
*
@ -48,9 +50,9 @@ class SoundManager
//! \returns a pointer to Mix_Chunk, which is added to a map in the AssetManager
//! \sa AssetManager::AddSound(std::string id, const char* path)
static void playSound(Game* game, std::string sound, bool canOverlap, int loops, int volume, int channel); //!< Plays sound effects
static void playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel); //!< Plays sound effects
//! handles if sounds can overlap, how often they can loop, as well as the volume at which the specified sound effect should play
static void playMusic(Game* game, std::string sound, int loops, int volume, int ms); //<! Plays music
static void playMusic(GameInternal* game, std::string sound, int loops, int volume, int ms); //<! Plays music
//! handles how often the track should loop, as well as the volume at which the specified track should play
static void setSoundVolume(int volume, int channel); //!< Volume handling for the entire program

View File

@ -3,6 +3,7 @@
#include <map>
#include <SDL_render.h>
#include <memory>
#include <string>
#include "AnimationHandler.h"
#include "Component.h"
@ -15,7 +16,7 @@ class SpriteComponent : public Component
public:
int animationIndex = 0;
std::map<AnimationType, std::unique_ptr<Animation>> animations;
std::map<std::string, std::unique_ptr<Animation>>* animations = nullptr;
private:
TransformComponent* transform;
@ -32,7 +33,11 @@ private:
public:
SpriteComponent() = default;
SpriteComponent(const char* path);
SpriteComponent(const char* path, bool isAnimated);
SpriteComponent(
const char* path,
bool isAnimated,
std::map<std::string, std::unique_ptr<Animation>>* animationList,
std::string defaultAnimation);
~SpriteComponent();
void setTexture(const char* path);
@ -40,6 +45,6 @@ public:
void init() override;
void update() override;
void draw() override;
void playAnimation(AnimationType type);
void playAnimation(std::string type);
void setDirection(Direction direction);
};

View File

@ -18,9 +18,10 @@ public:
void init() override;
void update() override;
void modifyStatDur(Stats stat, int duration);
void modifyStatDur(Stats stat, int duration, int value);
void modifyStatValue(Stats stat, int modifier);
void resetStatValue(Stats stat);
private:
std::array<int, MAX_STATS> buffs = { 0 };

View File

@ -14,7 +14,8 @@ public:
int width = 32;
int scale = 1;
int speed = 3;
int getSpeed() { return speed + speedMod; };
void resetSpeedMod() { speedMod = 0; };
TransformComponent();
explicit TransformComponent(int scale);
@ -26,4 +27,8 @@ public:
void update() override;
void setPositionAfterCollision(Vector2D& positionChange);
void modifySpeed(int8_t modifier);
private:
int speed = 3;
int speedMod = 0;
};

View File

@ -2,8 +2,8 @@
#include "TextureManager.h"
#include "SoundManager.h"
#include "Components.h"
#include "Game.h"
#include "ProjectileComponent.h"
#include "GameInternal.h"
#include "TransformComponent.h"
@ -11,7 +11,6 @@
#include "ColliderComponent.h"
#include "Constants.h"
#include "Entity.h"
#include "Game.h"
#include "Vector2D.h"
#include "PowerupComponent.h"
#include <iostream>

View File

@ -2,7 +2,7 @@
#include "CollisionHandler.h"
#include "Entity.h"
#include "Game.h"
#include "GameInternal.h"
#include "TransformComponent.h"
#include <iostream>

View File

@ -30,7 +30,7 @@ void Entity::delGroup(Group mGroup)
groupBitSet[mGroup] = false;
}
std::bitset<MAX_GROUPS> Entity::getGroupBitSet()
std::bitset<MAX_GROUPS> Entity::getGroupBitSet()
{
return groupBitSet;
}

View File

@ -1,10 +1,12 @@
#include "Game.h"
#include "GameInternal.h"
#include <SDL_error.h>
#include "CollisionHandler.h"
#include "Components.h"
#include "AssetManager.h"
#include "SoundManager.h"
// #include "KeyboardController.h"
#include "TileComponent.h"
#include "Direction.h"
#include "Entity.h"
#include "HealthComponent.h"
@ -12,31 +14,28 @@
#include "TextureManager.h"
#include "StatEffectsComponent.h"
#include "Constants.h"
#include "Game.h"
#include "GameFactory.h"
Game* engine::game = nullptr; // will be initialized in constructor
Game::Game() :
GameInternal::GameInternal() :
manager(this),
tiles(manager.getGroup((size_t)Entity::GroupLabel::MAPTILES)),
tiles(manager.getGroup((size_t)Entity::GroupLabel::MAPTILES)),
players(manager.getGroup((size_t)Entity::GroupLabel::PLAYERS)),
projectiles(manager.getGroup((size_t)Entity::GroupLabel::PROJECTILE)),
hearts(manager.getGroup((size_t)Entity::GroupLabel::HEARTS)),
powerups(manager.getGroup((size_t)Entity::GroupLabel::POWERUPS)),
player1(manager.addEntity()),
player2(manager.addEntity()),
wall(manager.addEntity())
{
engine::game = this;
};
powerups(manager.getGroup((size_t)Entity::GroupLabel::POWERUPS))
//player1(manager.addEntity()),
//player2(manager.addEntity())
{};
Game::~Game() = default;
GameInternal::~GameInternal() = default;
void Game::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
void GameInternal::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen)
{
Game::assets = new AssetManager(&manager);
Game::textureManager = new TextureManager(&manager);
Game::soundManager = new SoundManager();
Game::collisionHandler = new CollisionHandler(manager); // why does this use a referrence, but AssetManager a pointer?
GameInternal::assets = new AssetManager(&manager);
GameInternal::textureManager = new TextureManager(&manager);
GameInternal::soundManager = new SoundManager();
GameInternal::collisionHandler = new CollisionHandler(manager); // why does this use a referrence, but AssetManager a pointer?
int flags = 0;
if (fullscreen)
@ -82,7 +81,7 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo
}
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_Texture* backgroundTexture = Game::textureManager->loadTexture("assets/startscreen.png");
SDL_Texture* backgroundTexture = GameInternal::textureManager->loadTexture("assets/startscreen.png");
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, backgroundTexture, NULL, NULL);
@ -104,7 +103,7 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo
while (!hasQuit)
{
SDL_PollEvent(&event);
if (event.type == SDL_QUIT)
{
hasQuit = true;
@ -129,18 +128,18 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo
if (hasQuit)
{
this->isRunning = false;
this->setRunning(false);
return;
}
engine::init();
// engine::init(); // temporarily moved down to access groups at engine init call
// character selection
const char* player1Sprite;
const char* player2Sprite;
selectCharacters(player1Sprite, player2Sprite);
if (this->isRunning == false) return;
if (this->isRunning() == false) return;
map = new Map();
@ -157,31 +156,34 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo
assets->addSoundEffect("steps", "assets/sound/steps.wav");
// loading music
assets->addMusic("background_music", "assets/sound/background_music.mp3");
// assets->addMusic("background_music", "assets/sound/background_music.mp3");
//ecs implementation
player1.setTeam(Entity::TeamLabel::BLUE);
player1.addComponent<TransformComponent>(80,80,2); //posx, posy, scale
player1.addComponent<SpriteComponent>(player1Sprite, true); //adds sprite (32x32px), path needed
player1.addComponent<KeyboardController>(SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_A, SDL_SCANCODE_D, SDL_SCANCODE_E, Vector2D(2, 0));//custom keycontrols can be added
player1.addComponent<ColliderComponent>("player", 0.8f); //adds tag (for further use, reference tag)
player1.addComponent<HealthComponent>(5, Direction::LEFT);
player1.addComponent<StatEffectsComponent>();
player1.addGroup((size_t) Entity::GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order
// player1.setTeam(Entity::TeamLabel::BLUE);
// player1.addComponent<TransformComponent>(80,80,2); //posx, posy, scale
// player1.addComponent<SpriteComponent>(player1Sprite, true); //adds sprite (32x32px), path needed
// player1.addComponent<KeyboardController>(SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_A, SDL_SCANCODE_D, SDL_SCANCODE_E, Vector2D(2, 0));//custom keycontrols can be added
// player1.addComponent<ColliderComponent>("player", 0.8f); //adds tag (for further use, reference tag)
// player1.addComponent<HealthComponent>(5, Direction::LEFT, "assets/heart.png");
// player1.addComponent<StatEffectsComponent>();
// player1.addGroup((size_t) Entity::GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order
player2.setTeam(Entity::TeamLabel::RED);
player2.addComponent<TransformComponent>(600, 500, 2);
player2.addComponent<SpriteComponent>(player2Sprite, true);
player2.addComponent<KeyboardController>(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_RCTRL, Vector2D(-2, 0));
player2.addComponent<ColliderComponent>("enemy", 0.8f);
player2.addComponent<HealthComponent>(5, Direction::RIGHT);
player2.addComponent<StatEffectsComponent>();
player2.addGroup((size_t) Entity::GroupLabel::PLAYERS);
// player2.setTeam(Entity::TeamLabel::RED);
// player2.addComponent<TransformComponent>(600, 500, 2);
// player2.addComponent<SpriteComponent>(player2Sprite, true);
// player2.addComponent<KeyboardController>(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_RCTRL, Vector2D(-2, 0));
// player2.addComponent<ColliderComponent>("enemy", 0.8f);
// player2.addComponent<HealthComponent>(5, Direction::RIGHT, "assets/heart.png");
// player2.addComponent<StatEffectsComponent>();
// player2.addGroup((size_t) Entity::GroupLabel::PLAYERS);
this->gameInstance = GameFactory::instance().create("Chickengame", this); //!< \todo Should be specified via a config file
this->gameInstance->init();
}
void Game::selectCharacters(const char* &playerSprite, const char* &enemySprite)
void GameInternal::selectCharacters(const char* &playerSprite, const char* &enemySprite)
{
// TODO: move this whereever it makes sense (maybe game as a member)
std::map<int, std::pair<const char*, const char*>> characterSprites;
@ -249,7 +251,7 @@ void Game::selectCharacters(const char* &playerSprite, const char* &enemySprite)
}
}
SDL_Texture* backgroundTexture = Game::textureManager->loadTexture("assets/characterSelection.png");
SDL_Texture* backgroundTexture = GameInternal::textureManager->loadTexture("assets/characterSelection.png");
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, backgroundTexture, NULL, NULL);
@ -268,22 +270,22 @@ void Game::selectCharacters(const char* &playerSprite, const char* &enemySprite)
if (hasQuit)
{
this->isRunning = false;
this->setRunning(false);
return;
}
playerSprite = characterSprites.find(playerSelection)->second.second;
enemySprite = characterSprites.find(enemySelection)->second.second;
this->isRunning = true;
this->setRunning(true);
}
void Game::handleEvents()
void GameInternal::handleEvents()
{
SDL_PollEvent(&event);
switch (event.type)
{
case SDL_QUIT: this->isRunning = false;
case SDL_QUIT: this->setRunning(false);
break;
default:
@ -291,15 +293,15 @@ void Game::handleEvents()
}
}
void Game::update()
void GameInternal::update()
{
manager.refresh();
manager.update();
engine::update(); // TODO: this might have to be split up into two update functions, before and after manager...
this->gameInstance->update(); // TODO: this might have to be split up into two update functions, before and after manager...
}
void Game::render()
void GameInternal::render()
{
SDL_RenderClear(renderer);
for (auto& t : tiles)
@ -310,7 +312,7 @@ void Game::render()
for (auto& p : players)
p->draw();
for (auto& p : projectiles)
p->draw();
@ -320,7 +322,7 @@ void Game::render()
SDL_RenderPresent(renderer);
}
void Game::clean()
void GameInternal::clean()
{
delete(textureManager);
SDL_DestroyRenderer(renderer);
@ -329,18 +331,23 @@ void Game::clean()
std::cout << "Game Cleaned!" << std::endl;
}
bool Game::running() const
bool GameInternal::isRunning() const
{
return isRunning;
return running;
}
void Game::setWinner(Entity::TeamLabel winningTeam)
void GameInternal::setRunning(bool running)
{
this->running = running;
}
void GameInternal::setWinner(Entity::TeamLabel winningTeam)
{
this->winner = winningTeam;
this->isRunning = false;
this->setRunning(false);
}
Entity::TeamLabel Game::getWinner() const
Entity::TeamLabel GameInternal::getWinner() const
{
return this->winner;
}

View File

@ -2,7 +2,7 @@
#include "SDL_error.h"
#include "TextureManager.h"
#include "Game.h"
#include "GameInternal.h"
GameObject::GameObject(const char* texturesheet, int x, int y)
{

View File

@ -1,9 +1,8 @@
#include "HealthComponent.h"
#include "Components.h"
#include "Direction.h"
#include "Entity.h"
#include "Game.h"
#include "GameInternal.h"
#include <cstdio>
void HealthComponent::init()
@ -58,7 +57,7 @@ void HealthComponent::createHeartComponents(int x)
{
auto& heart(this->entity->getManager().addEntity());
heart.addComponent<TransformComponent>(x,5,2);
heart.addComponent<SpriteComponent>("assets/heart.png");
heart.addComponent<SpriteComponent>(this->healthTexture.data());
heart.addGroup((size_t)Entity::GroupLabel::HEARTS);
heart.setTeam(this->entity->getTeam());
}

121
src/InputComponent.cpp Normal file
View File

@ -0,0 +1,121 @@
#include "InputComponent.h"
InputComponent::InputComponent()
{
m_keyStates = SDL_GetKeyboardState(NULL);
InitKeyMappings();
}
InputComponent::~InputComponent() = default;
void InputComponent::init()
{
// m_keyStates = SDL_GetKeyboardState(NULL);
// InitKeyMappings();
}
void InputComponent::update()
{
SDL_PumpEvents();
}
bool InputComponent::isKeyDown(Key key)
{
return m_keyStates[mapKeyToSDL(key)];
}
SDL_Scancode InputComponent::mapKeyToSDL(Key key)
{
auto it = m_keyMappings.find(key);
if (it == m_keyMappings.end())
{
return SDL_SCANCODE_UNKNOWN;
}
return it->second;
}
void InputComponent::InitKeyMappings()
{
m_keyMappings =
{
{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}
};
}

View File

@ -1,85 +0,0 @@
#include "KeyboardController.h"
#include "Game.h"
#include "Components.h"
#include "AssetManager.h"
#include "SpriteComponent.h"
KeyboardController::KeyboardController(SDL_Scancode up, SDL_Scancode down, SDL_Scancode left, SDL_Scancode right, SDL_Scancode fire, Vector2D fireVelocity)
{
this->up = up;
this->down = down;
this->left = left;
this->right = right;
this->fire = fire;
this->fireVelocity = fireVelocity;
}
void KeyboardController::init()
{
sprite = &entity->getComponent<SpriteComponent>();
transform = &entity->getComponent<TransformComponent>();
}
void KeyboardController::update()
{
// TODO: move this, this is definitely the wrong place to put this but i wanted to put it somewhere to test it
SoundManager::playMusic(this->entity->getManager().getGame(), "background_music", PLAY_LOOPED, 10, 15000);
transform->direction.x = 0;
transform->direction.y = 0;
sprite->playAnimation(IDLE);
if (keystates[this->up]) {
transform->direction.y = -1;
sprite->playAnimation(WALK);
SoundManager::playSound(this->entity->getManager().getGame(), "steps", false, PLAY_ONCE, MAX_VOLUME, -1);
}
if (keystates[this->left]) {
transform->direction.x = -1;
sprite->playAnimation(WALK);
sprite->setDirection(Direction::LEFT);
SoundManager::playSound(this->entity->getManager().getGame(), "steps", false, PLAY_ONCE, MAX_VOLUME, -1);
}
if (keystates[this->down]) {
transform->direction.y = 1;
sprite->playAnimation(WALK);
SoundManager::playSound(this->entity->getManager().getGame(), "steps", false, PLAY_ONCE, MAX_VOLUME, -1);
}
if (keystates[this->right]) {
transform->direction.x = 1;
sprite->playAnimation(WALK);
sprite->setDirection(Direction::RIGHT);
SoundManager::playSound(this->entity->getManager().getGame(), "steps", false, PLAY_ONCE, MAX_VOLUME, -1);
}
if (keystates[this->fire]) {
Uint32 currentTicks = SDL_GetTicks();
if (currentTicks - lastFireTime >= fireCooldown) {
player = &entity->getComponent<TransformComponent>();
//checks player source via the firing velocity
//TODO: adding actual projectile textures
if (fireVelocity.x > 0) {
sprite->setDirection(Direction::RIGHT);
this->entity->getManager().getGame()->assets->createProjectile(Vector2D(player->position.x, player->position.y), fireVelocity,
1, 180, 2, "assets/egg.png", this->entity->getTeam());
}
else {
sprite->setDirection(Direction::LEFT);
this->entity->getManager().getGame()->assets->createProjectile(Vector2D(player->position.x, player->position.y), fireVelocity,
1, 180, 2, "assets/egg.png", this->entity->getTeam());
}
lastFireTime = currentTicks;
}
}
}
void KeyboardController::modifyAtkSpeed(int8_t modifier)
{
this->fireCooldown -= modifier * 400;
}

View File

@ -6,11 +6,11 @@
#include <utility>
#include "Constants.h"
#include "Game.h"
#include "GameInternal.h"
#include "SDL_error.h"
#include "TileComponent.h"
void Map::loadMap(const char* path, int sizeX, int sizeY, Game* game, const std::map<int, std::pair<std::string, bool>>* textureDict /* backreference */)
void Map::loadMap(const char* path, int sizeX, int sizeY, GameInternal* game, const std::map<int, std::pair<std::string, bool>>* textureDict /* backreference */)
{
std::string tileIDstr;
char singleChar = 0;
@ -56,7 +56,7 @@ void Map::loadMap(const char* path, int sizeX, int sizeY, Game* game, const std:
mapFile.close();
}
void Map::addTile(unsigned long id, int x, int y, Game* game, const std::map<int, std::pair<std::string, bool>>* textureDict) // tile entity
void Map::addTile(unsigned long id, int x, int y, GameInternal* game, const std::map<int, std::pair<std::string, bool>>* textureDict) // tile entity
{
auto& tile(game->manager.addEntity());
tile.addComponent<TileComponent>(x, y, TILE_SIZE, TILE_SIZE, id, textureDict);

View File

@ -4,7 +4,7 @@
#include "Entity.h"
#include "PopupWindow.h"
#include "TextureManager.h"
#include "Game.h"
#include "GameInternal.h"
PopupWindow::PopupWindow(const char* title, const std::string &message) :
continueGame(false), interacted(false) {

View File

@ -1,5 +1,5 @@
#include "PowerupComponent.h"
#include "Game.h"
#include "GameInternal.h"
#include "CollisionHandler.h"
#include "Entity.h"
#include "HealthComponent.h"

View File

@ -1,9 +1,10 @@
#include "ProjectileComponent.h"
#include "CollisionHandler.h"
#include "Components.h"
#include "SoundManager.h"
#include "TransformComponent.h"
#include "Entity.h"
#include "Game.h"
#include "GameInternal.h"
#include "HealthComponent.h"
#include "Vector2D.h"
#include <cassert>

View File

@ -4,7 +4,7 @@
#include <string>
#include <iostream>
#include "Game.h"
#include "GameInternal.h"
#include "AssetManager.h"
Mix_Music* SoundManager::loadMusic(const char* fileName)
@ -48,7 +48,7 @@ Mix_Chunk* SoundManager::loadSound(const char* fileName)
}
// TODO: using a string here is probably... a less than stellar method, figure out how to change this
void SoundManager::playSound(Game* game, std::string sound, bool canOverlap, int loops, int volume, int channel)
void SoundManager::playSound(GameInternal* game, std::string sound, bool canOverlap, int loops, int volume, int channel)
{
if(!canOverlap)
{
@ -67,7 +67,7 @@ void SoundManager::playSound(Game* game, std::string sound, bool canOverlap, int
}
}
void SoundManager::playMusic(Game* game, std::string music, int loops, int volume, int ms)
void SoundManager::playMusic(GameInternal* game, std::string music, int loops, int volume, int ms)
{
if (Mix_PlayingMusic() != 0 || Mix_Fading() == Mix_Fading::MIX_FADING_IN)
return;

View File

@ -9,7 +9,7 @@
#include "TextureManager.h"
#include "Entity.h"
#include "TransformComponent.h"
#include "Game.h"
#include "GameInternal.h"
#include "Manager.h"
SpriteComponent::SpriteComponent(const char* path)
@ -17,14 +17,17 @@ SpriteComponent::SpriteComponent(const char* path)
this->texturePath = path;
}
SpriteComponent::SpriteComponent(const char* path, bool isAnimated)
SpriteComponent::SpriteComponent(
const char* path,
bool isAnimated,
std::map<std::string, std::unique_ptr<Animation>>* animationMap,
std::string defaultAnimation)
{
animated = isAnimated;
animations.emplace(IDLE, std::make_unique<Animation>((uint8_t)AnimationType::IDLE, 2, 200));
animations.emplace(WALK, std::make_unique<Animation>((uint8_t)AnimationType::WALK, 2, 200));
animations = animationMap;
playAnimation(IDLE);
playAnimation(defaultAnimation);
this->texturePath = path;
}
@ -71,14 +74,14 @@ void SpriteComponent::draw()
this->entity->getManager().getGame()->textureManager->draw(this->entity->getManager().getGame()->renderer, this->texture, this->srcRect, this->destRect, this->animated && this->flipped);
}
void SpriteComponent::playAnimation(AnimationType type)
void SpriteComponent::playAnimation(std::string type)
{
this->animationIndex = animations.at(type)->index;
this->frames = animations.at(type)->frames;
this->speed = animations.at(type)->speed;
this->animationIndex = animations->at(type)->index;
this->frames = animations->at(type)->frames;
this->speed = animations->at(type)->speed;
}
void SpriteComponent::setDirection(Direction direction)
void SpriteComponent::setDirection(Direction direction)
{
this->flipped = direction == Direction::RIGHT;
}

View File

@ -1,7 +1,7 @@
#include "StatEffectsComponent.h"
#include "Entity.h"
#include "TransformComponent.h"
#include "KeyboardController.h"
// #include "KeyboardController.h"
#include <algorithm>
#include <iostream>
@ -15,15 +15,15 @@ void StatEffectsComponent::update()
if (this->buffs.at(i) == 0) continue;
if (this->buffs.at(i) - 1 == 0)
{
this->modifyStatValue((Stats)i, BUFF_VALUE * -1);
this->resetStatValue((Stats)i);
}
this->buffs.at(i) -= 1;
}
}
void StatEffectsComponent::modifyStatDur(Stats stat, int duration)
void StatEffectsComponent::modifyStatDur(Stats stat, int duration, int value)
{
if(this->buffs.at((uint8_t)stat) == 0) this->modifyStatValue(stat, BUFF_VALUE);
if(this->buffs.at((uint8_t)stat) == 0) this->modifyStatValue(stat, value);
this->buffs.at((uint8_t)stat) += duration;
}
@ -35,7 +35,21 @@ void StatEffectsComponent::modifyStatValue(Stats stat, int modifier) //modifier
this->entity->getComponent<TransformComponent>().modifySpeed(modifier);
break;
case Stats::ATTACK_SPEED:
this->entity->getComponent<KeyboardController>().modifyAtkSpeed(modifier);
// this->entity->getComponent<KeyboardController>().modifyAtkSpeed(modifier);
break;
default: break;
}
}
void StatEffectsComponent::resetStatValue(Stats stat)
{
switch (stat)
{
case Stats::MOVEMENT_SPEED:
this->entity->getComponent<TransformComponent>().resetSpeedMod();
break;
case Stats::ATTACK_SPEED:
// this->entity->getComponent<KeyboardController>().resetAtkSpeedMod();
break;
default: break;
}

View File

@ -4,7 +4,7 @@
#include <stdexcept>
#include <string>
#include "Game.h"
#include "GameInternal.h"
SDL_Texture* TextureManager::loadTexture(const char* fileName)
{

View File

@ -4,7 +4,7 @@
#include "ColliderComponent.h"
#include "Constants.h"
#include "Entity.h"
#include "Game.h"
#include "GameInternal.h"
#include "Vector2D.h"
#include <cstdio>
#include <initializer_list>
@ -56,8 +56,8 @@ void TransformComponent::update()
float multiplier = direction.x != 0 && direction.y != 0 ? 0.707 : 1; // normalizes vector; only works if directions are in increments of 45°
Vector2D positionChange(
direction.x * speed * multiplier,
direction.y * speed * multiplier
direction.x * this->getSpeed() * multiplier,
direction.y * this->getSpeed() * multiplier
);
if (this->entity->hasGroup((size_t)Entity::GroupLabel::PLAYERS)){
@ -69,7 +69,7 @@ void TransformComponent::update()
void TransformComponent::modifySpeed(int8_t modifier)
{
this->speed += modifier;
this->speedMod += modifier;
}
void TransformComponent::setPositionAfterCollision(Vector2D& positionChange)

View File

@ -2,11 +2,11 @@
#include <ctime>
#include "Entity.h"
#include "Game.h"
#include "GameInternal.h"
#include "Constants.h"
#include "PopupWindow.h"
Game* game = nullptr;
GameInternal* game = nullptr;
int main(int argc, char* argv[])
{
@ -18,10 +18,10 @@ int main(int argc, char* argv[])
Uint32 frameStart;
int frameTime;
game = new Game();
game = new GameInternal();
game->init("No_Name_Chicken_Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_SIZE_WIDTH, SCREEN_SIZE_HEIGHT, false);
while (game->running()) {
while (game->isRunning()) {
frameStart = SDL_GetTicks();
game->handleEvents();