diff --git a/.gitignore b/.gitignore index 79ac56c..3a9a395 100644 --- a/.gitignore +++ b/.gitignore @@ -91,4 +91,5 @@ assets/borrowed /dist /archive0 -/archive1 \ No newline at end of file +/archive1 +/archive \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 67745cc..ad3ec7d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,13 +20,16 @@ target_include_directories(${DUSK_TARGET_NAME} target_sources(${DUSK_TARGET_NAME} PRIVATE main.c + input.c ) # Subdirs add_subdirectory(assert) add_subdirectory(client) add_subdirectory(console) +add_subdirectory(display) add_subdirectory(error) +add_subdirectory(game) add_subdirectory(packet) add_subdirectory(server) add_subdirectory(util) \ No newline at end of file diff --git a/src/client/networked/networkedclient.c b/src/client/networked/networkedclient.c index c8d6008..37bc917 100644 --- a/src/client/networked/networkedclient.c +++ b/src/client/networked/networkedclient.c @@ -255,11 +255,11 @@ void * networkedClientThread(void *arg) { while(client->state == CLIENT_STATE_CONNECTED) { usleep(1000*1000);// Sleep for 1 second - packetPingCreate(&packet); - packetQueuePushOutbound( - &client->packetQueue, - &packet - ); + // packetPingCreate(&packet); + // packetQueuePushOutbound( + // &client->packetQueue, + // &packet + // ); } client->state = CLIENT_STATE_DISCONNECTED; diff --git a/src/console/console.c b/src/console/console.c index 1a5178b..d43df5d 100644 --- a/src/console/console.c +++ b/src/console/console.c @@ -9,6 +9,7 @@ #include "assert/assert.h" #include "util/memory.h" #include "util/string.h" +#include "input.h" console_t CONSOLE; @@ -20,6 +21,8 @@ void consoleInit() { CONSOLE.cmdGet = consoleRegCmd("get", cmdGet); CONSOLE.cmdSet = consoleRegCmd("set", cmdSet); consoleRegCmd("echo", cmdEcho); + + consolePrint(" = Dawn Console = "); } consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function) { @@ -331,37 +334,45 @@ void cmdEcho(const consolecmdexec_t *exec) { // May move these later void consoleUpdate() { - int32_t key = GetKeyPressed(); + if(inputIsPressed(INPUT_TOGGLE_CONSOLE)) { + CONSOLE.open = !CONSOLE.open; + } else if(CONSOLE.open) { + switch(INPUT.keyPressed) { + case 0: + break; - switch(key) { - case 0: - break; + case KEY_ENTER: + consoleExec(CONSOLE.inputBuffer); + CONSOLE.inputIndex = 0; + CONSOLE.inputBuffer[0] = '\0'; + break; - case KEY_ENTER: - consoleExec(CONSOLE.inputBuffer); - CONSOLE.inputIndex = 0; - CONSOLE.inputBuffer[0] = '\0'; - break; + case KEY_BACKSPACE: + if(CONSOLE.inputIndex > 0) { + CONSOLE.inputIndex--; + CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0'; + } + break; - case KEY_BACKSPACE: - if(CONSOLE.inputIndex > 0) { - CONSOLE.inputIndex--; - CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0'; - } - break; - - default: - if(key >= 32 && key <= 126 && CONSOLE.inputIndex < CONSOLE_LINE_MAX - 1) { - CONSOLE.inputBuffer[CONSOLE.inputIndex++] = (char_t)GetCharPressed(); - CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0'; - } - break; + default: + if( + INPUT.keyPressed >= 32 && + INPUT.keyPressed <= 126 && + CONSOLE.inputIndex < CONSOLE_LINE_MAX - 1 + ) { + CONSOLE.inputBuffer[CONSOLE.inputIndex++] = INPUT.charPressed; + CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0'; + } + break; + } } consoleProcess(); } void consoleDraw() { + if(!CONSOLE.open) return; + size_t i = 0; char_t *line; int32_t fontSize = 10; @@ -371,7 +382,7 @@ void consoleDraw() { i++; continue; } - DrawText(line, 0, i*fontSize, fontSize, BLACK); + DrawText(line, 0, i*fontSize, fontSize, YELLOW); i++; } while(i < CONSOLE_HISTORY_MAX); @@ -379,6 +390,6 @@ void consoleDraw() { CONSOLE.inputBuffer, 0, (CONSOLE_HISTORY_MAX + 1) * fontSize, fontSize, - BLACK + PINK ); } \ No newline at end of file diff --git a/src/console/console.h b/src/console/console.h index 17e28bc..59ee0e8 100644 --- a/src/console/console.h +++ b/src/console/console.h @@ -42,6 +42,8 @@ typedef struct { // May move these later char_t inputBuffer[CONSOLE_LINE_MAX]; int32_t inputIndex; + + bool_t open; } console_t; extern console_t CONSOLE; diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt new file mode 100644 index 0000000..7d676c7 --- /dev/null +++ b/src/display/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 + render.c +) + +# Subdirs \ No newline at end of file diff --git a/src/display/render.c b/src/display/render.c new file mode 100644 index 0000000..8ddc845 --- /dev/null +++ b/src/display/render.c @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "render.h" +#include "game/game.h" +#include "assert/assert.h" +#include "console/console.h" + +void renderInit() { + // Initialize the rendering system + InitWindow(800, 600, "Dusk"); +} + +renderresult_t renderDraw() { + BeginDrawing(); + ClearBackground(BLACK); + + for(uint32_t i = 0; i < GAME.entityCount; i++) { + entityRender(&GAME.entities[i]); + } + + consoleDraw(); + + EndDrawing(); + if(WindowShouldClose()) return RENDER_EXIT; + return RENDER_OK; +} + + +void renderDispose() { + CloseWindow(); +} \ No newline at end of file diff --git a/src/display/render.h b/src/display/render.h new file mode 100644 index 0000000..1663a5c --- /dev/null +++ b/src/display/render.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +#define RENDER_FONT_SIZE 20 + +typedef enum { + RENDER_OK, + RENDER_EXIT, + RENDER_ERROR +} renderresult_t; + +/** + * Initializes the rendering system. + * + * @return The result of the initialization. + */ +void renderInit(); + +/** + * Initializes the rendering system. + * + * @return The result of the initialization. + */ +renderresult_t renderDraw(); + +/** + * Renders the game. + * + * @return The result of the render operation. + */ +void renderDispose(); \ No newline at end of file diff --git a/src/dusk.h b/src/dusk.h index 9f264f9..dc64519 100644 --- a/src/dusk.h +++ b/src/dusk.h @@ -20,6 +20,8 @@ #include #include +#include + typedef bool bool_t; typedef char char_t; diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt new file mode 100644 index 0000000..f507c91 --- /dev/null +++ b/src/game/CMakeLists.txt @@ -0,0 +1,13 @@ +# 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 + game.c +) + +# Subdirs +add_subdirectory(entity) \ No newline at end of file diff --git a/src/game/direction.h b/src/game/direction.h new file mode 100644 index 0000000..417ba7d --- /dev/null +++ b/src/game/direction.h @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once + +typedef enum { + DIRECTION_SOUTH = 0, + DIRECTION_NORTH = 1, + DIRECTION_EAST = 2, + DIRECTION_WEST = 3, + + DIRECTION_DOWN = 0, + DIRECTION_UP = 1, + DIRECTION_RIGHT = 2, + DIRECTION_LEFT = 3, +} direction_t; \ No newline at end of file diff --git a/src/game/entity/CMakeLists.txt b/src/game/entity/CMakeLists.txt new file mode 100644 index 0000000..ebbd7cb --- /dev/null +++ b/src/game/entity/CMakeLists.txt @@ -0,0 +1,10 @@ +# 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 + entity.c +) \ No newline at end of file diff --git a/src/game/entity/entity.c b/src/game/entity/entity.c new file mode 100644 index 0000000..d9c8b5a --- /dev/null +++ b/src/game/entity/entity.c @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "entity.h" +#include "game/game.h" +#include "util/memory.h" +#include "assert/assert.h" +#include "display/render.h" +#include "input.h" + +void entityInit(entity_t *entity, const entitytype_t type) { + memoryZero(entity, sizeof(entity_t)); + + entity->type = type; + switch(type) { + case ENTITY_TYPE_PLAYER: + break; + + default: + assertUnreachable("Unknown entity type."); + break; + } +} + +void entityTest(entity_t *ent) { + if(inputIsPressed(INPUT_DOWN)) { + ent->direction = DIRECTION_DOWN; + if(ent->y < GAME.map.height - 1) ent->y++; + } else if(inputIsPressed(INPUT_UP)) { + ent->direction = DIRECTION_UP; + if(ent->y > 0) ent->y--; + } else if(inputIsPressed(INPUT_LEFT)) { + ent->direction = DIRECTION_LEFT; + if(ent->x > 0) ent->x--; + } else if(inputIsPressed(INPUT_RIGHT)) { + ent->direction = DIRECTION_RIGHT; + if(ent->x < GAME.map.width - 1) ent->x++; + } +} + +void entityRender(const entity_t *ent) { + // Draw the entity + int32_t fontSize = 20; + char_t str[1]; + switch(ent->direction) { + case DIRECTION_NORTH: + str[0] = '^'; + break; + case DIRECTION_EAST: + str[0] = '>'; + break; + case DIRECTION_SOUTH: + str[0] = 'v'; + break; + case DIRECTION_WEST: + str[0] = '<'; + break; + default: + assertUnreachable("Invalid entity direction."); + break; + } + + DrawTextEx( + GetFontDefault(), + str, + (struct Vector2){ + ent->x * RENDER_FONT_SIZE, + ent->y * RENDER_FONT_SIZE + }, + RENDER_FONT_SIZE, + (float)(RENDER_FONT_SIZE / 10), + WHITE + ); +} \ No newline at end of file diff --git a/src/game/entity/entity.h b/src/game/entity/entity.h new file mode 100644 index 0000000..0950c68 --- /dev/null +++ b/src/game/entity/entity.h @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "game/direction.h" + +typedef enum { + ENTITY_TYPE_NULL = 0, + ENTITY_TYPE_PLAYER, +} entitytype_t; + + +typedef struct { + entitytype_t type; + uint8_t x, y; + direction_t direction; +} entity_t; + +/** + * Initializes a given entity. + * + * @param entity The entity to initialize. + * @param type The type of the entity. + */ +void entityInit(entity_t *entity, const entitytype_t type); + +void entityTest(entity_t *entity); + +/** + * Renders a given entity. + * + * @param entity The entity to render. + */ +void entityRender(const entity_t *entity); \ No newline at end of file diff --git a/src/game/game.c b/src/game/game.c new file mode 100644 index 0000000..724fbc0 --- /dev/null +++ b/src/game/game.c @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "game.h" +#include "util/memory.h" + +game_t GAME; + +void gameInit(void) { + memoryZero(&GAME, sizeof(game_t)); + + GAME.map.width = 10; + GAME.map.height = 10; +} \ No newline at end of file diff --git a/src/game/game.h b/src/game/game.h new file mode 100644 index 0000000..81822ef --- /dev/null +++ b/src/game/game.h @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "game/entity/entity.h" +#include "game/map/map.h" + +#define GAME_ENTITIES_MAX 256 + +typedef struct { + entity_t entities[GAME_ENTITIES_MAX]; + uint32_t entityCount; + map_t map; +} game_t; + +extern game_t GAME; + +/** + * Initializes the game. + */ +void gameInit(void); \ No newline at end of file diff --git a/src/game/map/map.h b/src/game/map/map.h new file mode 100644 index 0000000..b9fde1a --- /dev/null +++ b/src/game/map/map.h @@ -0,0 +1,14 @@ +/** + * 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 { + void *nothing; + uint8_t width, height; +} map_t; \ No newline at end of file diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..49928d1 --- /dev/null +++ b/src/input.c @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "input.h" +#include "util/memory.h" +#include "assert/assert.h" + +inputbindmap_t INPUT_BIND_MAPS[] = { + { KEY_W, INPUT_UP }, + { KEY_S, INPUT_DOWN }, + { KEY_A, INPUT_LEFT }, + { KEY_D, INPUT_RIGHT }, + { KEY_ENTER, INPUT_ACCEPT }, + { KEY_ESCAPE, INPUT_CANCEL }, + { KEY_UP, INPUT_UP }, + { KEY_DOWN, INPUT_DOWN }, + { KEY_LEFT, INPUT_LEFT }, + { KEY_RIGHT, INPUT_RIGHT }, + { KEY_GRAVE, INPUT_TOGGLE_CONSOLE } +}; + +#define INPUT_BIND_MAP_COUNT (sizeof(INPUT_BIND_MAPS) / sizeof(inputbindmap_t)) + +input_t INPUT; + +void inputInit(void) { + memoryZero(&INPUT, sizeof(input_t)); +} + +void inputUpdate(void) { + memoryCopy( + INPUT.previous, + INPUT.current, + sizeof(INPUT.previous) + ); + + memoryZero( + INPUT.current, + sizeof(INPUT.current) + ); + + for(uint32_t i = 0; i < INPUT_BIND_MAP_COUNT; i++) { + const inputbindmap_t *map = &INPUT_BIND_MAPS[i]; + if(IsKeyDown(map->key)) INPUT.current[map->bind] = true; + } + + INPUT.keyPressed = GetKeyPressed(); + INPUT.charPressed = GetCharPressed(); +} + +bool_t inputIsDown(const inputbind_t input) { + assertTrue(input < INPUT_BIND_COUNT, "Input out of range"); + return INPUT.current[input]; +} + +bool_t inputIsUp(const inputbind_t input) { + return !inputIsDown(input); +} + +bool_t inputWasDown(const inputbind_t input) { + assertTrue(input < INPUT_BIND_COUNT, "Input out of range"); + return INPUT.previous[input]; +} + +bool_t inputWasUp(const inputbind_t input) { + return !inputWasDown(input); +} + +bool_t inputIsPressed(const inputbind_t input) { + return inputIsDown(input) && inputWasUp(input); +} + +bool_t inputIsReleased(const inputbind_t input) { + return inputIsUp(input) && inputWasDown(input); +} \ No newline at end of file diff --git a/src/input.h b/src/input.h new file mode 100644 index 0000000..a998565 --- /dev/null +++ b/src/input.h @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef enum { + INPUT_UP, + INPUT_DOWN, + INPUT_LEFT, + INPUT_RIGHT, + INPUT_ACCEPT, + INPUT_CANCEL, + INPUT_TOGGLE_CONSOLE, +} inputbind_t; + +#define INPUT_BIND_COUNT INPUT_TOGGLE_CONSOLE + 1 + +typedef struct { + const int32_t key; + const inputbind_t bind; +} inputbindmap_t; + +typedef struct { + bool_t current[INPUT_BIND_COUNT]; + bool_t previous[INPUT_BIND_COUNT]; + int32_t keyPressed; + char_t charPressed; +} input_t; + +extern input_t INPUT; + +/** + * Initializes the input system. + */ +void inputInit(void); + +/** + * Updates the input system. + */ +void inputUpdate(void); + +/** + * Returns whether a given input is currently pressed. + * + * @param input The input to check. + * @return True if the input is pressed, false otherwise. + */ +bool_t inputIsDown(const inputbind_t input); + +/** + * Returns whether a given input is currently up. + * + * @param input The input to check. + * @return True if the input is up, false otherwise. + */ +bool_t inputIsUp(const inputbind_t input); + +/** + * Returns whether a given input was just pressed. + * + * @param input The input to check. + * @return True if the input was just pressed, false otherwise. + */ +bool_t inputWasDown(const inputbind_t input); + +/** + * Returns whether a given input was just released. + * + * @param input The input to check. + * @return True if the input was just released, false otherwise. + */ +bool_t inputWasUp(const inputbind_t input); + +/** + * Returns whether a given input was just pressed. + * + * @param input The input to check. + * @return True if the input was just pressed, false otherwise. + */ +bool_t inputIsPressed(const inputbind_t input); + +/** + * Returns whether a given input was just released. + * + * @param input The input to check. + * @return True if the input was just released, false otherwise. + */ +bool_t inputIsReleased(const inputbind_t input); \ No newline at end of file diff --git a/src/main.c b/src/main.c index c83799f..0052568 100644 --- a/src/main.c +++ b/src/main.c @@ -5,12 +5,14 @@ * https://opensource.org/licenses/MIT */ +#include "assert/assert.h" +#include "game/game.h" +#include "display/render.h" +#include "input.h" #include "console/console.h" #include "client/client.h" #include "server/server.h" #include "util/random.h" -#include "util/string.h" -#include "assert/assert.h" bool_t exitRequested = false; @@ -18,34 +20,40 @@ void cmdExit(const consolecmdexec_t *exec) { exitRequested = true; } -int main(void) { +int32_t main(const int32_t argc, const char **argv) { assertInit(); - consoleInit(); randomInit(); + gameInit(); + inputInit(); + renderInit(); + consoleInit(); clientInit(); serverInit(); consoleRegCmd("exit", cmdExit); - InitWindow(1280, 720, DUSK_NAME); + entityInit(&GAME.entities[GAME.entityCount++], ENTITY_TYPE_PLAYER); - while(!WindowShouldClose()) { + while(true) { + inputUpdate(); consoleUpdate(); - BeginDrawing(); - ClearBackground(RAYWHITE); - - consoleDraw(); - - EndDrawing(); + if(!CONSOLE.open) { + for(uint32_t i = 0; i < GAME.entityCount; i++) { + entity_t *ent = &GAME.entities[i]; + entityTest(ent); + } + } + + renderresult_t result = renderDraw(); + if(result != RENDER_OK) break; if(exitRequested) break; } - CloseWindow(); - serverDispose(); clientDispose(); - + renderDispose(); + return EXIT_SUCCESS; } \ No newline at end of file diff --git a/src/util/string.c b/src/util/string.c index e5b9169..8bbc6ea 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -72,7 +72,7 @@ int32_t stringFormat( int32_t stringFormatVA( char_t *dest, const size_t destSize, - char_t *format, + const char_t *format, va_list args ) { assertNotNull(dest, "dest must not be NULL"); diff --git a/src/util/string.h b/src/util/string.h index 5484e33..1028ca3 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -77,7 +77,7 @@ int32_t stringFormat(char_t *dest, const size_t destSize, char_t *format, ...); int32_t stringFormatVA( char_t *dest, const size_t destSize, - char_t *format, + const char_t *format, va_list args );