diff --git a/assets/config/init-base.dcf b/assets/config/init-base.dcf index b42fc9e..aaea903 100644 --- a/assets/config/init-base.dcf +++ b/assets/config/init-base.dcf @@ -1,4 +1,4 @@ echo " = Dawn Init = "; fps 1; -scene test; \ No newline at end of file +scene map; \ No newline at end of file diff --git a/src/display/display.c b/src/display/display.c index ba99b96..ef0015d 100644 --- a/src/display/display.c +++ b/src/display/display.c @@ -13,6 +13,7 @@ #include "display/spritebatch.h" #include "display/mesh/quad.h" #include "display/screen.h" +#include "ui/ui.h" display_t DISPLAY; @@ -110,7 +111,12 @@ errorret_t displayUpdate(void) { // Bind screen and render scene screenBind(); + frameBufferClear( + FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH, + COLOR_CORNFLOWER_BLUE + ); sceneManagerRender(); + uiRender(); // UI will probs go here diff --git a/src/engine/engine.c b/src/engine/engine.c index 9a9fe8b..d5bdc33 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -13,6 +13,7 @@ #include "display/display.h" #include "scene/scenemanager.h" #include "asset/assetmanager.h" +#include "ui/ui.h" #include "rpg/rpg.h" engine_t ENGINE; @@ -30,6 +31,7 @@ errorret_t engineInit(void) { inputInit(); errorChain(assetManagerInit()); errorChain(displayInit()); + errorChain(uiInit()); errorChain(rpgInit()); errorChain(sceneManagerInit()); @@ -50,6 +52,7 @@ errorret_t engineUpdate(void) { assetManagerUpdate(); rpgUpdate(); + uiUpdate(); sceneManagerUpdate(); errorChain(displayUpdate()); @@ -63,6 +66,7 @@ void engineExit(void) { errorret_t engineDispose(void) { sceneManagerDispose(); rpgDispose(); + uiDispose(); errorChain(displayDispose()); assetManagerDispose(); consoleDispose(); diff --git a/src/rpg/entity/entity.c b/src/rpg/entity/entity.c index c9ab810..c210839 100644 --- a/src/rpg/entity/entity.c +++ b/src/rpg/entity/entity.c @@ -6,22 +6,25 @@ */ #include "entity.h" -#include "rpg/world/map.h" #include "assert/assert.h" #include "util/memory.h" #include "display/tileset/tileset_entities.h" #include "time/time.h" #include "util/math.h" -void entityInit(entity_t *entity, const entitytype_t type, map_t *map) { +entity_t ENTITIES[ENTITY_COUNT]; + +void entityInit(entity_t *entity, const entitytype_t type) { assertNotNull(entity, "Entity pointer cannot be NULL"); - assertNotNull(map, "Map pointer cannot be NULL"); assertTrue(type < ENTITY_TYPE_COUNT, "Invalid entity type"); assertTrue(type != ENTITY_TYPE_NULL, "Cannot have NULL entity type"); + assertTrue( + entity >= ENTITIES && entity < ENTITIES + ENTITY_COUNT, + "Entity pointer is out of bounds" + ); memoryZero(entity, sizeof(entity_t)); entity->type = type; - entity->map = map; // Init. I did use a callback struct but it was not flexible enough. switch(type) { @@ -42,66 +45,4 @@ void entityUpdate(entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); assertTrue(entity->type < ENTITY_TYPE_COUNT, "Invalid entity type"); assertTrue(entity->type != ENTITY_TYPE_NULL, "Cannot have NULL entity type"); - - // Handle movement logic - switch(entity->type) { - case ENTITY_TYPE_PLAYER: - playerMovement(entity); - break; - - case ENTITY_TYPE_NPC: - npcUpdate(entity); - break; - - default: - break; - } - - // Apply velocity - if(entity->velocity[0] != 0.0f || entity->velocity[1] != 0.0f) { - entity->position[0] += entity->velocity[0] * TIME.delta; - entity->position[1] += entity->velocity[1] * TIME.delta; - - // Hit test on other entities. - entity_t *start = entity->map->entities; - entity_t *end = &entity->map->entities[entity->map->entityCount]; - - // Our hitbox - physicscircle_t self; - glm_vec2_copy(entity->position, self.position); - self.radius = TILESET_ENTITIES.tileWidth / 2.0f; - - physicscircle_t other; - other.radius = self.radius; - - // TODO: what if multiple collisions? - do { - if(start == entity) continue; - if(start->type == ENTITY_TYPE_NULL) continue; - glm_vec2_copy(start->position, other.position); - - physicscirclecircleresult_t result; - physicsCircleCheckCircle(self, other, &result); - - if(result.hit) { - entity->position[0] -= result.normal[0] * result.depth; - entity->position[1] -= result.normal[1] * result.depth; - break; - } - } while((start++) != end); - - // Friction (and dampening) - entity->velocity[0] *= ENTITY_FRICTION * TIME.delta; - entity->velocity[1] *= ENTITY_FRICTION * TIME.delta; - if(mathAbs(entity->velocity[0]) < ENTITY_MIN_VELOCITY) { - entity->velocity[0] = 0.0f; - } - if(mathAbs(entity->velocity[1]) < ENTITY_MIN_VELOCITY) { - entity->velocity[1] = 0.0f; - } - } - - if(entity->type == ENTITY_TYPE_PLAYER) { - playerInteraction(entity); - } } \ No newline at end of file diff --git a/src/rpg/entity/entity.h b/src/rpg/entity/entity.h index 0015c48..67092af 100644 --- a/src/rpg/entity/entity.h +++ b/src/rpg/entity/entity.h @@ -10,9 +10,11 @@ #include "rpg/entity/player.h" #include "npc.h" #include "physics/physics.h" +#include "rpg/world/worldunit.h" -#define ENTITY_FRICTION 0.9f -#define ENTITY_MIN_VELOCITY 0.05f +#define ENTITY_FRICTION 1 +#define ENTITY_MIN_VELOCITY 1 +#define ENTITY_COUNT 256 typedef struct map_s map_t; @@ -25,12 +27,10 @@ typedef enum { } entitytype_t; typedef struct entity_s { - map_t *map; entitytype_t type; direction_t direction; - - vec2 position; - vec2 velocity; + worldchunkpos_t position[3]; + worldsubtile_t velocity[3]; union { player_t player; @@ -38,14 +38,15 @@ typedef struct entity_s { }; } entity_t; +extern entity_t ENTITIES[ENTITY_COUNT]; + /** * Initializes an entity structure. * * @param entity Pointer to the entity structure to initialize. * @param type The type of the entity. - * @param map Pointer to the map the entity belongs to. */ -void entityInit(entity_t *entity, const entitytype_t type, map_t *map); +void entityInit(entity_t *entity, const entitytype_t type); /** * Updates an entity. diff --git a/src/rpg/entity/player.c b/src/rpg/entity/player.c index 9c546c7..5a95f46 100644 --- a/src/rpg/entity/player.c +++ b/src/rpg/entity/player.c @@ -17,98 +17,98 @@ void playerInit(entity_t *entity) { void playerMovement(entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); - // Update velocity. - vec2 dir = { - inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT), - inputAxis(INPUT_ACTION_DOWN, INPUT_ACTION_UP) - }; - if(dir[0] == 0 && dir[1] == 0) return; + // // Update velocity. + // vec2 dir = { + // inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT), + // inputAxis(INPUT_ACTION_DOWN, INPUT_ACTION_UP) + // }; + // if(dir[0] == 0 && dir[1] == 0) return; - glm_vec2_normalize(dir); - entity->velocity[0] += PLAYER_SPEED * dir[0]; - entity->velocity[1] += PLAYER_SPEED * dir[1]; + // glm_vec2_normalize(dir); + // entity->velocity[0] += PLAYER_SPEED * dir[0]; + // entity->velocity[1] += PLAYER_SPEED * dir[1]; - // Update direction. - if(dir[0] > 0) { - if(entity->direction == DIRECTION_RIGHT) { - entity->direction = DIRECTION_RIGHT; - } else { - if(dir[1] < 0) { - entity->direction = DIRECTION_UP; - } else if(dir[1] > 0) { - entity->direction = DIRECTION_DOWN; - } else { - entity->direction = DIRECTION_RIGHT; - } - } - } else if(dir[0] < 0) { - if(entity->direction == DIRECTION_LEFT) { - entity->direction = DIRECTION_LEFT; - } else { - if(dir[1] < 0) { - entity->direction = DIRECTION_UP; - } else if(dir[1] > 0) { - entity->direction = DIRECTION_DOWN; - } else { - entity->direction = DIRECTION_LEFT; - } - } - } else if(dir[1] < 0) { - entity->direction = DIRECTION_UP; - } else if(dir[1] > 0) { - entity->direction = DIRECTION_DOWN; - } + // // Update direction. + // if(dir[0] > 0) { + // if(entity->direction == DIRECTION_RIGHT) { + // entity->direction = DIRECTION_RIGHT; + // } else { + // if(dir[1] < 0) { + // entity->direction = DIRECTION_UP; + // } else if(dir[1] > 0) { + // entity->direction = DIRECTION_DOWN; + // } else { + // entity->direction = DIRECTION_RIGHT; + // } + // } + // } else if(dir[0] < 0) { + // if(entity->direction == DIRECTION_LEFT) { + // entity->direction = DIRECTION_LEFT; + // } else { + // if(dir[1] < 0) { + // entity->direction = DIRECTION_UP; + // } else if(dir[1] > 0) { + // entity->direction = DIRECTION_DOWN; + // } else { + // entity->direction = DIRECTION_LEFT; + // } + // } + // } else if(dir[1] < 0) { + // entity->direction = DIRECTION_UP; + // } else if(dir[1] > 0) { + // entity->direction = DIRECTION_DOWN; + // } } void playerInteraction(entity_t *entity) { - assertNotNull(entity, "Entity pointer cannot be NULL"); + // assertNotNull(entity, "Entity pointer cannot be NULL"); - if(!inputPressed(INPUT_ACTION_ACCEPT)) return; + // if(!inputPressed(INPUT_ACTION_ACCEPT)) return; - physicsbox_t interactBox; + // physicsbox_t interactBox; - // Get direction vector - directionGetVec2(entity->direction, interactBox.min); + // // Get direction vector + // directionGetVec2(entity->direction, interactBox.min); - // Scale by interact range - glm_vec2_scale(interactBox.min, PLAYER_INTERACTION_RANGE, interactBox.min); + // // Scale by interact range + // glm_vec2_scale(interactBox.min, PLAYER_INTERACTION_RANGE, interactBox.min); - // Add entity position, this makes the center of the box. - glm_vec2_add(interactBox.min, entity->position, interactBox.min); + // // Add entity position, this makes the center of the box. + // glm_vec2_add(interactBox.min, entity->position, interactBox.min); - // Copy to max - glm_vec2_copy(interactBox.min, interactBox.max); + // // Copy to max + // glm_vec2_copy(interactBox.min, interactBox.max); - // Size of the hitbox - vec2 halfSize = { - TILESET_ENTITIES.tileWidth * PLAYER_INTERACTION_SIZE * 0.5f, - TILESET_ENTITIES.tileHeight * PLAYER_INTERACTION_SIZE * 0.5f - }; + // // Size of the hitbox + // vec2 halfSize = { + // TILESET_ENTITIES.tileWidth * PLAYER_INTERACTION_SIZE * 0.5f, + // TILESET_ENTITIES.tileHeight * PLAYER_INTERACTION_SIZE * 0.5f + // }; - // Subtract from min, add to max. - glm_vec2_sub(interactBox.min, halfSize, interactBox.min); - glm_vec2_add(interactBox.max, halfSize, interactBox.max); + // // Subtract from min, add to max. + // glm_vec2_sub(interactBox.min, halfSize, interactBox.min); + // glm_vec2_add(interactBox.max, halfSize, interactBox.max); - // For each entity - entity_t *start = entity->map->entities; - entity_t *end = &entity->map->entities[entity->map->entityCount]; - vec2 otherSize = { TILESET_ENTITIES.tileWidth, TILESET_ENTITIES.tileHeight }; - physicsbox_t otherBox; - physicsboxboxresult_t result; + // // For each entity + // entity_t *start = entity->map->entities; + // entity_t *end = &entity->map->entities[entity->map->entityCount]; + // vec2 otherSize = { TILESET_ENTITIES.tileWidth, TILESET_ENTITIES.tileHeight }; + // physicsbox_t otherBox; + // physicsboxboxresult_t result; - do { - if(start->type != ENTITY_TYPE_NPC) continue; + // do { + // if(start->type != ENTITY_TYPE_NPC) continue; - // Setup other box. - glm_vec2_copy(start->position, otherBox.min); - glm_vec2_copy(start->position, otherBox.max); - glm_vec2_sub(otherBox.min, otherSize, otherBox.min); - glm_vec2_add(otherBox.min, otherSize, otherBox.max); + // // Setup other box. + // glm_vec2_copy(start->position, otherBox.min); + // glm_vec2_copy(start->position, otherBox.max); + // glm_vec2_sub(otherBox.min, otherSize, otherBox.min); + // glm_vec2_add(otherBox.min, otherSize, otherBox.max); - physicsBoxCheckBox(interactBox, otherBox, &result); - if(!result.hit) continue; + // physicsBoxCheckBox(interactBox, otherBox, &result); + // if(!result.hit) continue; - printf("Interacted with entity at (%.2f, %.2f)\n", start->position[0], start->position[1]); - break; - } while(++start != end); + // printf("Interacted with entity at (%.2f, %.2f)\n", start->position[0], start->position[1]); + // break; + // } while(++start != end); } \ No newline at end of file diff --git a/src/rpg/rpg.c b/src/rpg/rpg.c index 6464364..285b977 100644 --- a/src/rpg/rpg.c +++ b/src/rpg/rpg.c @@ -6,13 +6,21 @@ */ #include "rpg.h" +#include "entity/entity.h" errorret_t rpgInit(void) { + // TEST + entityInit(&ENTITIES[0], ENTITY_TYPE_PLAYER); + errorOk(); } void rpgUpdate(void) { - + entity_t *ent = &ENTITIES[0]; + do { + if(ent->type == ENTITY_TYPE_NULL) continue; + entityUpdate(ent); + } while(++ent < &ENTITIES[ENTITY_COUNT]); } void rpgDispose(void) { diff --git a/src/scene/scene.h b/src/scene/scene.h index 2f491cf..39c89a4 100644 --- a/src/scene/scene.h +++ b/src/scene/scene.h @@ -21,5 +21,4 @@ typedef struct { void (*render)(scenedata_t *data); void (*dispose)(scenedata_t *data); uint8_t flags; - color_t background; } scene_t; \ No newline at end of file diff --git a/src/scene/scene/CMakeLists.txt b/src/scene/scene/CMakeLists.txt index 2f232af..a7e70c6 100644 --- a/src/scene/scene/CMakeLists.txt +++ b/src/scene/scene/CMakeLists.txt @@ -7,6 +7,7 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE scenetest.c + scenemap.c ) # Subdirs \ No newline at end of file diff --git a/src/scene/scene/scenemap.c b/src/scene/scene/scenemap.c new file mode 100644 index 0000000..ff9268a --- /dev/null +++ b/src/scene/scene/scenemap.c @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "scenemap.h" + +errorret_t sceneMapInit(scenedata_t *data) { + errorOk(); +} + +void sceneMapUpdate(scenedata_t *data) { +} + +void sceneMapRender(scenedata_t *data) { + +} + +void sceneMapDispose(scenedata_t *data) { +} diff --git a/src/scene/scene/scenemap.h b/src/scene/scene/scenemap.h new file mode 100644 index 0000000..a907cc2 --- /dev/null +++ b/src/scene/scene/scenemap.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "scene/scene.h" + +typedef struct { + int32_t nothing; +} scenemap_t; + +errorret_t sceneMapInit(scenedata_t *data); +void sceneMapUpdate(scenedata_t *data); +void sceneMapRender(scenedata_t *data); +void sceneMapDispose(scenedata_t *data); + +static scene_t SCENE_MAP = { + .name = "map", + .init = sceneMapInit, + .update = sceneMapUpdate, + .render = sceneMapRender, + .dispose = sceneMapDispose, + .flags = 0 +}; \ No newline at end of file diff --git a/src/scene/scenedata.h b/src/scene/scenedata.h index c3fdd3e..4122c42 100644 --- a/src/scene/scenedata.h +++ b/src/scene/scenedata.h @@ -9,9 +9,11 @@ #include "scene/scene.h" #include "scene/scene/scenetest.h" +#include "scene/scene/scenemap.h" typedef struct scenedata_s { union { scenetest_t sceneTest; + scenemap_t sceneMap; }; } scenedata_t; diff --git a/src/scene/scenemanager.c b/src/scene/scenemanager.c index 4abad30..01fece0 100644 --- a/src/scene/scenemanager.c +++ b/src/scene/scenemanager.c @@ -18,6 +18,7 @@ errorret_t sceneManagerInit(void) { memoryZero(&SCENE_MANAGER, sizeof(scenemanager_t)); sceneManagerRegisterScene(&SCENE_TEST); + sceneManagerRegisterScene(&SCENE_MAP); errorOk(); } @@ -91,11 +92,6 @@ void sceneManagerRender(void) { SCENE_MANAGER.current->flags & SCENE_FLAG_INITIALIZED, "Current scene not initialized" ); - - frameBufferClear( - FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH, - SCENE_MANAGER.current->background - ); if(SCENE_MANAGER.current->render) { SCENE_MANAGER.current->render(&SCENE_MANAGER.sceneData); diff --git a/src/ui/ui.c b/src/ui/ui.c index 91adaff..e6fc597 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -6,21 +6,59 @@ */ #include "ui.h" +#include "ui/uiconsole.h" +#include "ui/uifps.h" +#include "util/memory.h" +#include "display/tileset/tileset_minogram.h" +#include "display/screen.h" ui_t UI; -void uiInit(void) { +errorret_t uiInit(void) { + memoryZero(&UI, sizeof(ui_t)); + + cameraInitOrthographic(&UI.camera); + // Initialize UI components here + uiSetFont(&TILESET_MINOGRAM); + + errorOk(); } void uiUpdate(void) { // Update UI state here + UI.camera.orthographic.left = 0; + UI.camera.orthographic.right = SCREEN.width; + UI.camera.orthographic.top = 0; + UI.camera.orthographic.bottom = SCREEN.height; } void uiRender(void) { + + cameraPushMatrix(&UI.camera); + // Render UI elements here + if(UI.font) { + uiConsoleRender(0, 0, UI.fontTileset, &UI.font->alphaImage.texture); + uiFPSRender(UI.fontTileset, &UI.font->alphaImage.texture); + } + + cameraPopMatrix(); +} + +errorret_t uiSetFont(const tileset_t *fontTileset) { + if(UI.font) { + assetUnlock(UI.font, UI.fontRef); + UI.font = NULL; + } + + UI.fontTileset = fontTileset; + assetManagerLoadAsset(fontTileset->image, &UI.font, &UI.fontRef); } void uiDispose(void) { - // Clean up UI resources here + if(UI.font) { + assetUnlock(UI.font, UI.fontRef); + UI.font = NULL; + } } \ No newline at end of file diff --git a/src/ui/ui.h b/src/ui/ui.h index b374c59..529aa86 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -7,17 +7,26 @@ #pragma once #include "dusk.h" +#include "asset/assetmanager.h" +#include "display/tileset/tileset.h" +#include "display/camera.h" typedef struct { - int32_t nothing; + camera_t camera; + + ref_t fontRef; + asset_t *font; + const tileset_t *fontTileset; } ui_t; extern ui_t UI; /** * Initializes the UI system, loading necessary resources. + * + * @return An errorret_t indicating success or failure. */ -void uiInit(void); +errorret_t uiInit(void); /** * Updates the UI state, handling user interactions and animations. @@ -29,6 +38,15 @@ void uiUpdate(void); */ void uiRender(void); +/** + * Sets the font tileset for UI text rendering. + * + * @param fontTileset Pointer to the tileset to use for UI fonts. + * + * @return An errorret_t indicating success or failure. + */ +errorret_t uiSetFont(const tileset_t *fontTileset); + /** * Cleans up and frees all UI resources. */ diff --git a/src/ui/uiconsole.c b/src/ui/uiconsole.c index 00865c8..e964ae2 100644 --- a/src/ui/uiconsole.c +++ b/src/ui/uiconsole.c @@ -26,7 +26,7 @@ void uiConsoleRender( continue; } uiTextDraw( - x, y + (i * TILESET_MINOGRAM.tileHeight), + x, y + (i * tileset->tileHeight), line, COLOR_WHITE, tileset, texture ); diff --git a/src/ui/uifps.c b/src/ui/uifps.c index 2f6bb12..77d1a36 100644 --- a/src/ui/uifps.c +++ b/src/ui/uifps.c @@ -10,7 +10,8 @@ #include "console/console.h" #include "util/string.h" #include "ui/uitext.h" -#include "display/framebuffer.h" +#include "display/screen.h" +#include "display/spritebatch.h" void uiFPSRender(const tileset_t *tileset, texture_t *texture) { if(stringCompare(consoleVarGet("fps")->value, "0") == 0) { @@ -36,7 +37,8 @@ void uiFPSRender(const tileset_t *tileset, texture_t *texture) { int32_t w, h; uiTextMeasure(buffer, tileset, &w, &h); uiTextDraw( - frameBufferGetWidth(FRAMEBUFFER_BOUND) - w, 0, + SCREEN.width - w, 0, buffer, color, tileset, texture ); + spriteBatchFlush(); } \ No newline at end of file