diff --git a/.gitignore b/.gitignore index 2a8c1f9..4cd6814 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ build *.lst *.user *.kdev4 +*.kate-swp docs.json __dummy.html dub.selections.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..0453aa4 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Hibis Game Engine +Hibis (short for Hibiscus ([named after the genus of flowering plants](https://en.wikipedia.org/wiki/Hibiscus))) is a work in progress game engine written in C++.
+The goal of this game engine is to provide each part of the engine (renderer, audio, physics etc.) in seperate libraries so you can easily make your own system if need be. +# Install +## Pre-compiled libraries +lmao they don't exist yet chill +## Compiling +### Note: MSVC +`MSVC` (Microsoft Visual C++ Compiler) is unsupported and I cannot guarentee that Hibis will compile using it. Please use another compiler like G++ or Ninja instead. +### Dependencies +To compile Hibis, you will need: +- Meson +- Meson-compatible compiler (recommended: Ninja or ccache + G++) +- A few minutes of your time +Each non-core library also has specific dependencies, including: +- (RSDL) SDL2 +- (RSDL) SDL2_ttf +Linux users should be able to get all of these (except time) from their package manager.
+Windows users will need to use vcpkg or similar to easily get these dependencies. +### Actually Compiling +#### No Customising +Run `compile.sh` in the folder you cloned Hibis into. +#### Customising +In the folder you cloned Hibis into, run `meson build` to create a folder where the magic happens.
+Move into the build directory using CD and you can now use `meson configure` to adjust compile options.
+Once you have configured everything, run `meson compile` in the build directory and it should finish successfully. diff --git a/TODO.md b/TODO.md index 4a14ac2..ef9a5b7 100644 --- a/TODO.md +++ b/TODO.md @@ -36,3 +36,5 @@ - [ ] Physics Shape creation - [ ] Collision via raycasting - [ ] Option to *allow* for Physics Shapes to be able to be drawn (on by default, both compile time and run time, turn off at compile time via version(`-version=NoPhysShapeDraw`?)) +## Examples +- [ ] Example Game: Megaman clone diff --git a/core/engine/engine.cpp b/core/engine/engine.cpp index 1f1911d..d3eecf1 100644 --- a/core/engine/engine.cpp +++ b/core/engine/engine.cpp @@ -1,16 +1,18 @@ #include "enginever.hpp" #include "engine.hpp" +#include +#include namespace hibis { Engine::Engine(Renderer* renderer, LoggerCallback logger) { this->renderer = renderer; loggerCallback = logger; - previousProcessTick = 0.00001f; - previousPhysicsProcessTick = 0.00001f; + previousProcessTick = std::chrono::steady_clock::now(); + previousPhysicsProcessTick = std::chrono::steady_clock::now(); //watch.start(); - this->loggerCallback(Information, "Started Hibis!"); + this->loggerCallback(Information, "Started Hibis [using v" + (std::string)getEngineVersion() + "]!"); } Engine::~Engine() { @@ -18,32 +20,35 @@ namespace hibis { } void Engine::runNodeProcesses() { - // TODO: fix delta then adapt for runNodePhysicsProcesses - //const float current = watch.peek.total!"msecs" / 1_000; - //float delta = (current - previousProcessTick); + TODO("check if delta calc is correct") + const std::chrono::time_point current = std::chrono::steady_clock::now(); + auto delta = std::chrono::duration(current - previousProcessTick); for (Node* node : nodeList) { - node->physicsProcess(0.00f); + node->process(delta.count()); } - //this.previousProcessTick = watch.peek.total!"msecs" / 1_000; + previousProcessTick = std::chrono::steady_clock::now(); } void Engine::runNodePhysicsProcesses() { - // TODO: See above TODO - // Schade! Have the wrong function content while I figure out how std.datetime.watch works - //const float current = watch.peek.total!"msecs" / 1_000; - //float delta = (current - previousProcessTick); + const std::chrono::time_point current = std::chrono::steady_clock::now(); + auto delta = std::chrono::duration(current - previousProcessTick); for (Node* node : nodeList) { - node->physicsProcess(0.00f); + node->physicsProcess(delta.count()); } - //this.previousPhysicsProcessTick = watch.peek.total!"msecs" / 1_000; + previousProcessTick = std::chrono::steady_clock::now(); } void Engine::drawNodes() { - // TODO + TODO("check if this works") + for (Node* node : nodeList) { + if (Drawable* drawNode = (Drawable*)&node) { + drawNode->draw(renderer); + } + } } const char* Engine::getEngineVersion() { return HIBIS_VERSION; } diff --git a/core/engine/engine.hpp b/core/engine/engine.hpp index 3fe3521..e1513e4 100644 --- a/core/engine/engine.hpp +++ b/core/engine/engine.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "../renderer/renderer.hpp" #include "../callback.hpp" @@ -22,8 +23,8 @@ namespace hibis { private: Renderer* renderer; //StopWatch watch; - float previousProcessTick; - float previousPhysicsProcessTick; + std::chrono::time_point previousProcessTick; + std::chrono::time_point previousPhysicsProcessTick; std::vector nodeList; LoggerCallback loggerCallback; diff --git a/core/graphics/drawable.hpp b/core/graphics/drawable.hpp index 4ccad8f..c636b11 100644 --- a/core/graphics/drawable.hpp +++ b/core/graphics/drawable.hpp @@ -4,6 +4,7 @@ namespace hibis { class Drawable { + public: virtual void draw(Renderer* renderer) = 0; }; -} \ No newline at end of file +} diff --git a/core/resources/image.hpp b/core/resources/image.hpp deleted file mode 100644 index 6aec15f..0000000 --- a/core/resources/image.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "resource.hpp" - -namespace hibis { - class Image : Resource {}; -} \ No newline at end of file diff --git a/core/resources/texture.hpp b/core/resources/texture.hpp new file mode 100644 index 0000000..c551de2 --- /dev/null +++ b/core/resources/texture.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "resource.hpp" +#include + +namespace hibis { + TODO("Make this function") + class Texture : Resource { + void* data; + }; +} diff --git a/include/pragmautil.hpp b/include/pragmautil.hpp index 3ba8d87..8f84ea1 100644 --- a/include/pragmautil.hpp +++ b/include/pragmautil.hpp @@ -1,3 +1,9 @@ #pragma once -// TODO: pragma \ No newline at end of file +// TODO: pragma +#define PRAGMA(x) _Pragma(#x) + +#define MESSAGE(x) PRAGMA(message(x)) +#define TODO(x) PRAGMA(message("TODO: " x)) +#define WARNING(x) PRAGMA(GCC warning(x)) +#define ERROR(x) PRAGMA(GCC error(x)) diff --git a/renderer/rsdl/resources/font.cpp b/renderer/rsdl/resources/font.cpp index 9d9e3e4..8fa1a17 100644 --- a/renderer/rsdl/resources/font.cpp +++ b/renderer/rsdl/resources/font.cpp @@ -3,32 +3,30 @@ #include #include "font.hpp" -namespace hibis { - namespace rsdl { - Font::Font(std::string path, uint size) { - this->size = size; - this->path = path; - loadFont(); - } +namespace hibis::rsdl { + Font::Font(std::string path, uint size) { + this->size = size; + this->path = path; + loadFont(); + } - Font::~Font() { + Font::~Font() { + TTF_CloseFont(loadedFont); + } + + void Font::loadFont(bool reload) { + // If already loaded, close font + if (loadedFont != NULL) { TTF_CloseFont(loadedFont); + loadedFont = NULL; } - void Font::loadFont(bool reload) { - // If already loaded, close font - if (loadedFont != NULL) { - TTF_CloseFont(loadedFont); - loadedFont = NULL; - } + loadedFont = TTF_OpenFont(path.c_str(), size); - loadedFont = TTF_OpenFont(path.c_str(), size); - - // Do the message - if (!didReload) { - std::cout << fmt::format((reload ? "Reloaded font from" : "Loaded font at") + (std::string)" {}", path) << std::endl; - didReload = reload; - } + // Do the message + if (!didReload) { + std::cout << fmt::format((reload ? "Reloaded font from" : "Loaded font at") + (std::string)" {}", path) << std::endl; + didReload = reload; } } } diff --git a/renderer/rsdl/resources/font.hpp b/renderer/rsdl/resources/font.hpp index ace8c22..5ae37e2 100644 --- a/renderer/rsdl/resources/font.hpp +++ b/renderer/rsdl/resources/font.hpp @@ -5,26 +5,24 @@ #include -namespace hibis { - namespace rsdl { - class Font : public Resource { - public: - Font(std::string path, uint size); +namespace hibis::rsdl { + class Font : public Resource { + public: + Font(std::string path, uint size); - ~Font(); + ~Font(); - uint getFontSize() { return size; } + uint getFontSize() { return size; } - void setFontSize(uint newSize) { size = newSize; loadFont(true); } + void setFontSize(uint newSize) { size = newSize; loadFont(true); } - TTF_Font* loadedFont = NULL; - private: - void loadFont(bool reload = false); - uint size; - std::string path; + TTF_Font* loadedFont = NULL; + private: + void loadFont(bool reload = false); + uint size; + std::string path; - bool didReload = false; - }; - } + bool didReload = false; + }; } diff --git a/renderer/rsdl/rsdl.cpp b/renderer/rsdl/rsdl.cpp index f589c8c..0050c71 100644 --- a/renderer/rsdl/rsdl.cpp +++ b/renderer/rsdl/rsdl.cpp @@ -6,93 +6,94 @@ #include -namespace hibis { - namespace rsdl { - RSDL::RSDL(std::string title, IntVec2 size, LoggerCallback callback) { - logger = callback; +namespace hibis::rsdl { + RSDL::RSDL(std::string title, IntVec2 size, LoggerCallback callback) { + logger = callback; - SDL_Init(SDL_INIT_VIDEO); + SDL_Init(SDL_INIT_VIDEO); - // Create window. `title` is cast to a char* here as tostd::stringz returns an immutable char* (causing an error) - window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - size.x, size.y, SDL_WINDOW_RESIZABLE); + // Create window. `title` is cast to a char* here as tostd::stringz returns an immutable char* (causing an error) + window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + size.x, size.y, SDL_WINDOW_RESIZABLE); - if (window == NULL) { - logger(Fatal, fmt::format("Couldn't create window! what: {}", SDL_GetError())); - SDL_Quit(); - exit(1); - } - - renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); - - if (renderer == NULL) { - logger(Fatal, fmt::format("Couldn't create renderer! what: {}", SDL_GetError())); - SDL_DestroyWindow(window); - SDL_Quit(); - exit(1); - } - - if (TTF_Init() != 0) { - logger(Fatal, fmt::format("Couldn't load SDL_TTF! what: %d", TTF_GetError())); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - SDL_Quit(); - TTF_Quit(); - exit(1); - } + if (window == NULL) { + logger(Fatal, fmt::format("Couldn't create window! what: {}", SDL_GetError())); + SDL_Quit(); + exit(1); } - RSDL::~RSDL() { - TTF_Quit(); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + + if (renderer == NULL) { + logger(Fatal, fmt::format("Couldn't create renderer! what: {}", SDL_GetError())); + SDL_DestroyWindow(window); + SDL_Quit(); + exit(1); + } + + if (TTF_Init() != 0) { + logger(Fatal, fmt::format("Couldn't load SDL_TTF! what: %d", TTF_GetError())); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); + TTF_Quit(); + exit(1); } + } - void RSDL::clearScreen(Color col) { - SDL_SetRenderDrawColor(renderer, col.r, col.g, col.b, col.a); - SDL_RenderClear(renderer); + RSDL::~RSDL() { + TTF_Quit(); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + } + + void RSDL::clearScreen(Color col) { + SDL_SetRenderDrawColor(renderer, col.r, col.g, col.b, col.a); + SDL_RenderClear(renderer); + } + + void RSDL::renderCurrent() { + SDL_UpdateWindowSurface(window); + SDL_RenderPresent(renderer); + } + + void RSDL::drawText(Resource* resource, std::string text, IntVec2 pos, Color color) { + WARNING("tulip what the hell is this, this sucks.\nAvoid remaking textures every time text has to be drawn") + if (Font* font = (Font*)resource) { + SDL_Surface* textSurface = TTF_RenderText_Solid(font->loadedFont, text.c_str(), SDL_Color {color.r, color.g, color.b, color.a }); + SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface); + + int width = 0; + int height = 0; + + TTF_SizeText(font->loadedFont, text.c_str(), &width, &height); + + SDL_Rect textRect; + textRect.x = pos.x; + textRect.y = pos.y; + textRect.w = width; + textRect.h = height; + + SDL_RenderCopy(renderer, textTexture, NULL, &textRect); + + SDL_DestroyTexture(textTexture); + SDL_FreeSurface(textSurface); } + } - void RSDL::renderCurrent() { - SDL_UpdateWindowSurface(window); - SDL_RenderPresent(renderer); + void RSDL::preDraw() {} + void RSDL::postDraw() {} + + void RSDL::update() { + SDL_Event event; + + while(SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) keepOpen = false; } + } - void RSDL::drawText(Resource* resource, std::string text, IntVec2 pos, Color color) { - if (Font* font = (Font*)resource) { - SDL_Surface* textSurface = TTF_RenderText_Solid(font->loadedFont, text.c_str(), SDL_Color {color.r, color.g, color.b, color.a }); - SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface); - - int width = 0; - int height = 0; - - TTF_SizeText(font->loadedFont, text.c_str(), &width, &height); - - SDL_Rect textRect; - textRect.x = pos.x; - textRect.y = pos.y; - textRect.w = width; - textRect.h = height; - - SDL_RenderCopy(renderer, textTexture, NULL, &textRect); - - SDL_DestroyTexture(textTexture); - SDL_FreeSurface(textSurface); - } - } - - void RSDL::preDraw() {} - void RSDL::postDraw() {} - - void RSDL::update() { - SDL_Event event; - - while(SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) keepOpen = false; - } - } - - void RSDL::setWindowTitle(std::string title) {} + void RSDL::setWindowTitle(std::string title) { + SDL_SetWindowTitle(window, title.c_str()); } } diff --git a/renderer/rsdl/rsdl.hpp b/renderer/rsdl/rsdl.hpp index d4c7652..f868a53 100644 --- a/renderer/rsdl/rsdl.hpp +++ b/renderer/rsdl/rsdl.hpp @@ -9,35 +9,33 @@ #include #include -namespace hibis { - namespace rsdl { - /** \class RSDL - * Renderer implementation using SDL2 Renderer for the Hibis game engine - */ - class RSDL : public Renderer { - public: - RSDL(std::string title, IntVec2 size, LoggerCallback callback); +namespace hibis::rsdl { + /** \class RSDL + * Renderer implementation using SDL2 Renderer for the Hibis game engine + */ + class RSDL : public Renderer { + public: + RSDL(std::string title, IntVec2 size, LoggerCallback callback); - ~RSDL(); + ~RSDL(); - void clearScreen(Color col = Color {0, 0, 0, 1}); + void clearScreen(Color col = Color {0, 0, 0, 255}); - void renderCurrent(); + void renderCurrent(); - void drawText(Resource* resource, std::string text, IntVec2 pos, Color color); + void drawText(Resource* resource, std::string text, IntVec2 pos, Color color); - void preDraw(); - void postDraw(); + void preDraw(); + void postDraw(); - void update(); + void update(); - void setWindowTitle(std::string title); + void setWindowTitle(std::string title); - private: - SDL_Window* window; - SDL_Renderer* renderer; + private: + SDL_Window* window; + SDL_Renderer* renderer; - LoggerCallback logger; - }; - } + LoggerCallback logger; + }; } diff --git a/test/app.cpp b/test/app.cpp index da0cd7a..e2514d0 100644 --- a/test/app.cpp +++ b/test/app.cpp @@ -11,6 +11,12 @@ #include +#include + +#if defined(_MSC_VER) || defined(_MSC_FULL_VER) +WARNING("Please avoid using MSVC in C++ projects utilising std::chrono due to frame timing issues") +#endif + using namespace hibis; using namespace hibis::rsdl; @@ -34,7 +40,7 @@ void logger(LoggingSeverity severity, std::string message) { break; } - std::cout << fmt::format("[{}]: {}", severity, message) << std::endl; + std::cout << fmt::format("[{}]: {}", sevString, message) << std::endl; } int main() {