This commit is contained in:
2025-10-08 14:17:58 -05:00
parent 46f820690d
commit 67604eca8d
17 changed files with 230 additions and 165 deletions

View File

@@ -1,4 +1,4 @@
echo " = Dawn Init = "; echo " = Dawn Init = ";
fps 1; fps 1;
scene test; scene map;

View File

@@ -13,6 +13,7 @@
#include "display/spritebatch.h" #include "display/spritebatch.h"
#include "display/mesh/quad.h" #include "display/mesh/quad.h"
#include "display/screen.h" #include "display/screen.h"
#include "ui/ui.h"
display_t DISPLAY; display_t DISPLAY;
@@ -110,7 +111,12 @@ errorret_t displayUpdate(void) {
// Bind screen and render scene // Bind screen and render scene
screenBind(); screenBind();
frameBufferClear(
FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH,
COLOR_CORNFLOWER_BLUE
);
sceneManagerRender(); sceneManagerRender();
uiRender();
// UI will probs go here // UI will probs go here

View File

@@ -13,6 +13,7 @@
#include "display/display.h" #include "display/display.h"
#include "scene/scenemanager.h" #include "scene/scenemanager.h"
#include "asset/assetmanager.h" #include "asset/assetmanager.h"
#include "ui/ui.h"
#include "rpg/rpg.h" #include "rpg/rpg.h"
engine_t ENGINE; engine_t ENGINE;
@@ -30,6 +31,7 @@ errorret_t engineInit(void) {
inputInit(); inputInit();
errorChain(assetManagerInit()); errorChain(assetManagerInit());
errorChain(displayInit()); errorChain(displayInit());
errorChain(uiInit());
errorChain(rpgInit()); errorChain(rpgInit());
errorChain(sceneManagerInit()); errorChain(sceneManagerInit());
@@ -50,6 +52,7 @@ errorret_t engineUpdate(void) {
assetManagerUpdate(); assetManagerUpdate();
rpgUpdate(); rpgUpdate();
uiUpdate();
sceneManagerUpdate(); sceneManagerUpdate();
errorChain(displayUpdate()); errorChain(displayUpdate());
@@ -63,6 +66,7 @@ void engineExit(void) {
errorret_t engineDispose(void) { errorret_t engineDispose(void) {
sceneManagerDispose(); sceneManagerDispose();
rpgDispose(); rpgDispose();
uiDispose();
errorChain(displayDispose()); errorChain(displayDispose());
assetManagerDispose(); assetManagerDispose();
consoleDispose(); consoleDispose();

View File

@@ -6,22 +6,25 @@
*/ */
#include "entity.h" #include "entity.h"
#include "rpg/world/map.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h" #include "util/memory.h"
#include "display/tileset/tileset_entities.h" #include "display/tileset/tileset_entities.h"
#include "time/time.h" #include "time/time.h"
#include "util/math.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(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_COUNT, "Invalid entity type");
assertTrue(type != ENTITY_TYPE_NULL, "Cannot have NULL 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)); memoryZero(entity, sizeof(entity_t));
entity->type = type; entity->type = type;
entity->map = map;
// Init. I did use a callback struct but it was not flexible enough. // Init. I did use a callback struct but it was not flexible enough.
switch(type) { switch(type) {
@@ -42,66 +45,4 @@ void entityUpdate(entity_t *entity) {
assertNotNull(entity, "Entity pointer cannot be NULL"); assertNotNull(entity, "Entity pointer cannot be NULL");
assertTrue(entity->type < ENTITY_TYPE_COUNT, "Invalid entity type"); assertTrue(entity->type < ENTITY_TYPE_COUNT, "Invalid entity type");
assertTrue(entity->type != ENTITY_TYPE_NULL, "Cannot have NULL 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);
}
} }

View File

@@ -10,9 +10,11 @@
#include "rpg/entity/player.h" #include "rpg/entity/player.h"
#include "npc.h" #include "npc.h"
#include "physics/physics.h" #include "physics/physics.h"
#include "rpg/world/worldunit.h"
#define ENTITY_FRICTION 0.9f #define ENTITY_FRICTION 1
#define ENTITY_MIN_VELOCITY 0.05f #define ENTITY_MIN_VELOCITY 1
#define ENTITY_COUNT 256
typedef struct map_s map_t; typedef struct map_s map_t;
@@ -25,12 +27,10 @@ typedef enum {
} entitytype_t; } entitytype_t;
typedef struct entity_s { typedef struct entity_s {
map_t *map;
entitytype_t type; entitytype_t type;
direction_t direction; direction_t direction;
worldchunkpos_t position[3];
vec2 position; worldsubtile_t velocity[3];
vec2 velocity;
union { union {
player_t player; player_t player;
@@ -38,14 +38,15 @@ typedef struct entity_s {
}; };
} entity_t; } entity_t;
extern entity_t ENTITIES[ENTITY_COUNT];
/** /**
* Initializes an entity structure. * Initializes an entity structure.
* *
* @param entity Pointer to the entity structure to initialize. * @param entity Pointer to the entity structure to initialize.
* @param type The type of the entity. * @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. * Updates an entity.

View File

@@ -17,98 +17,98 @@ void playerInit(entity_t *entity) {
void playerMovement(entity_t *entity) { void playerMovement(entity_t *entity) {
assertNotNull(entity, "Entity pointer cannot be NULL"); assertNotNull(entity, "Entity pointer cannot be NULL");
// Update velocity. // // Update velocity.
vec2 dir = { // vec2 dir = {
inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT), // inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT),
inputAxis(INPUT_ACTION_DOWN, INPUT_ACTION_UP) // inputAxis(INPUT_ACTION_DOWN, INPUT_ACTION_UP)
}; // };
if(dir[0] == 0 && dir[1] == 0) return; // if(dir[0] == 0 && dir[1] == 0) return;
glm_vec2_normalize(dir); // glm_vec2_normalize(dir);
entity->velocity[0] += PLAYER_SPEED * dir[0]; // entity->velocity[0] += PLAYER_SPEED * dir[0];
entity->velocity[1] += PLAYER_SPEED * dir[1]; // entity->velocity[1] += PLAYER_SPEED * dir[1];
// Update direction. // // Update direction.
if(dir[0] > 0) { // if(dir[0] > 0) {
if(entity->direction == DIRECTION_RIGHT) { // if(entity->direction == DIRECTION_RIGHT) {
entity->direction = DIRECTION_RIGHT; // entity->direction = DIRECTION_RIGHT;
} else { // } else {
if(dir[1] < 0) { // if(dir[1] < 0) {
entity->direction = DIRECTION_UP; // entity->direction = DIRECTION_UP;
} else if(dir[1] > 0) { // } else if(dir[1] > 0) {
entity->direction = DIRECTION_DOWN; // entity->direction = DIRECTION_DOWN;
} else { // } else {
entity->direction = DIRECTION_RIGHT; // entity->direction = DIRECTION_RIGHT;
} // }
} // }
} else if(dir[0] < 0) { // } else if(dir[0] < 0) {
if(entity->direction == DIRECTION_LEFT) { // if(entity->direction == DIRECTION_LEFT) {
entity->direction = DIRECTION_LEFT; // entity->direction = DIRECTION_LEFT;
} else { // } else {
if(dir[1] < 0) { // if(dir[1] < 0) {
entity->direction = DIRECTION_UP; // entity->direction = DIRECTION_UP;
} else if(dir[1] > 0) { // } else if(dir[1] > 0) {
entity->direction = DIRECTION_DOWN; // entity->direction = DIRECTION_DOWN;
} else { // } else {
entity->direction = DIRECTION_LEFT; // entity->direction = DIRECTION_LEFT;
} // }
} // }
} else if(dir[1] < 0) { // } else if(dir[1] < 0) {
entity->direction = DIRECTION_UP; // entity->direction = DIRECTION_UP;
} else if(dir[1] > 0) { // } else if(dir[1] > 0) {
entity->direction = DIRECTION_DOWN; // entity->direction = DIRECTION_DOWN;
} // }
} }
void playerInteraction(entity_t *entity) { 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 // // Get direction vector
directionGetVec2(entity->direction, interactBox.min); // directionGetVec2(entity->direction, interactBox.min);
// Scale by interact range // // Scale by interact range
glm_vec2_scale(interactBox.min, PLAYER_INTERACTION_RANGE, interactBox.min); // glm_vec2_scale(interactBox.min, PLAYER_INTERACTION_RANGE, interactBox.min);
// Add entity position, this makes the center of the box. // // Add entity position, this makes the center of the box.
glm_vec2_add(interactBox.min, entity->position, interactBox.min); // glm_vec2_add(interactBox.min, entity->position, interactBox.min);
// Copy to max // // Copy to max
glm_vec2_copy(interactBox.min, interactBox.max); // glm_vec2_copy(interactBox.min, interactBox.max);
// Size of the hitbox // // Size of the hitbox
vec2 halfSize = { // vec2 halfSize = {
TILESET_ENTITIES.tileWidth * PLAYER_INTERACTION_SIZE * 0.5f, // TILESET_ENTITIES.tileWidth * PLAYER_INTERACTION_SIZE * 0.5f,
TILESET_ENTITIES.tileHeight * PLAYER_INTERACTION_SIZE * 0.5f // TILESET_ENTITIES.tileHeight * PLAYER_INTERACTION_SIZE * 0.5f
}; // };
// Subtract from min, add to max. // // Subtract from min, add to max.
glm_vec2_sub(interactBox.min, halfSize, interactBox.min); // glm_vec2_sub(interactBox.min, halfSize, interactBox.min);
glm_vec2_add(interactBox.max, halfSize, interactBox.max); // glm_vec2_add(interactBox.max, halfSize, interactBox.max);
// For each entity // // For each entity
entity_t *start = entity->map->entities; // entity_t *start = entity->map->entities;
entity_t *end = &entity->map->entities[entity->map->entityCount]; // entity_t *end = &entity->map->entities[entity->map->entityCount];
vec2 otherSize = { TILESET_ENTITIES.tileWidth, TILESET_ENTITIES.tileHeight }; // vec2 otherSize = { TILESET_ENTITIES.tileWidth, TILESET_ENTITIES.tileHeight };
physicsbox_t otherBox; // physicsbox_t otherBox;
physicsboxboxresult_t result; // physicsboxboxresult_t result;
do { // do {
if(start->type != ENTITY_TYPE_NPC) continue; // if(start->type != ENTITY_TYPE_NPC) continue;
// Setup other box. // // Setup other box.
glm_vec2_copy(start->position, otherBox.min); // glm_vec2_copy(start->position, otherBox.min);
glm_vec2_copy(start->position, otherBox.max); // glm_vec2_copy(start->position, otherBox.max);
glm_vec2_sub(otherBox.min, otherSize, otherBox.min); // glm_vec2_sub(otherBox.min, otherSize, otherBox.min);
glm_vec2_add(otherBox.min, otherSize, otherBox.max); // glm_vec2_add(otherBox.min, otherSize, otherBox.max);
physicsBoxCheckBox(interactBox, otherBox, &result); // physicsBoxCheckBox(interactBox, otherBox, &result);
if(!result.hit) continue; // if(!result.hit) continue;
printf("Interacted with entity at (%.2f, %.2f)\n", start->position[0], start->position[1]); // printf("Interacted with entity at (%.2f, %.2f)\n", start->position[0], start->position[1]);
break; // break;
} while(++start != end); // } while(++start != end);
} }

View File

@@ -6,13 +6,21 @@
*/ */
#include "rpg.h" #include "rpg.h"
#include "entity/entity.h"
errorret_t rpgInit(void) { errorret_t rpgInit(void) {
// TEST
entityInit(&ENTITIES[0], ENTITY_TYPE_PLAYER);
errorOk(); errorOk();
} }
void rpgUpdate(void) { 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) { void rpgDispose(void) {

View File

@@ -21,5 +21,4 @@ typedef struct {
void (*render)(scenedata_t *data); void (*render)(scenedata_t *data);
void (*dispose)(scenedata_t *data); void (*dispose)(scenedata_t *data);
uint8_t flags; uint8_t flags;
color_t background;
} scene_t; } scene_t;

View File

@@ -7,6 +7,7 @@
target_sources(${DUSK_TARGET_NAME} target_sources(${DUSK_TARGET_NAME}
PRIVATE PRIVATE
scenetest.c scenetest.c
scenemap.c
) )
# Subdirs # Subdirs

View File

@@ -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) {
}

View File

@@ -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
};

View File

@@ -9,9 +9,11 @@
#include "scene/scene.h" #include "scene/scene.h"
#include "scene/scene/scenetest.h" #include "scene/scene/scenetest.h"
#include "scene/scene/scenemap.h"
typedef struct scenedata_s { typedef struct scenedata_s {
union { union {
scenetest_t sceneTest; scenetest_t sceneTest;
scenemap_t sceneMap;
}; };
} scenedata_t; } scenedata_t;

View File

@@ -18,6 +18,7 @@ errorret_t sceneManagerInit(void) {
memoryZero(&SCENE_MANAGER, sizeof(scenemanager_t)); memoryZero(&SCENE_MANAGER, sizeof(scenemanager_t));
sceneManagerRegisterScene(&SCENE_TEST); sceneManagerRegisterScene(&SCENE_TEST);
sceneManagerRegisterScene(&SCENE_MAP);
errorOk(); errorOk();
} }
@@ -92,11 +93,6 @@ void sceneManagerRender(void) {
"Current scene not initialized" "Current scene not initialized"
); );
frameBufferClear(
FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH,
SCENE_MANAGER.current->background
);
if(SCENE_MANAGER.current->render) { if(SCENE_MANAGER.current->render) {
SCENE_MANAGER.current->render(&SCENE_MANAGER.sceneData); SCENE_MANAGER.current->render(&SCENE_MANAGER.sceneData);
} }

View File

@@ -6,21 +6,59 @@
*/ */
#include "ui.h" #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; ui_t UI;
void uiInit(void) { errorret_t uiInit(void) {
memoryZero(&UI, sizeof(ui_t));
cameraInitOrthographic(&UI.camera);
// Initialize UI components here // Initialize UI components here
uiSetFont(&TILESET_MINOGRAM);
errorOk();
} }
void uiUpdate(void) { void uiUpdate(void) {
// Update UI state here // 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) { void uiRender(void) {
cameraPushMatrix(&UI.camera);
// Render UI elements here // 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) { void uiDispose(void) {
// Clean up UI resources here if(UI.font) {
assetUnlock(UI.font, UI.fontRef);
UI.font = NULL;
}
} }

View File

@@ -7,17 +7,26 @@
#pragma once #pragma once
#include "dusk.h" #include "dusk.h"
#include "asset/assetmanager.h"
#include "display/tileset/tileset.h"
#include "display/camera.h"
typedef struct { typedef struct {
int32_t nothing; camera_t camera;
ref_t fontRef;
asset_t *font;
const tileset_t *fontTileset;
} ui_t; } ui_t;
extern ui_t UI; extern ui_t UI;
/** /**
* Initializes the UI system, loading necessary resources. * 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. * Updates the UI state, handling user interactions and animations.
@@ -29,6 +38,15 @@ void uiUpdate(void);
*/ */
void uiRender(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. * Cleans up and frees all UI resources.
*/ */

View File

@@ -26,7 +26,7 @@ void uiConsoleRender(
continue; continue;
} }
uiTextDraw( uiTextDraw(
x, y + (i * TILESET_MINOGRAM.tileHeight), x, y + (i * tileset->tileHeight),
line, COLOR_WHITE, line, COLOR_WHITE,
tileset, texture tileset, texture
); );

View File

@@ -10,7 +10,8 @@
#include "console/console.h" #include "console/console.h"
#include "util/string.h" #include "util/string.h"
#include "ui/uitext.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) { void uiFPSRender(const tileset_t *tileset, texture_t *texture) {
if(stringCompare(consoleVarGet("fps")->value, "0") == 0) { if(stringCompare(consoleVarGet("fps")->value, "0") == 0) {
@@ -36,7 +37,8 @@ void uiFPSRender(const tileset_t *tileset, texture_t *texture) {
int32_t w, h; int32_t w, h;
uiTextMeasure(buffer, tileset, &w, &h); uiTextMeasure(buffer, tileset, &w, &h);
uiTextDraw( uiTextDraw(
frameBufferGetWidth(FRAMEBUFFER_BOUND) - w, 0, SCREEN.width - w, 0,
buffer, color, tileset, texture buffer, color, tileset, texture
); );
spriteBatchFlush();
} }