From 8181a28557c629fe2e254d0331ca0aadf5c91785 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 26 Jun 2026 19:42:34 -0500 Subject: [PATCH] Bunch of stuff done --- assets/chunks/0_0_0.dcf | Bin 0 -> 63500 bytes src/dusk/asset/loader/CMakeLists.txt | 3 +- src/dusk/asset/loader/assetloader.c | 6 + src/dusk/asset/loader/assetloader.h | 5 + src/dusk/asset/loader/chunk/CMakeLists.txt | 10 ++ .../asset/loader/chunk/assetchunkloader.c | 115 ++++++++++++++++++ .../asset/loader/chunk/assetchunkloader.h | 65 ++++++++++ src/dusk/rpg/entity/CMakeLists.txt | 4 +- src/dusk/rpg/entity/anim/CMakeLists.txt | 13 ++ src/dusk/rpg/entity/anim/entityanim.c | 27 ++++ src/dusk/rpg/entity/anim/entityanim.h | 37 ++++++ src/dusk/rpg/entity/anim/entityanimidle.c | 14 +++ src/dusk/rpg/entity/anim/entityanimidle.h | 18 +++ src/dusk/rpg/entity/anim/entityanimrun.c | 21 ++++ src/dusk/rpg/entity/anim/entityanimrun.h | 21 ++++ src/dusk/rpg/entity/anim/entityanimturn.c | 14 +++ src/dusk/rpg/entity/anim/entityanimturn.h | 21 ++++ src/dusk/rpg/entity/anim/entityanimwalk.c | 21 ++++ src/dusk/rpg/entity/anim/entityanimwalk.h | 21 ++++ src/dusk/rpg/entity/entity.c | 30 +++++ src/dusk/rpg/entity/entity.h | 19 ++- src/dusk/rpg/entity/entityanim.c | 41 ------- src/dusk/rpg/entity/entityanim.h | 29 ----- src/dusk/rpg/entity/interact/CMakeLists.txt | 9 ++ .../entity/{ => interact}/entityinteract.c | 2 +- .../entity/{ => interact}/entityinteract.h | 0 src/dusk/rpg/overworld/CMakeLists.txt | 3 +- src/dusk/rpg/overworld/chunk.h | 1 - src/dusk/rpg/overworld/map.c | 103 +++++++--------- src/dusk/rpg/overworld/worldpos.h | 6 +- src/dusk/rpg/rpg.c | 12 ++ src/dusk/scene/overworld/sceneoverworld.c | 24 +++- 32 files changed, 567 insertions(+), 148 deletions(-) create mode 100644 assets/chunks/0_0_0.dcf create mode 100644 src/dusk/asset/loader/chunk/CMakeLists.txt create mode 100644 src/dusk/asset/loader/chunk/assetchunkloader.c create mode 100644 src/dusk/asset/loader/chunk/assetchunkloader.h create mode 100644 src/dusk/rpg/entity/anim/CMakeLists.txt create mode 100644 src/dusk/rpg/entity/anim/entityanim.c create mode 100644 src/dusk/rpg/entity/anim/entityanim.h create mode 100644 src/dusk/rpg/entity/anim/entityanimidle.c create mode 100644 src/dusk/rpg/entity/anim/entityanimidle.h create mode 100644 src/dusk/rpg/entity/anim/entityanimrun.c create mode 100644 src/dusk/rpg/entity/anim/entityanimrun.h create mode 100644 src/dusk/rpg/entity/anim/entityanimturn.c create mode 100644 src/dusk/rpg/entity/anim/entityanimturn.h create mode 100644 src/dusk/rpg/entity/anim/entityanimwalk.c create mode 100644 src/dusk/rpg/entity/anim/entityanimwalk.h delete mode 100644 src/dusk/rpg/entity/entityanim.c delete mode 100644 src/dusk/rpg/entity/entityanim.h create mode 100644 src/dusk/rpg/entity/interact/CMakeLists.txt rename src/dusk/rpg/entity/{ => interact}/entityinteract.c (97%) rename src/dusk/rpg/entity/{ => interact}/entityinteract.h (100%) diff --git a/assets/chunks/0_0_0.dcf b/assets/chunks/0_0_0.dcf new file mode 100644 index 0000000000000000000000000000000000000000..7e7f4803f22dbe82792fc1c203e628610ddc65bc GIT binary patch literal 63500 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 literal 0 HcmV?d00001 diff --git a/src/dusk/asset/loader/CMakeLists.txt b/src/dusk/asset/loader/CMakeLists.txt index 9bca3019..556ccd17 100644 --- a/src/dusk/asset/loader/CMakeLists.txt +++ b/src/dusk/asset/loader/CMakeLists.txt @@ -14,4 +14,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} # Subdirs add_subdirectory(display) add_subdirectory(locale) -add_subdirectory(json) \ No newline at end of file +add_subdirectory(json) +add_subdirectory(chunk) \ No newline at end of file diff --git a/src/dusk/asset/loader/assetloader.c b/src/dusk/asset/loader/assetloader.c index 5987246f..902731b6 100644 --- a/src/dusk/asset/loader/assetloader.c +++ b/src/dusk/asset/loader/assetloader.c @@ -39,4 +39,10 @@ assetloadercallbacks_t ASSET_LOADER_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = { .loadAsync = assetJsonLoaderAsync, .dispose = assetJsonDispose }, + + [ASSET_LOADER_TYPE_CHUNK] = { + .loadSync = assetChunkLoaderSync, + .loadAsync = assetChunkLoaderAsync, + .dispose = assetChunkDispose + }, }; diff --git a/src/dusk/asset/loader/assetloader.h b/src/dusk/asset/loader/assetloader.h index 8324581d..61ba9696 100644 --- a/src/dusk/asset/loader/assetloader.h +++ b/src/dusk/asset/loader/assetloader.h @@ -11,6 +11,7 @@ #include "asset/loader/display/assettilesetloader.h" #include "asset/loader/locale/assetlocaleloader.h" #include "asset/loader/json/assetjsonloader.h" +#include "asset/loader/chunk/assetchunkloader.h" typedef enum { ASSET_LOADER_TYPE_NULL, @@ -20,6 +21,7 @@ typedef enum { ASSET_LOADER_TYPE_TILESET, ASSET_LOADER_TYPE_LOCALE, ASSET_LOADER_TYPE_JSON, + ASSET_LOADER_TYPE_CHUNK, ASSET_LOADER_TYPE_COUNT } assetloadertype_t; @@ -30,6 +32,7 @@ typedef union { assettilesetloaderinput_t tileset; assetlocaleloaderinput_t locale; assetjsonloaderinput_t json; + assetchunkloaderinput_t chunk; } assetloaderinput_t; typedef union { @@ -38,6 +41,7 @@ typedef union { assettilesetloaderloading_t tileset; assetlocaleloaderloading_t locale; assetjsonloaderloading_t json; + assetchunkloaderloading_t chunk; } assetloaderloading_t; typedef union { @@ -46,6 +50,7 @@ typedef union { assettilesetoutput_t tileset; assetlocaleoutput_t locale; assetjsonoutput_t json; + assetchunkoutput_t chunk; } assetloaderoutput_t; typedef struct assetloading_s assetloading_t; diff --git a/src/dusk/asset/loader/chunk/CMakeLists.txt b/src/dusk/asset/loader/chunk/CMakeLists.txt new file mode 100644 index 00000000..64e16290 --- /dev/null +++ b/src/dusk/asset/loader/chunk/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2026 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + assetchunkloader.c +) diff --git a/src/dusk/asset/loader/chunk/assetchunkloader.c b/src/dusk/asset/loader/chunk/assetchunkloader.c new file mode 100644 index 00000000..7b1a09ce --- /dev/null +++ b/src/dusk/asset/loader/chunk/assetchunkloader.c @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assetchunkloader.h" +#include "assert/assert.h" +#include "util/memory.h" +#include "util/endian.h" +#include "asset/loader/assetloading.h" +#include "asset/loader/assetentry.h" + +errorret_t assetChunkLoaderAsync(assetloading_t *loading) { + assertNotNull(loading, "Loading cannot be NULL"); + assertNotMainThread("Should be called from an async thread."); + + if(loading->loading.chunk.state != ASSET_CHUNK_LOADING_STATE_READ_FILE) { + errorOk(); + } + + assertNull(loading->loading.chunk.data, "Data already defined?"); + + assetfile_t *file = &loading->loading.chunk.file; + assetLoaderErrorChain(loading, + assetFileInit(file, loading->entry->name, NULL, NULL) + ); + + uint8_t *data = memoryAllocate(file->size); + assetLoaderErrorChain(loading, assetFileOpen(file)); + assetLoaderErrorChain(loading, assetFileRead(file, data, file->size)); + assetLoaderErrorChain(loading, assetFileClose(file)); + assetLoaderErrorChain(loading, assetFileDispose(file)); + assertTrue( + file->lastRead == file->size, + "Failed to read entire chunk file." + ); + + loading->loading.chunk.data = data; + loading->loading.chunk.state = ASSET_CHUNK_LOADING_STATE_PARSE; + loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC; + errorOk(); +} + +errorret_t assetChunkLoaderSync(assetloading_t *loading) { + assertNotNull(loading, "Loading cannot be NULL"); + assertTrue(loading->type == ASSET_LOADER_TYPE_CHUNK, "Invalid type."); + assertIsMainThread("Must be called from the main thread."); + + switch(loading->loading.chunk.state) { + case ASSET_CHUNK_LOADING_STATE_INITIAL: + loading->loading.chunk.state = ASSET_CHUNK_LOADING_STATE_READ_FILE; + loading->entry->state = ASSET_ENTRY_STATE_PENDING_ASYNC; + errorOk(); + break; + + case ASSET_CHUNK_LOADING_STATE_PARSE: + break; + + default: + errorOk(); + } + + uint8_t *data = loading->loading.chunk.data; + assertNotNull(data, "Chunk data should have been loaded by now."); + + if(data[0] != 'D' || data[1] != 'C' || data[2] != 'F') { + memoryFree(data); + assetLoaderErrorThrow(loading, "Invalid chunk file header"); + } + + uint32_t version = endianLittleToHost32(*(uint32_t *)(data + 4)); + if(version != ASSET_CHUNK_FILE_VERSION) { + memoryFree(data); + assetLoaderErrorThrow( + loading, "Unsupported chunk file version %u", version + ); + } + + assetchunkoutput_t *out = &loading->entry->data.chunk; + size_t offset = 8; + + size_t tileSize = CHUNK_TILE_COUNT * sizeof(tile_t); + memoryCopy(out->tiles, data + offset, tileSize); + offset += tileSize; + + out->vertCount = endianLittleToHost32(*(uint32_t *)(data + offset)); + offset += sizeof(uint32_t); + + assertTrue( + out->vertCount <= CHUNK_VERTEX_COUNT, + "Chunk vertex count exceeds maximum." + ); + + memoryCopy( + out->vertices, + data + offset, + out->vertCount * sizeof(meshvertex_t) + ); + + memoryFree(data); + loading->loading.chunk.data = NULL; + + loading->entry->state = ASSET_ENTRY_STATE_LOADED; + errorOk(); +} + +errorret_t assetChunkDispose(assetentry_t *entry) { + assertNotNull(entry, "Entry cannot be NULL"); + assertTrue(entry->type == ASSET_LOADER_TYPE_CHUNK, "Invalid type."); + assertIsMainThread("Must be called from the main thread."); + + errorOk(); +} diff --git a/src/dusk/asset/loader/chunk/assetchunkloader.h b/src/dusk/asset/loader/chunk/assetchunkloader.h new file mode 100644 index 00000000..44e7636f --- /dev/null +++ b/src/dusk/asset/loader/chunk/assetchunkloader.h @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "asset/assetfile.h" +#include "rpg/overworld/chunk.h" + +#define ASSET_CHUNK_FILE_VERSION 1 + +typedef struct assetloading_s assetloading_t; +typedef struct assetentry_s assetentry_t; + +typedef struct { + void *nothing; +} assetchunkloaderinput_t; + +typedef enum { + ASSET_CHUNK_LOADING_STATE_INITIAL, + ASSET_CHUNK_LOADING_STATE_READ_FILE, + ASSET_CHUNK_LOADING_STATE_PARSE, + ASSET_CHUNK_LOADING_STATE_DONE +} assetchunkloadingstate_t; + +typedef struct { + assetfile_t file; + assetchunkloadingstate_t state; + uint8_t *data; +} assetchunkloaderloading_t; + +typedef struct { + tile_t tiles[CHUNK_TILE_COUNT]; + uint32_t vertCount; + meshvertex_t vertices[CHUNK_VERTEX_COUNT]; +} assetchunkoutput_t; + +/** + * Asynchronous loader for chunk assets. Reads the raw DCF file bytes into + * the loading buffer so the sync phase can parse without blocking the + * main thread on I/O. + * + * @param loading Loading information for the asset being loaded. + * @return Error code indicating success or failure of the load operation. + */ +errorret_t assetChunkLoaderAsync(assetloading_t *loading); + +/** + * Synchronous loader for chunk assets. Validates the DCF binary previously + * read by the async phase and populates the output assetchunkoutput_t. + * + * @param loading Loading information for the asset being loaded. + * @return Error code indicating success or failure of the load operation. + */ +errorret_t assetChunkLoaderSync(assetloading_t *loading); + +/** + * Disposer for chunk assets. + * + * @param entry Asset entry containing the chunk data to dispose. + * @return Error code indicating success or failure of the dispose operation. + */ +errorret_t assetChunkDispose(assetentry_t *entry); diff --git a/src/dusk/rpg/entity/CMakeLists.txt b/src/dusk/rpg/entity/CMakeLists.txt index 8a249fd4..0cf1f321 100644 --- a/src/dusk/rpg/entity/CMakeLists.txt +++ b/src/dusk/rpg/entity/CMakeLists.txt @@ -7,10 +7,10 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC entity.c - entityanim.c entitydir.c - entityinteract.c player.c ) +add_subdirectory(anim) +add_subdirectory(interact) add_subdirectory(npc) \ No newline at end of file diff --git a/src/dusk/rpg/entity/anim/CMakeLists.txt b/src/dusk/rpg/entity/anim/CMakeLists.txt new file mode 100644 index 00000000..54c1015e --- /dev/null +++ b/src/dusk/rpg/entity/anim/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) 2026 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +target_sources(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + entityanim.c + entityanimidle.c + entityanimturn.c + entityanimwalk.c + entityanimrun.c +) diff --git a/src/dusk/rpg/entity/anim/entityanim.c b/src/dusk/rpg/entity/anim/entityanim.c new file mode 100644 index 00000000..1d472662 --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanim.c @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "rpg/entity/entity.h" +#include "time/time.h" + +const entityanimcallback_t ENTITY_ANIM_CALLBACKS[ENTITY_ANIM_COUNT] = { + [ENTITY_ANIM_IDLE] = { entityAnimIdleUpdate }, + [ENTITY_ANIM_TURN] = { entityAnimTurnUpdate }, + [ENTITY_ANIM_WALK] = { entityAnimWalkUpdate }, + [ENTITY_ANIM_RUN] = { entityAnimRunUpdate }, +}; + +void entityAnimUpdate(entity_t *entity) { + if(entity->animation != ENTITY_ANIM_IDLE) { + entity->animTime -= TIME.delta; + if(entity->animTime <= 0) { + entity->animation = ENTITY_ANIM_IDLE; + entity->animTime = 0; + } + } + ENTITY_ANIM_CALLBACKS[entity->animation].update(entity); +} diff --git a/src/dusk/rpg/entity/anim/entityanim.h b/src/dusk/rpg/entity/anim/entityanim.h new file mode 100644 index 00000000..548c289f --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanim.h @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "entityanimidle.h" +#include "entityanimturn.h" +#include "entityanimwalk.h" +#include "entityanimrun.h" + +typedef struct entity_s entity_t; + +typedef enum { + ENTITY_ANIM_IDLE, + ENTITY_ANIM_TURN, + ENTITY_ANIM_WALK, + ENTITY_ANIM_RUN, + ENTITY_ANIM_COUNT +} entityanim_t; + +typedef struct { + /** Updates the render position for this animation state. */ + void (*update)(entity_t *entity); +} entityanimcallback_t; + +extern const entityanimcallback_t ENTITY_ANIM_CALLBACKS[ENTITY_ANIM_COUNT]; + +/** + * Updates the entity animation timer and render position. + * + * @param entity Pointer to the entity to update. + */ +void entityAnimUpdate(entity_t *entity); diff --git a/src/dusk/rpg/entity/anim/entityanimidle.c b/src/dusk/rpg/entity/anim/entityanimidle.c new file mode 100644 index 00000000..53836258 --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanimidle.c @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "rpg/entity/entity.h" + +void entityAnimIdleUpdate(entity_t *entity) { + entity->renderPosition[0] = (float_t)entity->position.x; + entity->renderPosition[1] = (float_t)entity->position.y; + entity->renderPosition[2] = (float_t)entity->position.z; +} diff --git a/src/dusk/rpg/entity/anim/entityanimidle.h b/src/dusk/rpg/entity/anim/entityanimidle.h new file mode 100644 index 00000000..b7bd9a53 --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanimidle.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct entity_s entity_t; + +/** + * Updates render position for the idle animation state. + * + * @param entity Pointer to the entity to update. + */ +void entityAnimIdleUpdate(entity_t *entity); diff --git a/src/dusk/rpg/entity/anim/entityanimrun.c b/src/dusk/rpg/entity/anim/entityanimrun.c new file mode 100644 index 00000000..f3ce19d8 --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanimrun.c @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "rpg/entity/entity.h" + +void entityAnimRunUpdate(entity_t *entity) { + float_t t = 1.0f - (entity->animTime / ENTITY_ANIM_RUN_DURATION); + entity->renderPosition[0] = (float_t)entity->lastPosition.x + t * ( + (float_t)entity->position.x - (float_t)entity->lastPosition.x + ); + entity->renderPosition[1] = (float_t)entity->lastPosition.y + t * ( + (float_t)entity->position.y - (float_t)entity->lastPosition.y + ); + entity->renderPosition[2] = (float_t)entity->lastPosition.z + t * ( + (float_t)entity->position.z - (float_t)entity->lastPosition.z + ); +} diff --git a/src/dusk/rpg/entity/anim/entityanimrun.h b/src/dusk/rpg/entity/anim/entityanimrun.h new file mode 100644 index 00000000..ecace434 --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanimrun.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "time/time.h" + +typedef struct entity_s entity_t; + +#define ENTITY_ANIM_RUN_DURATION TIME_TICKS_TO_TIME(6) + +/** + * Updates render position for the run animation state. + * + * @param entity Pointer to the entity to update. + */ +void entityAnimRunUpdate(entity_t *entity); diff --git a/src/dusk/rpg/entity/anim/entityanimturn.c b/src/dusk/rpg/entity/anim/entityanimturn.c new file mode 100644 index 00000000..feab189b --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanimturn.c @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "rpg/entity/entity.h" + +void entityAnimTurnUpdate(entity_t *entity) { + entity->renderPosition[0] = (float_t)entity->position.x; + entity->renderPosition[1] = (float_t)entity->position.y; + entity->renderPosition[2] = (float_t)entity->position.z; +} diff --git a/src/dusk/rpg/entity/anim/entityanimturn.h b/src/dusk/rpg/entity/anim/entityanimturn.h new file mode 100644 index 00000000..aa765dfd --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanimturn.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "time/time.h" + +typedef struct entity_s entity_t; + +#define ENTITY_ANIM_TURN_DURATION TIME_TICKS_TO_TIME(2) + +/** + * Updates render position for the turn animation state. + * + * @param entity Pointer to the entity to update. + */ +void entityAnimTurnUpdate(entity_t *entity); diff --git a/src/dusk/rpg/entity/anim/entityanimwalk.c b/src/dusk/rpg/entity/anim/entityanimwalk.c new file mode 100644 index 00000000..e5af80ff --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanimwalk.c @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "rpg/entity/entity.h" + +void entityAnimWalkUpdate(entity_t *entity) { + float_t t = 1.0f - (entity->animTime / ENTITY_ANIM_WALK_DURATION); + entity->renderPosition[0] = (float_t)entity->lastPosition.x + t * ( + (float_t)entity->position.x - (float_t)entity->lastPosition.x + ); + entity->renderPosition[1] = (float_t)entity->lastPosition.y + t * ( + (float_t)entity->position.y - (float_t)entity->lastPosition.y + ); + entity->renderPosition[2] = (float_t)entity->lastPosition.z + t * ( + (float_t)entity->position.z - (float_t)entity->lastPosition.z + ); +} diff --git a/src/dusk/rpg/entity/anim/entityanimwalk.h b/src/dusk/rpg/entity/anim/entityanimwalk.h new file mode 100644 index 00000000..608a46ff --- /dev/null +++ b/src/dusk/rpg/entity/anim/entityanimwalk.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "time/time.h" + +typedef struct entity_s entity_t; + +#define ENTITY_ANIM_WALK_DURATION TIME_TICKS_TO_TIME(10) + +/** + * Updates render position for the walk animation state. + * + * @param entity Pointer to the entity to update. + */ +void entityAnimWalkUpdate(entity_t *entity); diff --git a/src/dusk/rpg/entity/entity.c b/src/dusk/rpg/entity/entity.c index 85d00fb6..af4d272a 100644 --- a/src/dusk/rpg/entity/entity.c +++ b/src/dusk/rpg/entity/entity.c @@ -12,6 +12,7 @@ #include "util/math.h" #include "rpg/cutscene/cutscenemode.h" #include "rpg/overworld/map.h" +#include "rpg/overworld/chunk.h" #include "rpg/overworld/tile.h" entity_t ENTITIES[ENTITY_COUNT]; @@ -28,6 +29,7 @@ void entityInit(entity_t *entity, const entitytype_t type) { memoryZero(entity, sizeof(entity_t)); entity->id = (uint8_t)(entity - ENTITIES); entity->type = type; + entity->chunkIndex = 0xFF; if(ENTITY_CALLBACKS[type].init != NULL) ENTITY_CALLBACKS[type].init(entity); } @@ -216,4 +218,32 @@ uint8_t entityGetAvailable() { } while(++ent, ent < &ENTITIES[ENTITY_COUNT]); return 0xFF; +} + +void entitySetChunk(entity_t *entity, const uint8_t chunkIndex) { + assertNotNull(entity, "Entity pointer cannot be NULL"); + + if(entity->chunkIndex != 0xFF) { + chunk_t *old = mapGetChunk(entity->chunkIndex); + if(old != NULL) { + for(uint8_t i = 0; i < CHUNK_ENTITY_COUNT_MAX; i++) { + if(old->entities[i] != entity->id) continue; + old->entities[i] = 0xFF; + break; + } + } + } + + entity->chunkIndex = chunkIndex; + + if(chunkIndex != 0xFF) { + chunk_t *next = mapGetChunk(chunkIndex); + if(next != NULL) { + for(uint8_t i = 0; i < CHUNK_ENTITY_COUNT_MAX; i++) { + if(next->entities[i] != 0xFF) continue; + next->entities[i] = entity->id; + break; + } + } + } } \ No newline at end of file diff --git a/src/dusk/rpg/entity/entity.h b/src/dusk/rpg/entity/entity.h index 544e341c..6e8f9085 100644 --- a/src/dusk/rpg/entity/entity.h +++ b/src/dusk/rpg/entity/entity.h @@ -7,8 +7,8 @@ #pragma once #include "entitydir.h" -#include "entityanim.h" -#include "entityinteract.h" +#include "anim/entityanim.h" +#include "interact/entityinteract.h" #include "entitytype.h" #include "npc/npc.h" @@ -29,6 +29,8 @@ typedef struct entity_s { float_t animTime; entityinteract_t interact; + + uint8_t chunkIndex; } entity_t; extern entity_t ENTITIES[ENTITY_COUNT]; @@ -107,7 +109,16 @@ entity_t *entityGetAt(const worldpos_t pos); /** * Gets an available entity index. - * + * * @return The index of an available entity, or 0xFF if none are available. */ -uint8_t entityGetAvailable(); \ No newline at end of file +uint8_t entityGetAvailable(); + +/** + * Assigns an entity to a chunk, removing it from its current chunk first. + * Pass 0xFF as chunkIndex to detach the entity from any chunk. + * + * @param entity Pointer to the entity. + * @param chunkIndex Index of the chunk to assign to, or 0xFF for none. + */ +void entitySetChunk(entity_t *entity, const uint8_t chunkIndex); \ No newline at end of file diff --git a/src/dusk/rpg/entity/entityanim.c b/src/dusk/rpg/entity/entityanim.c deleted file mode 100644 index 8882a222..00000000 --- a/src/dusk/rpg/entity/entityanim.c +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entity.h" -#include "time/time.h" - -void entityAnimUpdate(entity_t *entity) { - if(entity->animation != ENTITY_ANIM_IDLE) { - entity->animTime -= TIME.delta; - if(entity->animTime <= 0) { - entity->animation = ENTITY_ANIM_IDLE; - entity->animTime = 0; - } - } - - if( - entity->animation == ENTITY_ANIM_WALK || - entity->animation == ENTITY_ANIM_RUN - ) { - float_t duration = entity->animation == ENTITY_ANIM_WALK ? - ENTITY_ANIM_WALK_DURATION : ENTITY_ANIM_RUN_DURATION; - float_t t = 1.0f - (entity->animTime / duration); - entity->renderPosition[0] = (float_t)entity->lastPosition.x + t * ( - (float_t)entity->position.x - (float_t)entity->lastPosition.x - ); - entity->renderPosition[1] = (float_t)entity->lastPosition.y + t * ( - (float_t)entity->position.y - (float_t)entity->lastPosition.y - ); - entity->renderPosition[2] = (float_t)entity->lastPosition.z + t * ( - (float_t)entity->position.z - (float_t)entity->lastPosition.z - ); - } else { - entity->renderPosition[0] = (float_t)entity->position.x; - entity->renderPosition[1] = (float_t)entity->position.y; - entity->renderPosition[2] = (float_t)entity->position.z; - } -} \ No newline at end of file diff --git a/src/dusk/rpg/entity/entityanim.h b/src/dusk/rpg/entity/entityanim.h deleted file mode 100644 index c822d605..00000000 --- a/src/dusk/rpg/entity/entityanim.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "time/time.h" - -#define ENTITY_ANIM_TURN_DURATION TIME_TICKS_TO_TIME(2) -#define ENTITY_ANIM_WALK_DURATION TIME_TICKS_TO_TIME(12) -#define ENTITY_ANIM_RUN_DURATION TIME_TICKS_TO_TIME(6) - -typedef struct entity_s entity_t; - -typedef enum { - ENTITY_ANIM_IDLE, - ENTITY_ANIM_TURN, - ENTITY_ANIM_WALK, - ENTITY_ANIM_RUN, -} entityanim_t; - -/** - * Updates the entity's animation state. - * - * @param entity Pointer to the entity to update. - */ -void entityAnimUpdate(entity_t *entity); \ No newline at end of file diff --git a/src/dusk/rpg/entity/interact/CMakeLists.txt b/src/dusk/rpg/entity/interact/CMakeLists.txt new file mode 100644 index 00000000..f7e07e35 --- /dev/null +++ b/src/dusk/rpg/entity/interact/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2026 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +target_sources(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + entityinteract.c +) diff --git a/src/dusk/rpg/entity/entityinteract.c b/src/dusk/rpg/entity/interact/entityinteract.c similarity index 97% rename from src/dusk/rpg/entity/entityinteract.c rename to src/dusk/rpg/entity/interact/entityinteract.c index c618ab0c..83a1573d 100644 --- a/src/dusk/rpg/entity/entityinteract.c +++ b/src/dusk/rpg/entity/interact/entityinteract.c @@ -5,7 +5,7 @@ * https://opensource.org/licenses/MIT */ -#include "entity.h" +#include "rpg/entity/entity.h" #include "assert/assert.h" #include "rpg/cutscene/cutscenesystem.h" #include "ui/rpg/uitextboxmain.h" diff --git a/src/dusk/rpg/entity/entityinteract.h b/src/dusk/rpg/entity/interact/entityinteract.h similarity index 100% rename from src/dusk/rpg/entity/entityinteract.h rename to src/dusk/rpg/entity/interact/entityinteract.h diff --git a/src/dusk/rpg/overworld/CMakeLists.txt b/src/dusk/rpg/overworld/CMakeLists.txt index b697bf8a..d5d69e56 100644 --- a/src/dusk/rpg/overworld/CMakeLists.txt +++ b/src/dusk/rpg/overworld/CMakeLists.txt @@ -10,4 +10,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} map.c worldpos.c tile.c -) \ No newline at end of file +) + diff --git a/src/dusk/rpg/overworld/chunk.h b/src/dusk/rpg/overworld/chunk.h index baf82341..c19dbebd 100644 --- a/src/dusk/rpg/overworld/chunk.h +++ b/src/dusk/rpg/overworld/chunk.h @@ -22,7 +22,6 @@ typedef struct chunk_s { meshvertex_t vertices[CHUNK_VERTEX_COUNT]; uint32_t vertCount; mesh_t mesh; - color_t testColor; // uint8_t meshCount; // meshvertex_t vertices[CHUNK_VERTEX_COUNT_MAX]; diff --git a/src/dusk/rpg/overworld/map.c b/src/dusk/rpg/overworld/map.c index 78d78ca0..806342cd 100644 --- a/src/dusk/rpg/overworld/map.c +++ b/src/dusk/rpg/overworld/map.c @@ -202,84 +202,65 @@ errorret_t mapDispose() { } void mapChunkUnload(chunk_t* chunk) { + uint8_t chunkIndex = (uint8_t)(chunk - MAP.chunks); for(uint8_t i = 0; i < CHUNK_ENTITY_COUNT_MAX; i++) { - if(chunk->entities[i] == 0xFF) break; + if(chunk->entities[i] == 0xFF) continue; entity_t *entity = &ENTITIES[chunk->entities[i]]; - entity->type = ENTITY_TYPE_NULL; + assertTrue( + entity->chunkIndex == chunkIndex, + "Entity chunk index does not match chunk" + ); + if(entity->type == ENTITY_TYPE_PLAYER) { + entitySetChunk(entity, 0xFF); + } else { + entity->type = ENTITY_TYPE_NULL; + } } chunk->vertCount = 0; } errorret_t mapChunkLoad(chunk_t* chunk) { if(!mapIsLoaded()) errorThrow("No map loaded"); - - color_t color = COLOR_WHITE; - if(chunk->position.y % 2 == 0) { - if(chunk->position.x % 2 == 0) { - color = COLOR_BLACK; - } else { - color = COLOR_WHITE; - } - } else { - if(chunk->position.x % 2 == 0) { - color = COLOR_WHITE; - } else { - color = COLOR_BLACK; - } - } - // if(chunk->position.x == 0 && chunk->position.y == 0 && chunk->position.z == 0) { - // color = COLOR_RED; - // } - chunk->testColor = color; - - memorySet(chunk->tiles, TILE_SHAPE_GROUND, sizeof(chunk->tiles)); + memorySet(chunk->entities, 0xFF, sizeof(chunk->entities)); chunk->vertCount = 0; - if(chunk->position.z != 0) { + char_t name[64]; + stringFormat( + name, sizeof(name), + "chunks/%d_%d_%d.dcf", + (int32_t)chunk->position.x, + (int32_t)chunk->position.y, + (int32_t)chunk->position.z + ); + + if(!assetFileExists(name)) { + memorySet(chunk->tiles, TILE_SHAPE_GROUND, sizeof(chunk->tiles)); errorOk(); } - // Set Chunk sprites. - vec3 spriteMin = { - chunk->position.x * CHUNK_WIDTH, - chunk->position.y * CHUNK_HEIGHT, - chunk->position.z * CHUNK_DEPTH - }; - - spritebatchsprite_t sprites[CHUNK_TILE_COUNT]; - uint32_t i = 0; - for(uint8_t x = 0; x < CHUNK_WIDTH; x++) { - for(uint8_t y = 0; y < CHUNK_HEIGHT; y++) { - glm_vec3_copy(spriteMin, sprites[i].min); - glm_vec3_add( - sprites[i].min, - (vec3){ x, y, 0 }, - sprites[i].min - ); + assetentry_t *entry = assetLock(name, ASSET_LOADER_TYPE_CHUNK, NULL); + assertNotNull(entry, "Failed to get chunk asset entry"); - glm_vec3_copy(sprites[i].min, sprites[i].max); - glm_vec3_add( - sprites[i].max, - (vec3){ 1, 1, 0 }, - sprites[i].max - ); - - glm_vec2_copy((vec2){ 0, 0 }, sprites[i].uvMin); - glm_vec2_copy((vec2){ 1, 1 }, sprites[i].uvMax); - - i++; - } + errorret_t ret = assetRequireLoaded(entry); + if(errorIsNotOk(ret)) { + assetUnlockEntry(entry); + return ret; } - chunk->vertCount = i * QUAD_VERTEX_COUNT; - spriteBatchBufferToMesh( - sprites, - i, - chunk->vertices, - chunk->vertCount - ); - errorChain(meshFlush(&chunk->mesh, 0, chunk->vertCount)); + memoryCopy( + chunk->tiles, entry->data.chunk.tiles, sizeof(chunk->tiles) + ); + chunk->vertCount = entry->data.chunk.vertCount; + memoryCopy( + chunk->vertices, + entry->data.chunk.vertices, + chunk->vertCount * sizeof(meshvertex_t) + ); + assetUnlockEntry(entry); + + if(chunk->vertCount == 0) errorOk(); + errorChain(meshFlush(&chunk->mesh, 0, chunk->vertCount)); errorOk(); } diff --git a/src/dusk/rpg/overworld/worldpos.h b/src/dusk/rpg/overworld/worldpos.h index 41c803a1..30430a80 100644 --- a/src/dusk/rpg/overworld/worldpos.h +++ b/src/dusk/rpg/overworld/worldpos.h @@ -11,14 +11,14 @@ #define TILE_SIZE_PIXELS 24 #define CHUNK_WIDTH 16 -#define CHUNK_HEIGHT 14 -#define CHUNK_DEPTH 8 +#define CHUNK_HEIGHT 16 +#define CHUNK_DEPTH 32 #define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) #define MAP_CHUNK_WIDTH 5 #define MAP_CHUNK_HEIGHT 3 -#define MAP_CHUNK_DEPTH 2 +#define MAP_CHUNK_DEPTH 1 #define MAP_CHUNK_COUNT (MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT * MAP_CHUNK_DEPTH) #define ENTITY_COUNT 32 diff --git a/src/dusk/rpg/rpg.c b/src/dusk/rpg/rpg.c index 128902fc..fb4d9a42 100644 --- a/src/dusk/rpg/rpg.c +++ b/src/dusk/rpg/rpg.c @@ -37,6 +37,12 @@ errorret_t rpgInit(void) { entityInit(ent, ENTITY_TYPE_PLAYER); RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY; RPG_CAMERA.followEntity.followEntityId = ent->id; + { + chunkpos_t cp; + worldPosToChunkPos(&ent->position, &cp); + chunkindex_t ci = mapGetChunkIndexAt(cp); + if(ci != -1) entitySetChunk(ent, (uint8_t)ci); + } uint8_t npcIndex = entityGetAvailable(); entity_t *npc = &ENTITIES[npcIndex]; @@ -45,6 +51,12 @@ errorret_t rpgInit(void) { npc->position = (worldpos_t){ 3, 3, 0 }; npc->interact.type = ENTITY_INTERACT_PRINT; npc->interact.data.message = "hello world"; + { + chunkpos_t cp; + worldPosToChunkPos(&npc->position, &cp); + chunkindex_t ci = mapGetChunkIndexAt(cp); + if(ci != -1) entitySetChunk(npc, (uint8_t)ci); + } npcpath_t *path = &npc->data.npc.moveData.path; path->positions[0] = (worldpos_t){ 3, 3, 0 }; diff --git a/src/dusk/scene/overworld/sceneoverworld.c b/src/dusk/scene/overworld/sceneoverworld.c index 064a4748..3c5156f1 100644 --- a/src/dusk/scene/overworld/sceneoverworld.c +++ b/src/dusk/scene/overworld/sceneoverworld.c @@ -13,15 +13,32 @@ #include "display/screen/screen.h" #include "display/shader/shaderunlit.h" #include "display/spritebatch/spritebatch.h" +#include "display/texture/texture.h" #include "rpg/overworld/map.h" #include "rpg/entity/entity.h" #include "rpg/rpgcamera.h" +#define TEXTURE_CHUNK_SIZE 16 + +static texture_t TEXTURE_CHUNK; +static color_t TEXTURE_CHUNK_PIXELS[TEXTURE_CHUNK_SIZE * TEXTURE_CHUNK_SIZE]; + errorret_t sceneOverworldInit(scenedata_t *sceneData) { assertNotNull(sceneData, "Scene data cannot be null"); - + for(uint32_t i = 0; i < TEXTURE_CHUNK_SIZE * TEXTURE_CHUNK_SIZE; i++) { + uint8_t r = (uint8_t)((i & 7) * 36); + uint8_t g = (uint8_t)(((i >> 3) & 7) * 36); + uint8_t b = (uint8_t)((i >> 6) * 85); + TEXTURE_CHUNK_PIXELS[i] = color4b(r, g, b, 255); + } + errorChain(textureInit( + &TEXTURE_CHUNK, + TEXTURE_CHUNK_SIZE, TEXTURE_CHUNK_SIZE, + TEXTURE_FORMAT_RGBA, + (texturedata_t){ .rgbaColors = TEXTURE_CHUNK_PIXELS } + )); errorOk(); } @@ -84,7 +101,7 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) { shadermaterial_t chunkMaterial = { .unlit = { .color = COLOR_WHITE, - .texture = NULL + .texture = &TEXTURE_CHUNK } }; @@ -98,7 +115,6 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) { continue; } - chunkMaterial.unlit.color = chunk->testColor; errorChain(shaderSetMaterial(&SHADER_UNLIT, &chunkMaterial)); errorChain(meshDraw(&chunk->mesh, 0, chunk->vertCount)); i++; @@ -143,7 +159,7 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) { errorret_t sceneOverworldDispose(scenedata_t *sceneData) { assertNotNull(sceneData, "Scene data cannot be null"); - + errorChain(textureDispose(&TEXTURE_CHUNK)); errorOk(); } \ No newline at end of file