From 25414524a0fd9fad65a469db19c6a90ed09c1968 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Mon, 18 Nov 2024 16:20:41 +0100 Subject: [PATCH] new main logic & new time keeping --- include/AssetManager.h | 2 +- include/ColliderComponent.h | 2 +- include/Component.h | 3 ++- include/Entity.h | 2 +- include/Game.h | 2 +- include/GameInternal.h | 7 +++-- include/InputComponent.h | 2 +- include/Manager.h | 2 +- include/PowerupComponent.h | 2 +- include/ProjectileComponent.h | 6 ++--- include/SpriteComponent.h | 2 +- include/StatEffectsComponent.h | 2 +- include/TransformComponent.h | 4 +-- src/AssetManager.cpp | 2 +- src/ColliderComponent.cpp | 4 +-- src/Entity.cpp | 4 +-- src/GameInternal.cpp | 26 +++++++++++------- src/InputComponent.cpp | 2 +- src/Manager.cpp | 4 +-- src/PowerupComponent.cpp | 2 +- src/ProjectileComponent.cpp | 6 ++--- src/SoundManager.cpp | 1 - src/SpriteComponent.cpp | 6 ++--- src/StatEffectsComponent.cpp | 10 +++---- src/TransformComponent.cpp | 6 ++--- src/_Init.cpp | 48 ++++++++++++++++++++++++++++++++++ src/main.cpp | 42 ----------------------------- 27 files changed, 109 insertions(+), 92 deletions(-) create mode 100644 src/_Init.cpp delete mode 100644 src/main.cpp diff --git a/include/AssetManager.h b/include/AssetManager.h index 212828c..541fa04 100644 --- a/include/AssetManager.h +++ b/include/AssetManager.h @@ -24,7 +24,7 @@ public: AssetManager(Manager* manager); ~AssetManager(); - void createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, int speed, const char* texturePath, Entity* owner); + void createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, float speed, const char* texturePath, Entity* owner); void createPowerup(Vector2D pos, std::function pickupFunc, std::string texturePath); Vector2D calculateSpawnPosition(); diff --git a/include/ColliderComponent.h b/include/ColliderComponent.h index b49fd33..91280c0 100644 --- a/include/ColliderComponent.h +++ b/include/ColliderComponent.h @@ -22,7 +22,7 @@ public: ColliderComponent(const char* tag, float hitboxScale); void init() override; - void update() override; + void update(uint_fast16_t diffTime) override; void removeCollision(); void handleCollision(Vector2D& characterPos, SDL_Rect& characterCollider, SDL_Rect& componentCollider); diff --git a/include/Component.h b/include/Component.h index 566fee9..5003dc3 100644 --- a/include/Component.h +++ b/include/Component.h @@ -1,5 +1,6 @@ #pragma once +#include class Entity; class Component @@ -8,7 +9,7 @@ public: Entity* entity; virtual void init() {} - virtual void update() {} + virtual void update(uint_fast16_t diffTime) {} virtual ~Component() = default; }; \ No newline at end of file diff --git a/include/Entity.h b/include/Entity.h index aa067a4..0ce952c 100644 --- a/include/Entity.h +++ b/include/Entity.h @@ -59,7 +59,7 @@ public: explicit Entity(Manager& mManager) : manager(mManager) { }; - void update() const; //!< Call each frame to update all components + void update(uint_fast16_t diffTime) const; //!< Call each frame to update all components bool isActive() const { return this->active; } //!< \sa destroy() //! Mark for destruction for Manager::refresh() and disables collision diff --git a/include/Game.h b/include/Game.h index c1b1aa3..3eb990d 100644 --- a/include/Game.h +++ b/include/Game.h @@ -8,7 +8,7 @@ public: virtual ~Game() {} virtual void init() = 0; - virtual void update() = 0; + virtual void update(uint_fast16_t diffTime) = 0; GameInternal* gameInternal; //!< \deprecated }; diff --git a/include/GameInternal.h b/include/GameInternal.h index 57b9aac..7cb3b1f 100644 --- a/include/GameInternal.h +++ b/include/GameInternal.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -26,10 +27,10 @@ public: GameInternal(); ~GameInternal(); - void init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen); + SDL_AppResult init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen); void handleEvents(); - void update(); + void update(Uint64 frameTime); void render(); void clean(); bool isRunning() const; @@ -63,4 +64,6 @@ private: int counter = 0; bool running = true; SDL_Window* window; + + Uint64 lastFrameTime = 0; }; diff --git a/include/InputComponent.h b/include/InputComponent.h index 8d62202..31cd381 100644 --- a/include/InputComponent.h +++ b/include/InputComponent.h @@ -94,7 +94,7 @@ public: ~InputComponent(); void init() override; - void update() override; + void update(uint_fast16_t diffTime) override; bool isKeyDown(Key key); diff --git a/include/Manager.h b/include/Manager.h index 8b9ceb3..a796e42 100644 --- a/include/Manager.h +++ b/include/Manager.h @@ -24,7 +24,7 @@ class Manager public: Manager(GameInternal* game) : game(game) {}; - void update(); //!< \sa Entity::update() + void update(uint_fast16_t diffTime); //!< \sa Entity::update() //! Disables all functionality of entities marked for destruction //! \sa Entity::destroy() void refresh(); diff --git a/include/PowerupComponent.h b/include/PowerupComponent.h index 53f365b..a0a3f36 100644 --- a/include/PowerupComponent.h +++ b/include/PowerupComponent.h @@ -9,7 +9,7 @@ public: PowerupComponent(std::function func); ~PowerupComponent() {}; - void update() override; + void update(uint_fast16_t diffTime) override; private: std::function pickupFunc; diff --git a/include/ProjectileComponent.h b/include/ProjectileComponent.h index 4db0bfd..da67ff6 100644 --- a/include/ProjectileComponent.h +++ b/include/ProjectileComponent.h @@ -16,14 +16,14 @@ public: ~ProjectileComponent() {} void init() override; - void update() override; + void update(uint_fast16_t diffTime) override; private: TransformComponent* transformComponent; int range = 0; - int speed = 0; - int distance = 0; + float speed = 0; + float distance = 0; Entity* owner = nullptr; diff --git a/include/SpriteComponent.h b/include/SpriteComponent.h index f8077cd..6966977 100644 --- a/include/SpriteComponent.h +++ b/include/SpriteComponent.h @@ -48,7 +48,7 @@ public: void setTexture(const char* path); void init() override; - void update() override; + void update(uint_fast16_t diffTime) override; void draw() override; void playAnimation(std::string type); void setDirection(Direction direction); diff --git a/include/StatEffectsComponent.h b/include/StatEffectsComponent.h index bc93f2b..ca32d05 100644 --- a/include/StatEffectsComponent.h +++ b/include/StatEffectsComponent.h @@ -16,7 +16,7 @@ public: ~StatEffectsComponent() {}; void init() override; - void update() override; + void update(uint_fast16_t diffTime) override; void modifyStatDur(Stats stat, int duration, int value); diff --git a/include/TransformComponent.h b/include/TransformComponent.h index 7a15aa4..c325fce 100644 --- a/include/TransformComponent.h +++ b/include/TransformComponent.h @@ -25,11 +25,11 @@ public: void init() override; /*! TODO: document usage of collision handler */ - void update() override; + void update(uint_fast16_t diffTime) override; void setPositionAfterCollision(Vector2D& positionChange); void modifySpeed(int8_t modifier); private: - int speed = 3; + int speed = 180; int speedMod = 0; }; diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index e4b1cf4..ef32ce8 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -46,7 +46,7 @@ Mix_Music* AssetManager::getMusic(std::string id) return music.at(id); } -void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, int speed, const char* texturePath, Entity* owner) { +void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, int scale, int range, float speed, const char* texturePath, Entity* owner) { auto& projectile(man->addEntity()); projectile.addComponent(pos.x, pos.y, 32, 32, scale); //32x32 is standard size for objects diff --git a/src/ColliderComponent.cpp b/src/ColliderComponent.cpp index 2275163..8cb2ad6 100644 --- a/src/ColliderComponent.cpp +++ b/src/ColliderComponent.cpp @@ -31,10 +31,10 @@ void ColliderComponent::init() } transform = &entity->getComponent(); - this->update(); + this->update(0); } -void ColliderComponent::update() +void ColliderComponent::update(uint_fast16_t diffTime) { collider.x = transform->position.x - (transform->width - transform->width * transform->scale * this->hitboxScale) / 2; collider.y = transform->position.y - (transform->width - transform->width * transform->scale * this->hitboxScale) / 2; diff --git a/src/Entity.cpp b/src/Entity.cpp index 60455c1..987626d 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -4,9 +4,9 @@ #include "Component.h" #include -void Entity::update() const +void Entity::update(uint_fast16_t diffTime) const { - for (auto const& c : components) c->update(); + for (auto const& c : components) c->update(diffTime); } bool Entity::hasGroup(Group mGroup) diff --git a/src/GameInternal.cpp b/src/GameInternal.cpp index d3a65dc..1e4eac3 100644 --- a/src/GameInternal.cpp +++ b/src/GameInternal.cpp @@ -13,6 +13,8 @@ #include "Game.h" #include "GameFactory.h" +#include + GameInternal::GameInternal() : manager(this), renderManager(), @@ -25,7 +27,7 @@ GameInternal::GameInternal() : GameInternal::~GameInternal() = default; -void GameInternal::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) +SDL_AppResult GameInternal::init(const char* title, int xpos, int ypos, int width, int height, bool fullscreen) { GameInternal::assets = new AssetManager(&manager); GameInternal::textureManager = new TextureManager(&manager); @@ -42,12 +44,12 @@ void GameInternal::init(const char* title, int xpos, int ypos, int width, int he { std::cout << "ERROR. Subsystem couldnt be initialized! " << SDL_GetError() << std::endl; SDL_ClearError(); - return; + return SDL_APP_FAILURE; } if (Mix_Init(MIX_INIT_MP3) != MIX_INIT_MP3) { std::cout << "ERROR. Subsystem couldnt be initialized!" << std::endl; - return; + return SDL_APP_FAILURE; } window = SDL_CreateWindow(title, width, height, flags); @@ -55,7 +57,7 @@ void GameInternal::init(const char* title, int xpos, int ypos, int width, int he { std::cout << "ERROR: Window couldnt be created! " << SDL_GetError() << std::endl; SDL_ClearError(); - return; + return SDL_APP_FAILURE; } // bad @@ -72,7 +74,7 @@ void GameInternal::init(const char* title, int xpos, int ypos, int width, int he { std::cout << "ERROR: Renderer couldnt be created! " << SDL_GetError() << std::endl; SDL_ClearError(); - return; + return SDL_APP_FAILURE; } SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); @@ -80,7 +82,7 @@ void GameInternal::init(const char* title, int xpos, int ypos, int width, int he { std::cout << "ERROR: Mixer couldnt be initialized! " << SDL_GetError() << std::endl; SDL_ClearError(); - return; + return SDL_APP_FAILURE; } Mix_Volume(-1, MIX_MAX_VOLUME); @@ -95,6 +97,8 @@ void GameInternal::init(const char* title, int xpos, int ypos, int width, int he this->gameInstance = GameFactory::instance().create(this); this->gameInstance->init(); + + return SDL_APP_CONTINUE; } void GameInternal::handleEvents() @@ -111,12 +115,16 @@ void GameInternal::handleEvents() } } -void GameInternal::update() +void GameInternal::update(Uint64 frameTime) { manager.refresh(); - manager.update(); - this->gameInstance->update(); // TODO: this might have to be split up into two update functions, before and after manager... + uint_fast16_t diffTime = frameTime - this->lastFrameTime; + manager.update(diffTime); + + this->gameInstance->update(diffTime); // TODO: this might have to be split up into two update functions, before and after manager... + + this->lastFrameTime = frameTime; } void GameInternal::render() diff --git a/src/InputComponent.cpp b/src/InputComponent.cpp index ac26b32..8f31ad4 100644 --- a/src/InputComponent.cpp +++ b/src/InputComponent.cpp @@ -10,7 +10,7 @@ InputComponent::~InputComponent() = default; void InputComponent::init(){} -void InputComponent::update() +void InputComponent::update(uint_fast16_t diffTime) { SDL_PumpEvents(); } diff --git a/src/Manager.cpp b/src/Manager.cpp index 09eea97..31e42a4 100644 --- a/src/Manager.cpp +++ b/src/Manager.cpp @@ -27,9 +27,9 @@ void Manager::refresh() std::end(entities)); } -void Manager::update() +void Manager::update(uint_fast16_t diffTime) { - for (auto& e : entities) e->update(); + for (auto& e : entities) e->update(diffTime); } void Manager::addToGroup(Entity* mEntity, Group mGroup) diff --git a/src/PowerupComponent.cpp b/src/PowerupComponent.cpp index 5c1df71..4db3f95 100644 --- a/src/PowerupComponent.cpp +++ b/src/PowerupComponent.cpp @@ -12,7 +12,7 @@ PowerupComponent::PowerupComponent(std::function func) this->pickupFunc = func; } -void PowerupComponent::update() +void PowerupComponent::update(uint_fast16_t diffTime) { Entity* player; if ((player = this->entity->getManager().getGame()->collisionHandler->getAnyIntersection( diff --git a/src/ProjectileComponent.cpp b/src/ProjectileComponent.cpp index 11599c8..2596009 100644 --- a/src/ProjectileComponent.cpp +++ b/src/ProjectileComponent.cpp @@ -17,9 +17,9 @@ void ProjectileComponent::init() SoundManager::playSound(this->entity->getManager().getGame(), "throw_egg", true, PLAY_ONCE, MAX_VOLUME, -1); } -void ProjectileComponent::update() +void ProjectileComponent::update(uint_fast16_t diffTime) { - distance += speed; + distance += speed * diffTime * (1.f/1000); IntersectionBitSet boundsIntersection = this->entity->getManager().getGame()->collisionHandler->getIntersectionWithBounds(entity); @@ -27,7 +27,7 @@ void ProjectileComponent::update() this->entity->destroy(); } - if (distance > range) { + if (distance > range && false) { this->entity->destroy(); } diff --git a/src/SoundManager.cpp b/src/SoundManager.cpp index 3f101e2..182d616 100644 --- a/src/SoundManager.cpp +++ b/src/SoundManager.cpp @@ -1,6 +1,5 @@ #include "SoundManager.h" -#include #include #include diff --git a/src/SpriteComponent.cpp b/src/SpriteComponent.cpp index 026f8dc..e646289 100644 --- a/src/SpriteComponent.cpp +++ b/src/SpriteComponent.cpp @@ -59,14 +59,14 @@ void SpriteComponent::init() this->srcRect.x = this->textureXOffset * this->srcRect.w; this->srcRect.y = this->textureYOffset * this->srcRect.h;; - this->update(); + this->update(0); } -void SpriteComponent::update() +void SpriteComponent::update(uint_fast16_t diffTime) { // This code is not compatible for animated tiles if (animated) { - srcRect.x = srcRect.w * static_cast((SDL_GetTicks() / speed) % frames); + srcRect.x = srcRect.w * static_cast((SDL_GetTicks() / speed) % frames); // TODO: should not call SDL_GetTicks() but use diffTime srcRect.y = animationIndex * transform->height; } diff --git a/src/StatEffectsComponent.cpp b/src/StatEffectsComponent.cpp index c66e206..05ab31a 100644 --- a/src/StatEffectsComponent.cpp +++ b/src/StatEffectsComponent.cpp @@ -8,16 +8,16 @@ void StatEffectsComponent::init() {} -void StatEffectsComponent::update() +void StatEffectsComponent::update(uint_fast16_t diffTime) { for (int i = 0; i < MAX_STATS; i++) { - if (this->buffs.at(i) == 0) continue; - if (this->buffs.at(i) - 1 == 0) + if (this->buffs.at(i) <= 0) continue; + if (this->buffs.at(i) - diffTime <= 0) { this->resetStatValue((Stats)i); } - this->buffs.at(i) -= 1; + this->buffs.at(i) -= diffTime; } } @@ -32,7 +32,7 @@ void StatEffectsComponent::modifyStatValue(Stats stat, int modifier) //modifier switch (stat) { case Stats::MOVEMENT_SPEED: - this->entity->getComponent().modifySpeed(modifier); + this->entity->getComponent().modifySpeed(modifier * 60); break; case Stats::ATTACK_SPEED: // this->entity->getComponent().modifyAtkSpeed(modifier); diff --git a/src/TransformComponent.cpp b/src/TransformComponent.cpp index e8e299b..c50fb5a 100644 --- a/src/TransformComponent.cpp +++ b/src/TransformComponent.cpp @@ -50,12 +50,12 @@ void TransformComponent::init() direction.zero(); } -void TransformComponent::update() +void TransformComponent::update(uint_fast16_t diffTime) { 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 * this->getSpeed() * multiplier, - direction.y * this->getSpeed() * multiplier + direction.x * this->getSpeed() * multiplier * diffTime * (1.f/1000), + direction.y * this->getSpeed() * multiplier * diffTime * (1.f/1000) ); if (this->entity->hasGroup((size_t)Entity::GroupLabel::PLAYERS)){ diff --git a/src/_Init.cpp b/src/_Init.cpp new file mode 100644 index 0000000..cb82136 --- /dev/null +++ b/src/_Init.cpp @@ -0,0 +1,48 @@ +#include "SDL3/SDL_init.h" +#include +#define SDL_MAIN_USE_CALLBACKS +#include + +#include +#include + +#include "VEGO.h" +#include "Entity.h" +#include "GameInternal.h" +#include "Constants.h" + +GameInternal* vego::game = nullptr; + +SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { + srand(time(NULL)); + bool playing = true; + + *appstate = vego::game = new GameInternal(); + + return vego::game->init("No_Name_Chicken_Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_SIZE_WIDTH, SCREEN_SIZE_HEIGHT, false); +} + +SDL_AppResult SDL_AppIterate(void *appstate) { + if (!vego::game->isRunning()) { + return SDL_APP_SUCCESS; + } + + vego::game->handleEvents(); // bad + + Uint64 frameStart = SDL_GetTicks(); + + vego::game->update(frameStart); + vego::game->render(); + + int frameTime = SDL_GetTicks() - frameStart; + + return SDL_APP_CONTINUE; +} + +SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { + return SDL_APP_CONTINUE; +} + +void SDL_AppQuit(void *appstate, SDL_AppResult result) { + vego::game->clean(); +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 33bccd7..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include - -#include "VEGO.h" -#include "Entity.h" -#include "GameInternal.h" -#include "Constants.h" - -GameInternal* vego::game = nullptr; - -int main(int argc, char* argv[]) -{ - srand(time(NULL)); - bool playing = true; - - const int frameDelay = 1000 / FPS; - - Uint32 frameStart; - int frameTime; - - vego::game = new GameInternal(); - - vego::game->init("No_Name_Chicken_Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_SIZE_WIDTH, SCREEN_SIZE_HEIGHT, false); - while (vego::game->isRunning()) { - frameStart = SDL_GetTicks(); - - vego::game->handleEvents(); - vego::game->update(); - vego::game->render(); - - frameTime = SDL_GetTicks() - frameStart; - - if (frameDelay > frameTime) { - SDL_Delay(frameDelay - frameTime); - } - } - - vego::game->clean(); - - return 0; -} \ No newline at end of file