diff options
-rw-r--r-- | gameloop/.vscode/settings.json | 54 | ||||
-rw-r--r-- | gameloop/CMakeLists.txt | 2 | ||||
-rw-r--r-- | gameloop/include/gameObject.h | 29 | ||||
-rw-r--r-- | gameloop/include/loopManager.h | 14 | ||||
-rw-r--r-- | gameloop/include/timer.h | 31 | ||||
-rw-r--r-- | gameloop/include/window.h | 12 | ||||
-rw-r--r-- | gameloop/src/gameObject.cpp | 58 | ||||
-rw-r--r-- | gameloop/src/loopManager.cpp | 41 | ||||
-rw-r--r-- | gameloop/src/main.cpp | 2 | ||||
-rw-r--r-- | gameloop/src/timer.cpp | 56 | ||||
-rw-r--r-- | gameloop/src/window.cpp | 38 | ||||
-rw-r--r-- | gameloop/versions/delayBased.cpp | 57 |
12 files changed, 366 insertions, 28 deletions
diff --git a/gameloop/.vscode/settings.json b/gameloop/.vscode/settings.json new file mode 100644 index 0000000..6cee9cb --- /dev/null +++ b/gameloop/.vscode/settings.json @@ -0,0 +1,54 @@ +{ + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "valarray": "cpp" + } +} diff --git a/gameloop/CMakeLists.txt b/gameloop/CMakeLists.txt index 16cbcf3..6bc5017 100644 --- a/gameloop/CMakeLists.txt +++ b/gameloop/CMakeLists.txt @@ -14,6 +14,8 @@ set(SOURCES src/window.cpp src/main.cpp src/eventManager.cpp + src/gameObject.cpp + src/timer.cpp ) add_executable(gameloop ${SOURCES}) diff --git a/gameloop/include/gameObject.h b/gameloop/include/gameObject.h new file mode 100644 index 0000000..0e17991 --- /dev/null +++ b/gameloop/include/gameObject.h @@ -0,0 +1,29 @@ +#pragma once +#include <iostream> +class GameObject { + public: + GameObject(); + GameObject(std::string name, float x, float y, float width, float height, float velX, float velY); + std::string getName() const; + float getX() const; + float getY() const; + float getWidth() const; + float getHeight() const; + float getVelX() const; + float getVelY() const; + void setName(std::string value); + void setX(float value); + void setY(float value); + void setWidth(float value); + void setHeight(float value); + void setVelX(float value); + void setVelY(float value); + private: + std::string name = ""; + float x = 0; + float y = 0; + float width = 0; + float height = 0; + float velX = 0; + float velY = 0; +}; diff --git a/gameloop/include/loopManager.h b/gameloop/include/loopManager.h index 03b07a9..5ed918d 100644 --- a/gameloop/include/loopManager.h +++ b/gameloop/include/loopManager.h @@ -1,6 +1,7 @@ #pragma once #include <SDL2/SDL.h> #include "window.h" +#include "gameObject.h" class LoopManager{ public: LoopManager(); @@ -8,11 +9,18 @@ class LoopManager{ void loop(); private: - + std::vector<GameObject*> objectList; void processInput(); void update(); + void lateUpdate(); + void fixedUpdate(); void render(); - bool gameRunning; + bool gameRunning = false; WindowManager window; - + int timeScale = 1; + float lag = 0.0; + double currentTime; + double t = 0.0; + double dt = 0.01; + state previous; }; diff --git a/gameloop/include/timer.h b/gameloop/include/timer.h new file mode 100644 index 0000000..2769e4d --- /dev/null +++ b/gameloop/include/timer.h @@ -0,0 +1,31 @@ +#pragma once + +#include <SDL2/SDL.h> + +class LoopTimer { +public: + static LoopTimer& getInstance(); + void start(); + void update(); + float getDeltaTime() const; + float getDeltaTimeMs() const; + float getFixedDeltaTime() const; + int getCurrentTime() const; + void setFPS(int FPS); + int getFPS() const; + void enforceFrameRate(); + float getLag() const; +private: + LoopTimer(); + int FPS = 30; + float frameTargetTime = FPS / 1000; + int lastTime; + float fixedDeltaTime = 2; + float maxDeltaTime = 1; + float fixedTime = 0; + int lastFrameTime; + float deltaTime; + float time = 0; + int frequency; + float lag; +}; diff --git a/gameloop/include/window.h b/gameloop/include/window.h index b4f2b78..cfde0e9 100644 --- a/gameloop/include/window.h +++ b/gameloop/include/window.h @@ -1,20 +1,18 @@ #pragma once #include <SDL2/SDL.h> +#include <vector> +#include "gameObject.h" +#include <iostream> class WindowManager{ public: WindowManager(); virtual ~WindowManager(); - bool loadMedia(); - void update(); - bool init(); - void close(); + void render(std::vector<GameObject*> objects); bool initWindow(); void destroyWindow(); + SDL_Renderer* getRenderer(); private: - //Loads media - //Frees media and shuts down SDL - const int SCREEN_WIDTH = 800; const int SCREEN_HEIGHT = 600; SDL_Window* window = NULL; diff --git a/gameloop/src/gameObject.cpp b/gameloop/src/gameObject.cpp new file mode 100644 index 0000000..f637314 --- /dev/null +++ b/gameloop/src/gameObject.cpp @@ -0,0 +1,58 @@ +#include "gameObject.h" +std::string GameObject::getName() const{ + return name; +} +float GameObject::getX() const{ + return x; +} + +float GameObject::getY() const{ + return y; +} + +float GameObject::getWidth() const{ + return width; +} + +float GameObject::getHeight() const{ + return height; +} + +float GameObject::getVelX() const{ + return velX; +} + +float GameObject::getVelY() const{ + return velY; +} +void GameObject::setName(std::string value){ + name = value; +} +void GameObject::setX(float value){ + x = value; +} + +void GameObject::setY(float value){ + y = value; +} + +void GameObject::setWidth(float value){ + width = value; +} + +void GameObject::setHeight(float value){ + height = value; +} + +void GameObject::setVelX(float value){ + velX = value; +} + +void GameObject::setVelY(float value){ + velY = value; +} + +GameObject::GameObject(std::string name, float x, float y, float width, float height, float velX, float velY) + : name(name),x(x), y(y), width(width), height(height), velX(velX), velY(velY) { + + } diff --git a/gameloop/src/loopManager.cpp b/gameloop/src/loopManager.cpp index ef2decf..c439a3e 100644 --- a/gameloop/src/loopManager.cpp +++ b/gameloop/src/loopManager.cpp @@ -1,4 +1,5 @@ #include "loopManager.h" +#include "timer.h" LoopManager::LoopManager(){ } void LoopManager::processInput(){ @@ -15,23 +16,53 @@ void LoopManager::processInput(){ break; } } +void LoopManager::fixedUpdate(){ + fprintf(stderr,"fixed update\n"); +} void LoopManager::loop(){ + fprintf(stderr,"loop. \n"); + LoopTimer& timer = LoopTimer::getInstance(); while(gameRunning){ - //processInput(); + timer.update(); + lag += timer.getDeltaTime(); + processInput(); + while (lag >= timer.getFixedDeltaTime()) + { + fixedUpdate(); + lag -= timer.getFixedDeltaTime(); + } //update(); - //render(); + //timer.enforceFrameRate(); + render(); } window.destroyWindow(); } void LoopManager::setup(){ gameRunning = window.initWindow(); + LoopTimer::getInstance().start(); + LoopTimer::getInstance().setFPS(50); + + for(int i = 0; i < 2;i++){ + GameObject* square = new GameObject("square2",i*40,i*40,20,20,0,0); + objectList.push_back(square); + } } void LoopManager::render(){ + fprintf(stderr,"**********render********** \n"); if(gameRunning){ - SDL_SetRenderDrawColor(window.getRenderer(),255,0,0,255); - SDL_RenderClear(window.getRenderer()); + window.render(objectList); } } -void LoopManager::update(){ +void LoopManager::update() { + fprintf(stderr,"**********normal update********** \n"); + LoopTimer& timer = LoopTimer::getInstance(); + + float delta= timer.getDeltaTime(); + + for (int i = 0; i < objectList.size(); i++) { + objectList[i]->setX(objectList[i]->getX() + 50 * delta); + objectList[i]->setY(objectList[i]->getY() + 50 * delta); + } } + diff --git a/gameloop/src/main.cpp b/gameloop/src/main.cpp index 76d0c84..2333e63 100644 --- a/gameloop/src/main.cpp +++ b/gameloop/src/main.cpp @@ -3,6 +3,7 @@ #include <stdio.h> //#include "window.h" #include "loopManager.h" +#include "timer.h" //Screen dimension constants @@ -13,5 +14,6 @@ int main( int argc, char* args[] ) LoopManager gameLoop; gameLoop.setup(); gameLoop.loop(); + return 0; } diff --git a/gameloop/src/timer.cpp b/gameloop/src/timer.cpp new file mode 100644 index 0000000..6428797 --- /dev/null +++ b/gameloop/src/timer.cpp @@ -0,0 +1,56 @@ +#include "timer.h" + +// Singleton instance for global access +LoopTimer& LoopTimer::getInstance() { + static LoopTimer instance; + return instance; +} + +// Private constructor +LoopTimer::LoopTimer() : lastTime(0), deltaTime(0), frequency(0), FPS(0), frameTargetTime(0) {} + +void LoopTimer::start() { + +} + +void LoopTimer::update() { + Uint64 currentTime = SDL_GetTicks64(); + deltaTime = (currentTime - lastFrameTime) / 1000.0; + time += deltaTime; + lastFrameTime = currentTime; +} + +float LoopTimer::getDeltaTime() const { + return deltaTime; +} +float LoopTimer::getDeltaTimeMs() const { + return deltaTime * 1000; +} +int LoopTimer::getCurrentTime() const { + return SDL_GetTicks64(); +} + +float LoopTimer::getFixedDeltaTime() const { + return fixedDeltaTime; +} + +void LoopTimer::setFPS(int FPS) { + if (FPS > 0) { + this->FPS = FPS; + frameTargetTime = 1000 / FPS; + } +} +float LoopTimer::getLag() const{ + return lag; +} +int LoopTimer::getFPS() const { + return FPS; +} + +// Delay to match target frame time +void LoopTimer::enforceFrameRate() { + int waitTime = frameTargetTime - (SDL_GetTicks64() - lastFrameTime); + if(waitTime > 0 && waitTime <= frameTargetTime){ + SDL_Delay(waitTime); + } +} diff --git a/gameloop/src/window.cpp b/gameloop/src/window.cpp index 11424dd..f998a79 100644 --- a/gameloop/src/window.cpp +++ b/gameloop/src/window.cpp @@ -1,5 +1,4 @@ #include "window.h" - WindowManager::WindowManager(){ if( !initWindow() ) { @@ -9,27 +8,40 @@ WindowManager::WindowManager(){ WindowManager::~WindowManager(){ destroyWindow(); } -bool WindowManager::init() -{ -} -bool WindowManager::loadMedia() -{ -} -void WindowManager::close() -{ - -} SDL_Renderer* WindowManager::getRenderer(){ return renderer; } -void WindowManager::update(){ + +void WindowManager::render(std::vector<GameObject*> objects){ + // Set the draw color to black and clear the screen + SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); + SDL_RenderClear(renderer); + + // Print object position (optional for debugging) + //fprintf(stderr, "%d\n", objectList.size()); + for(int i = 0; i < objects.size();i++){ + //fprintf(stderr, "%f\n", objectList[i]->getX()); + // Create a rectangle representing the ball + SDL_Rect ball_rect = { + (int)objects[i]->getX(), + (int)objects[i]->getY(), + (int)objects[i]->getWidth(), + (int)objects[i]->getHeight(), + }; + // Set the draw color to white and render the ball + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + SDL_RenderFillRect(renderer, &ball_rect); + } + + SDL_RenderPresent(renderer); } + bool WindowManager::initWindow(){ if(SDL_Init(SDL_INIT_EVERYTHING) != 0){ fprintf(stderr,"Error inititalising SDL.\n"); return false; } - window = SDL_CreateWindow("Gameloop POC",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,SCREEN_WIDTH,SCREEN_HEIGHT,SDL_WINDOW_RESIZABLE); + window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); if(!window){ fprintf(stderr,"Error creating SDL Window. \n"); return false; diff --git a/gameloop/versions/delayBased.cpp b/gameloop/versions/delayBased.cpp new file mode 100644 index 0000000..a8cad15 --- /dev/null +++ b/gameloop/versions/delayBased.cpp @@ -0,0 +1,57 @@ +#include "loopManager.h" +#include "timer.h" +LoopManager::LoopManager(){ +} +void LoopManager::processInput(){ + SDL_Event event; + SDL_PollEvent(&event); + switch(event.type){ + case SDL_QUIT: + gameRunning = false; + break; + case SDL_KEYDOWN: + if(event.key.keysym.sym == SDLK_ESCAPE){ + gameRunning = false; + } + break; + } +} +void LoopManager::loop(){ + fprintf(stderr,"loop. \n"); + while(gameRunning){ + //Timer::getInstance().update(); + //deltaTime = Timer::getInstance().getDeltaTime(); + processInput(); + update(); + render(); + } + window.destroyWindow(); +} +void LoopManager::setup(){ + gameRunning = window.initWindow(); + LoopTimer::getInstance().start(); + LoopTimer::getInstance().setFPS(210); + + for(int i = 0; i < 2;i++){ + GameObject* square2 = new GameObject("square2",i*40,i*40,20,20,0,0); + objectList.push_back(square2); + } +} +void LoopManager::render(){ + if(gameRunning){ + window.render(objectList); + } +} + +void LoopManager::update() { + LoopTimer& timer = LoopTimer::getInstance(); + timer.enforceFrameRate(); + timer.update(); + float delta= timer.getDeltaTime(); + + for (int i = 0; i < objectList.size(); i++) { + objectList[i]->setX(objectList[i]->getX() + 50 * delta); + objectList[i]->setY(objectList[i]->getY() + 50 * delta); + } +} + |