diff --git a/src/dusk/CMakeLists.txt b/src/dusk/CMakeLists.txt index 068a8ec..8dfd25f 100644 --- a/src/dusk/CMakeLists.txt +++ b/src/dusk/CMakeLists.txt @@ -14,8 +14,10 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE game.c input.c + gametime.c ) # Subdirs add_subdirectory(assert) +add_subdirectory(console) add_subdirectory(display) \ No newline at end of file diff --git a/src/dusk/console/CMakeLists.txt b/src/dusk/console/CMakeLists.txt new file mode 100644 index 0000000..d180d71 --- /dev/null +++ b/src/dusk/console/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_TARGET_NAME} + PRIVATE + console.c +) + +# Subdirs \ No newline at end of file diff --git a/src/dusk/console/console.c b/src/dusk/console/console.c new file mode 100644 index 0000000..15134e5 --- /dev/null +++ b/src/dusk/console/console.c @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "console.h" +#include "assert/assert.h" + +console_t CONSOLE; + +void consoleInit() { + memset(&CONSOLE, 0, sizeof(console_t)); +} + +const consolecmd_t * consoleCommand(const char_t *cmd) { + assertTrue( + CONSOLE.commandCount < CONSOLE_COMMAND_COUNT_MAX, + "Command buffer full." + ); + assertStrLen(cmd, CONSOLE_CMD_LENGTH_MAX, "Command too long."); + + consolecmd_t *command = &CONSOLE.commands[CONSOLE.commandCount++]; + strcpy(command->cmd, cmd); + return command; +} + +void consolePrint(const char_t *fmt, ...) { + // Do we need to shift the log buffer? + if (CONSOLE.logCount == CONSOLE_LOG_COUNT_MAX) { + memcpy( + CONSOLE.log[0], + CONSOLE.log[1], + sizeof(char_t) * + CONSOLE_LOG_MESSAGE_LENGTH_MAX * + (CONSOLE_LOG_COUNT_MAX - 1) + ); + } + + // Print the message + va_list args; + va_start(args, fmt); + + // buffer but don't let it overflow the string length. + int ret = vsnprintf( + CONSOLE.log[CONSOLE.logCount++], + CONSOLE_LOG_MESSAGE_LENGTH_MAX, + fmt, + args + ); + + assertTrue(ret >= 0, "Log message error."); + assertTrue(ret < CONSOLE_LOG_MESSAGE_LENGTH_MAX, "Log message overflow."); + + printf("%s\n", CONSOLE.log[CONSOLE.logCount - 1]); + + va_end(args); +} \ No newline at end of file diff --git a/src/dusk/console/console.h b/src/dusk/console/console.h new file mode 100644 index 0000000..f6edab9 --- /dev/null +++ b/src/dusk/console/console.h @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "consolecmd.h" + +#define CONSOLE_COMMAND_COUNT_MAX 64 +#define CONSOLE_LOG_MESSAGE_LENGTH_MAX 1024 +#define CONSOLE_LOG_COUNT_MAX 256 + +typedef struct { + consolecmd_t commands[CONSOLE_COMMAND_COUNT_MAX]; + uint8_t commandCount; + + char_t log[CONSOLE_LOG_COUNT_MAX][CONSOLE_LOG_MESSAGE_LENGTH_MAX + 1]; + uint8_t logCount; +} console_t; + +extern console_t CONSOLE; + +/** + * Initializes the console. + */ +void consoleInit(); + +/** + * Run a command against the console. + * + * @param cmd The command string to run. + */ +const consolecmd_t * consoleCommand(const char_t *cmd); + +/** + * Prints a message to the console. + * + * @param fmt The format string. + * @param ... The format arguments. + */ +void consolePrint(const char_t *fmt, ...); \ No newline at end of file diff --git a/src/dusk/console/consolecmd.h b/src/dusk/console/consolecmd.h new file mode 100644 index 0000000..221a11c --- /dev/null +++ b/src/dusk/console/consolecmd.h @@ -0,0 +1,15 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +#define CONSOLE_CMD_LENGTH_MAX 256 + +typedef struct { + char_t cmd[CONSOLE_CMD_LENGTH_MAX + 1]; +} consolecmd_t; \ No newline at end of file diff --git a/src/dusk/dusk.h b/src/dusk/dusk.h index 231a732..c450b4b 100644 --- a/src/dusk/dusk.h +++ b/src/dusk/dusk.h @@ -13,6 +13,7 @@ #include #include #include +#include typedef bool bool_t; typedef char char_t; \ No newline at end of file diff --git a/src/dusk/game.c b/src/dusk/game.c index 773081e..90b82c1 100644 --- a/src/dusk/game.c +++ b/src/dusk/game.c @@ -6,12 +6,17 @@ */ #include "game.h" +#include "gametime.h" #include "input.h" +#include "console/console.h" void gameInit() { + consoleInit(); + gameTimeInit(); inputInit(); } -void gameUpdate() { +void gameUpdate(const float delta) { + gameTimeUpdate(delta); inputUpdate(); } \ No newline at end of file diff --git a/src/dusk/game.h b/src/dusk/game.h index 2c4fdb1..45056c6 100644 --- a/src/dusk/game.h +++ b/src/dusk/game.h @@ -15,5 +15,7 @@ void gameInit(); /** * Updates the game. + * + * @param delta Game time update delta since last tick. */ -void gameUpdate(); \ No newline at end of file +void gameUpdate(const float_t delta); \ No newline at end of file diff --git a/src/dusk/gametime.c b/src/dusk/gametime.c new file mode 100644 index 0000000..7f7166f --- /dev/null +++ b/src/dusk/gametime.c @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "gametime.h" + +gametime_t GAME_TIME; + +void gameTimeInit() { + memset(&GAME_TIME, 0, sizeof(gametime_t)); + GAME_TIME.delta = GAME_TIME_STEP_DEFAULT; +} + +void gameTimeUpdate(const float_t delta) { + GAME_TIME.delta = delta; + GAME_TIME.time += GAME_TIME.delta; +} \ No newline at end of file diff --git a/src/dusk/gametime.h b/src/dusk/gametime.h new file mode 100644 index 0000000..1ab76f2 --- /dev/null +++ b/src/dusk/gametime.h @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct { + float_t delta; + float_t time; +} gametime_t; + +extern gametime_t GAME_TIME; + +#define GAME_TIME_STEP_DEFAULT 0.016f + +/** + * Initializes the game time. + */ +void gameTimeInit(); + +/** + * Updates the game time. + * + * @param delta The time since the last frame. + */ +void gameTimeUpdate(const float_t delta); \ No newline at end of file diff --git a/src/dusk/input.h b/src/dusk/input.h index 88d86b6..1737a09 100644 --- a/src/dusk/input.h +++ b/src/dusk/input.h @@ -17,7 +17,7 @@ typedef enum { INPUT_RIGHT, INPUT_ACCEPT, INPUT_BACK, - INPUT_QUIT + INPUT_QUIT, } inputbind_t; #define INPUT_BIND_COUNT INPUT_QUIT + 1 diff --git a/src/duskgl/display/render.c b/src/duskgl/display/render.c index bdb2493..17e13b7 100644 --- a/src/duskgl/display/render.c +++ b/src/duskgl/display/render.c @@ -7,11 +7,24 @@ #include "assert/assertgl.h" #include "render.h" +#include "console/console.h" render_t RENDER; void renderInit() { memset(&RENDER, 0, sizeof(render_t)); + + // Get OpenGL version + const GLubyte *version = glGetString(GL_VERSION); + const GLubyte *renderer = glGetString(GL_RENDERER); + const GLubyte *vendor = glGetString(GL_VENDOR); + const GLubyte *glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION); + + consolePrint("OpenGL Renderer"); + consolePrint("Version: %s", version); + consolePrint("Renderer: %s", renderer); + consolePrint("Vendor: %s", vendor); + consolePrint("GLSL: %s", glslVersion); } void renderUpdate() { diff --git a/src/duskglfw/main.c b/src/duskglfw/main.c index ad01f8a..dd89a86 100644 --- a/src/duskglfw/main.c +++ b/src/duskglfw/main.c @@ -10,10 +10,7 @@ #include "display/render.h" #include "game.h" #include "asset.h" - -#define TIME_BETWEEN_UPDATES (1.0f / 60.0f) - -float_t timeUntilNextUpdate; +#include "console/console.h" char_t EXECUTABLE_PATH[FILENAME_MAX]; char_t EXECUTABLE_DIRECTORY[FILENAME_MAX]; @@ -35,15 +32,20 @@ int32_t main(int32_t argc, char_t **argv) { if((ret = windowInit()) != 0) { return -1; } + gameInit(); + + // Print OS Information + const char* glfwVersionString = glfwGetVersionString(); + consolePrint("GLFW: %s", glfwVersionString); + + // Init asset and render systems. assetInit(); renderInit(); - gameInit(); // Prepare for time tracking double_t time, newTime; float_t fDelta; int32_t updateResult; - timeUntilNextUpdate = 0.0f; // Main loop while(!windowShouldClose()) { @@ -51,13 +53,8 @@ int32_t main(int32_t argc, char_t **argv) { newTime = glfwGetTime(); fDelta = (float_t)(newTime - time); time = newTime; - timeUntilNextUpdate -= fDelta; - // Should game tick? - if(timeUntilNextUpdate <= 0) { - gameUpdate(); - timeUntilNextUpdate = TIME_BETWEEN_UPDATES; - } + gameUpdate(fDelta); // Draw renderUpdate();