Bunch of stuff done

This commit is contained in:
2026-06-26 19:42:34 -05:00
parent 88aed11d98
commit 8181a28557
32 changed files with 567 additions and 148 deletions
Binary file not shown.
+2 -1
View File
@@ -14,4 +14,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
# Subdirs # Subdirs
add_subdirectory(display) add_subdirectory(display)
add_subdirectory(locale) add_subdirectory(locale)
add_subdirectory(json) add_subdirectory(json)
add_subdirectory(chunk)
+6
View File
@@ -39,4 +39,10 @@ assetloadercallbacks_t ASSET_LOADER_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
.loadAsync = assetJsonLoaderAsync, .loadAsync = assetJsonLoaderAsync,
.dispose = assetJsonDispose .dispose = assetJsonDispose
}, },
[ASSET_LOADER_TYPE_CHUNK] = {
.loadSync = assetChunkLoaderSync,
.loadAsync = assetChunkLoaderAsync,
.dispose = assetChunkDispose
},
}; };
+5
View File
@@ -11,6 +11,7 @@
#include "asset/loader/display/assettilesetloader.h" #include "asset/loader/display/assettilesetloader.h"
#include "asset/loader/locale/assetlocaleloader.h" #include "asset/loader/locale/assetlocaleloader.h"
#include "asset/loader/json/assetjsonloader.h" #include "asset/loader/json/assetjsonloader.h"
#include "asset/loader/chunk/assetchunkloader.h"
typedef enum { typedef enum {
ASSET_LOADER_TYPE_NULL, ASSET_LOADER_TYPE_NULL,
@@ -20,6 +21,7 @@ typedef enum {
ASSET_LOADER_TYPE_TILESET, ASSET_LOADER_TYPE_TILESET,
ASSET_LOADER_TYPE_LOCALE, ASSET_LOADER_TYPE_LOCALE,
ASSET_LOADER_TYPE_JSON, ASSET_LOADER_TYPE_JSON,
ASSET_LOADER_TYPE_CHUNK,
ASSET_LOADER_TYPE_COUNT ASSET_LOADER_TYPE_COUNT
} assetloadertype_t; } assetloadertype_t;
@@ -30,6 +32,7 @@ typedef union {
assettilesetloaderinput_t tileset; assettilesetloaderinput_t tileset;
assetlocaleloaderinput_t locale; assetlocaleloaderinput_t locale;
assetjsonloaderinput_t json; assetjsonloaderinput_t json;
assetchunkloaderinput_t chunk;
} assetloaderinput_t; } assetloaderinput_t;
typedef union { typedef union {
@@ -38,6 +41,7 @@ typedef union {
assettilesetloaderloading_t tileset; assettilesetloaderloading_t tileset;
assetlocaleloaderloading_t locale; assetlocaleloaderloading_t locale;
assetjsonloaderloading_t json; assetjsonloaderloading_t json;
assetchunkloaderloading_t chunk;
} assetloaderloading_t; } assetloaderloading_t;
typedef union { typedef union {
@@ -46,6 +50,7 @@ typedef union {
assettilesetoutput_t tileset; assettilesetoutput_t tileset;
assetlocaleoutput_t locale; assetlocaleoutput_t locale;
assetjsonoutput_t json; assetjsonoutput_t json;
assetchunkoutput_t chunk;
} assetloaderoutput_t; } assetloaderoutput_t;
typedef struct assetloading_s assetloading_t; typedef struct assetloading_s assetloading_t;
@@ -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
)
@@ -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();
}
@@ -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);
+2 -2
View File
@@ -7,10 +7,10 @@
target_sources(${DUSK_LIBRARY_TARGET_NAME} target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC PUBLIC
entity.c entity.c
entityanim.c
entitydir.c entitydir.c
entityinteract.c
player.c player.c
) )
add_subdirectory(anim)
add_subdirectory(interact)
add_subdirectory(npc) add_subdirectory(npc)
+13
View File
@@ -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
)
+27
View File
@@ -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);
}
+37
View File
@@ -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);
+14
View File
@@ -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;
}
+18
View File
@@ -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);
+21
View File
@@ -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
);
}
+21
View File
@@ -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);
+14
View File
@@ -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;
}
+21
View File
@@ -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);
+21
View File
@@ -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
);
}
+21
View File
@@ -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);
+30
View File
@@ -12,6 +12,7 @@
#include "util/math.h" #include "util/math.h"
#include "rpg/cutscene/cutscenemode.h" #include "rpg/cutscene/cutscenemode.h"
#include "rpg/overworld/map.h" #include "rpg/overworld/map.h"
#include "rpg/overworld/chunk.h"
#include "rpg/overworld/tile.h" #include "rpg/overworld/tile.h"
entity_t ENTITIES[ENTITY_COUNT]; entity_t ENTITIES[ENTITY_COUNT];
@@ -28,6 +29,7 @@ void entityInit(entity_t *entity, const entitytype_t type) {
memoryZero(entity, sizeof(entity_t)); memoryZero(entity, sizeof(entity_t));
entity->id = (uint8_t)(entity - ENTITIES); entity->id = (uint8_t)(entity - ENTITIES);
entity->type = type; entity->type = type;
entity->chunkIndex = 0xFF;
if(ENTITY_CALLBACKS[type].init != NULL) ENTITY_CALLBACKS[type].init(entity); if(ENTITY_CALLBACKS[type].init != NULL) ENTITY_CALLBACKS[type].init(entity);
} }
@@ -216,4 +218,32 @@ uint8_t entityGetAvailable() {
} while(++ent, ent < &ENTITIES[ENTITY_COUNT]); } while(++ent, ent < &ENTITIES[ENTITY_COUNT]);
return 0xFF; 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;
}
}
}
} }
+15 -4
View File
@@ -7,8 +7,8 @@
#pragma once #pragma once
#include "entitydir.h" #include "entitydir.h"
#include "entityanim.h" #include "anim/entityanim.h"
#include "entityinteract.h" #include "interact/entityinteract.h"
#include "entitytype.h" #include "entitytype.h"
#include "npc/npc.h" #include "npc/npc.h"
@@ -29,6 +29,8 @@ typedef struct entity_s {
float_t animTime; float_t animTime;
entityinteract_t interact; entityinteract_t interact;
uint8_t chunkIndex;
} entity_t; } entity_t;
extern entity_t ENTITIES[ENTITY_COUNT]; extern entity_t ENTITIES[ENTITY_COUNT];
@@ -107,7 +109,16 @@ entity_t *entityGetAt(const worldpos_t pos);
/** /**
* Gets an available entity index. * Gets an available entity index.
* *
* @return The index of an available entity, or 0xFF if none are available. * @return The index of an available entity, or 0xFF if none are available.
*/ */
uint8_t entityGetAvailable(); 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);
-41
View File
@@ -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;
}
}
-29
View File
@@ -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);
@@ -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
)
@@ -5,7 +5,7 @@
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
#include "entity.h" #include "rpg/entity/entity.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "rpg/cutscene/cutscenesystem.h" #include "rpg/cutscene/cutscenesystem.h"
#include "ui/rpg/uitextboxmain.h" #include "ui/rpg/uitextboxmain.h"
+2 -1
View File
@@ -10,4 +10,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
map.c map.c
worldpos.c worldpos.c
tile.c tile.c
) )
-1
View File
@@ -22,7 +22,6 @@ typedef struct chunk_s {
meshvertex_t vertices[CHUNK_VERTEX_COUNT]; meshvertex_t vertices[CHUNK_VERTEX_COUNT];
uint32_t vertCount; uint32_t vertCount;
mesh_t mesh; mesh_t mesh;
color_t testColor;
// uint8_t meshCount; // uint8_t meshCount;
// meshvertex_t vertices[CHUNK_VERTEX_COUNT_MAX]; // meshvertex_t vertices[CHUNK_VERTEX_COUNT_MAX];
+42 -61
View File
@@ -202,84 +202,65 @@ errorret_t mapDispose() {
} }
void mapChunkUnload(chunk_t* chunk) { void mapChunkUnload(chunk_t* chunk) {
uint8_t chunkIndex = (uint8_t)(chunk - MAP.chunks);
for(uint8_t i = 0; i < CHUNK_ENTITY_COUNT_MAX; i++) { 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_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; chunk->vertCount = 0;
} }
errorret_t mapChunkLoad(chunk_t* chunk) { errorret_t mapChunkLoad(chunk_t* chunk) {
if(!mapIsLoaded()) errorThrow("No map loaded"); 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)); memorySet(chunk->entities, 0xFF, sizeof(chunk->entities));
chunk->vertCount = 0; 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(); errorOk();
} }
// Set Chunk sprites. assetentry_t *entry = assetLock(name, ASSET_LOADER_TYPE_CHUNK, NULL);
vec3 spriteMin = { assertNotNull(entry, "Failed to get chunk asset entry");
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
);
glm_vec3_copy(sprites[i].min, sprites[i].max); errorret_t ret = assetRequireLoaded(entry);
glm_vec3_add( if(errorIsNotOk(ret)) {
sprites[i].max, assetUnlockEntry(entry);
(vec3){ 1, 1, 0 }, return ret;
sprites[i].max
);
glm_vec2_copy((vec2){ 0, 0 }, sprites[i].uvMin);
glm_vec2_copy((vec2){ 1, 1 }, sprites[i].uvMax);
i++;
}
} }
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(); errorOk();
} }
+3 -3
View File
@@ -11,14 +11,14 @@
#define TILE_SIZE_PIXELS 24 #define TILE_SIZE_PIXELS 24
#define CHUNK_WIDTH 16 #define CHUNK_WIDTH 16
#define CHUNK_HEIGHT 14 #define CHUNK_HEIGHT 16
#define CHUNK_DEPTH 8 #define CHUNK_DEPTH 32
#define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH) #define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH)
#define MAP_CHUNK_WIDTH 5 #define MAP_CHUNK_WIDTH 5
#define MAP_CHUNK_HEIGHT 3 #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 MAP_CHUNK_COUNT (MAP_CHUNK_WIDTH * MAP_CHUNK_HEIGHT * MAP_CHUNK_DEPTH)
#define ENTITY_COUNT 32 #define ENTITY_COUNT 32
+12
View File
@@ -37,6 +37,12 @@ errorret_t rpgInit(void) {
entityInit(ent, ENTITY_TYPE_PLAYER); entityInit(ent, ENTITY_TYPE_PLAYER);
RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY; RPG_CAMERA.mode = RPG_CAMERA_MODE_FOLLOW_ENTITY;
RPG_CAMERA.followEntity.followEntityId = ent->id; 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(); uint8_t npcIndex = entityGetAvailable();
entity_t *npc = &ENTITIES[npcIndex]; entity_t *npc = &ENTITIES[npcIndex];
@@ -45,6 +51,12 @@ errorret_t rpgInit(void) {
npc->position = (worldpos_t){ 3, 3, 0 }; npc->position = (worldpos_t){ 3, 3, 0 };
npc->interact.type = ENTITY_INTERACT_PRINT; npc->interact.type = ENTITY_INTERACT_PRINT;
npc->interact.data.message = "hello world"; 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; npcpath_t *path = &npc->data.npc.moveData.path;
path->positions[0] = (worldpos_t){ 3, 3, 0 }; path->positions[0] = (worldpos_t){ 3, 3, 0 };
+20 -4
View File
@@ -13,15 +13,32 @@
#include "display/screen/screen.h" #include "display/screen/screen.h"
#include "display/shader/shaderunlit.h" #include "display/shader/shaderunlit.h"
#include "display/spritebatch/spritebatch.h" #include "display/spritebatch/spritebatch.h"
#include "display/texture/texture.h"
#include "rpg/overworld/map.h" #include "rpg/overworld/map.h"
#include "rpg/entity/entity.h" #include "rpg/entity/entity.h"
#include "rpg/rpgcamera.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) { errorret_t sceneOverworldInit(scenedata_t *sceneData) {
assertNotNull(sceneData, "Scene data cannot be null"); 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(); errorOk();
} }
@@ -84,7 +101,7 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) {
shadermaterial_t chunkMaterial = { shadermaterial_t chunkMaterial = {
.unlit = { .unlit = {
.color = COLOR_WHITE, .color = COLOR_WHITE,
.texture = NULL .texture = &TEXTURE_CHUNK
} }
}; };
@@ -98,7 +115,6 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) {
continue; continue;
} }
chunkMaterial.unlit.color = chunk->testColor;
errorChain(shaderSetMaterial(&SHADER_UNLIT, &chunkMaterial)); errorChain(shaderSetMaterial(&SHADER_UNLIT, &chunkMaterial));
errorChain(meshDraw(&chunk->mesh, 0, chunk->vertCount)); errorChain(meshDraw(&chunk->mesh, 0, chunk->vertCount));
i++; i++;
@@ -143,7 +159,7 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) {
errorret_t sceneOverworldDispose(scenedata_t *sceneData) { errorret_t sceneOverworldDispose(scenedata_t *sceneData) {
assertNotNull(sceneData, "Scene data cannot be null"); assertNotNull(sceneData, "Scene data cannot be null");
errorChain(textureDispose(&TEXTURE_CHUNK));
errorOk(); errorOk();
} }