Compare commits

...

3 Commits

Author SHA1 Message Date
87d3c9087e Merge branch 'debug'
Fixed some warnings
2025-10-06 19:52:28 +01:00
0c33944721 Merge branch 'debug/world_change' of yibble.dev:bulmanator/ld58 into debug 2025-10-06 19:38:14 +01:00
c1fb705f68 Fixed level saving and loading 2025-10-06 19:36:41 +01:00
3 changed files with 132 additions and 81 deletions

View File

@@ -398,6 +398,7 @@ int main(int argc, char **argv)
G_Editor editor = game->editor; G_Editor editor = game->editor;
F32 tilex = cast(F32) floor(editor.cursor.x+TILE_SIZE/2); F32 tilex = cast(F32) floor(editor.cursor.x+TILE_SIZE/2);
F32 tiley = cast(F32) floor(editor.cursor.y+TILE_SIZE/2); F32 tiley = cast(F32) floor(editor.cursor.y+TILE_SIZE/2);
switch(game->editor.mode) { switch(game->editor.mode) {
case G_EDITOR_MODE_TILE: { case G_EDITOR_MODE_TILE: {
World_Tile asset = game->world->tileTypes[editor.currentAsset]; World_Tile asset = game->world->tileTypes[editor.currentAsset];
@@ -419,7 +420,7 @@ int main(int argc, char **argv)
.texture=0, .texture=0,
.dim=game->world->hitboxes[i].size, .dim=game->world->hitboxes[i].size,
.flags=D_RECT_IGNORE_ASPECT, .flags=D_RECT_IGNORE_ASPECT,
.c=V4F(100,0,0,0.7), .c=V4F(100,0,0,0.7f),
); );
} }
break; break;

View File

@@ -35,7 +35,7 @@ void ProcessEvents(SDL_Event *event, World *world)
{ {
PlayerInput(event, &world->player); PlayerInput(event, &world->player);
if(event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_F5){ if(event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_F5){
SaveWorld(world->arena, world); SaveWorld(world);
} }
if(event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_F6){ if(event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_F6){
LoadWorld(world->arena, world); LoadWorld(world->arena, world);
@@ -64,7 +64,7 @@ void RenderWorld(World *world, D_Context *draw) {
); );
} }
} }
for (int i = 0; i < world->navMesh->nodeCount; i++) { for (U32 i = 0; i < world->navMesh->nodeCount; i++) {
NavNode n = world->navMesh->nodes[i]; NavNode n = world->navMesh->nodes[i];
D_Rect( D_Rect(
draw, draw,
@@ -89,94 +89,144 @@ void RenderWorld(World *world, D_Context *draw) {
PlayerDraw(draw, &world->player); PlayerDraw(draw, &world->player);
} }
void SaveWorld(M_Arena *arena, World *world) { #define WRITE(v) FS_FileWrite(file, &(v), sizeof(v), offset); offset += sizeof(v)
(void) arena; #define WRITEN(v, n) FS_FileWrite(file, v, (n) * sizeof(*(v)), offset); offset += ((n) * sizeof(*(v)))
void SaveWorld(World *world) {
printf("--- Saving World ---\n");
printf(" - %d props\n", world->propCount);
printf(" - %d hitboxes\n", world->hitboxCount);
printf("Saving world\n");
OS_Handle file = FS_FileOpen(S("world.sgdat"), FS_ACCESS_WRITE); OS_Handle file = FS_FileOpen(S("world.sgdat"), FS_ACCESS_WRITE);
U32 offset = 0; U64 offset = 0;
for(int i = 0; i < WORLD_TILE_TYPE_MAX; i++) {
FS_FileWrite(file, &world->tileTypes[i].tag.count, sizeof(S64), offset); for (U32 i = 0; i < WORLD_TILE_TYPE_MAX; i++) {
offset += sizeof(S64); World_Tile *tile = &world->tileTypes[i];
FS_FileWrite(file, world->tileTypes[i].tag.data, world->tileTypes[i].tag.count, offset);
offset += sizeof(U8) * world->tileTypes[i].tag.count; WRITE(tile->tag.count);
FS_FileWrite(file, &world->tileTypes[i].rotation, sizeof(F32), offset); WRITEN(tile->tag.data, tile->tag.count);
offset += sizeof(F32); WRITE(tile->rotation);
}
for(int i = 0; i < WORLD_PROP_TYPE_MAX; i++) {
FS_FileWrite(file, &world->propTypes[i].tag.count, sizeof(S64), offset);
offset += sizeof(S64);
FS_FileWrite(file, world->propTypes[i].tag.data, world->propTypes[i].tag.count, offset);
offset += sizeof(U8) * world->propTypes[i].tag.count;
FS_FileWrite(file, &world->propTypes[i].scale, sizeof(F32), offset);
offset += sizeof(F32);
} }
FS_FileWrite(file, &world->propCount, sizeof(U32), offset); for (U32 i = 0; i < WORLD_PROP_TYPE_MAX; i++) {
offset += sizeof(U32); World_PropType *type = &world->propTypes[i];
FS_FileWrite(file, world->props, sizeof(World_Prop)*WORLD_PROP_MAX, offset); WRITE(type->tag.count);
offset += sizeof(World_Prop)*WORLD_PROP_MAX; WRITEN(type->tag.data, type->tag.count);
WRITE(type->scale);
}
FS_FileWrite(file, &world->hitboxCount, sizeof(U32), offset); WRITE(world->propCount);
offset += sizeof(U32); WRITEN(world->props, WORLD_PROP_MAX);
FS_FileWrite(file, world->hitboxes, sizeof(AABB)*WORLD_HITBOX_MAX, offset); WRITE(world->hitboxCount);
offset += sizeof(AABB)*WORLD_HITBOX_MAX; WRITEN(world->hitboxes, WORLD_HITBOX_MAX);
FS_FileWrite(file, world->map, sizeof(U32)*WORLD_MAP_MAX, offset); WRITEN(world->map, WORLD_MAP_MAX);
offset += sizeof(U32)*WORLD_MAP_MAX;
FS_FileClose(file); FS_FileClose(file);
printf("Saved world :)\n");
printf("--- World Saved ---\n");
} }
void LoadWorld(M_Arena *arena, World *world) { void LoadWorld(M_Arena *arena, World *world) {
printf("loading world\n"); printf("--- Loading World ---\n");
OS_Handle file = FS_FileOpen(S("world.sgdat"), FS_ACCESS_READ);
U32 offset = 0;
M_TempScope(0, 0) {
Str8 data = FS_ReadEntireFile(temp.arena, S("world.sgdat"));
U8 *base = data.data;
// Load tile types
//
world->tileTypes = M_ArenaPush(arena, World_Tile, .count = WORLD_TILE_TYPE_MAX); world->tileTypes = M_ArenaPush(arena, World_Tile, .count = WORLD_TILE_TYPE_MAX);
for(int i = 0; i < WORLD_TILE_TYPE_MAX; i++) { for (U32 it = 0; it < WORLD_TILE_TYPE_MAX; ++it) {
FS_FileRead(file, &world->tileTypes[i].tag.count, sizeof(S64), offset); World_Tile *type = &world->tileTypes[it];
offset += sizeof(S64);
world->tileTypes[i].tag.data = M_ArenaPush(arena, U8, .count=world->tileTypes[i].tag.count); Str8 name;
FS_FileRead(file, world->tileTypes[i].tag.data, world->tileTypes[i].tag.count, offset); name.count = *(S64 *) base;
offset += sizeof(U8) * world->tileTypes[i].tag.count; name.data = base + 8;
FS_FileRead(file, &world->tileTypes[i].rotation, sizeof(F32), offset);
offset += sizeof(F32); base += 8;
base += name.count;
if (name.count != 0) {
// Means we likely got a vaild tag
type->tag = Str8_Copy(arena, name);
type->rotation = *(F32 *) base;
} }
base += 4;
}
// Load prop types
//
world->propTypes = M_ArenaPush(arena, World_PropType, .count = WORLD_PROP_TYPE_MAX); world->propTypes = M_ArenaPush(arena, World_PropType, .count = WORLD_PROP_TYPE_MAX);
for(int i = 0; i < WORLD_PROP_TYPE_MAX; i++) { for (U32 it = 0; it < WORLD_PROP_TYPE_MAX; ++it) {
FS_FileRead(file, &world->propTypes[i].tag.count, sizeof(S64), offset); World_PropType *type = &world->propTypes[it];
offset += sizeof(S64);
world->propTypes[i].tag.data = M_ArenaPush(arena, U8, .count=world->propTypes[i].tag.count); Str8 name;
FS_FileRead(file, world->propTypes[i].tag.data, world->propTypes[i].tag.count, offset); name.count = *(S64 *) base;
offset += sizeof(U8) * world->propTypes[i].tag.count; name.data = base + 8;
FS_FileRead(file, &world->propTypes[i].scale, sizeof(F32), offset);
offset += sizeof(F32); base += 8;
base += name.count;
if (name.count != 0) {
type->tag = Str8_Copy(arena, name);
type->scale = *(F32 *) base;
} }
FS_FileRead(file, &world->propCount, sizeof(U32), offset); base += 4;
offset += sizeof(U32); }
// Prop locations
{
U32 n_props = *(U32 *) base; base += 4;
World_Prop *props = (World_Prop *) base;
world->propCount = n_props;
world->props = M_ArenaPush(arena, World_Prop, .count = WORLD_PROP_MAX); world->props = M_ArenaPush(arena, World_Prop, .count = WORLD_PROP_MAX);
FS_FileRead(file, world->props, sizeof(World_Prop)*WORLD_PROP_MAX, offset);
offset += sizeof(World_Prop)*WORLD_PROP_MAX;
FS_FileRead(file, &world->hitboxCount, sizeof(U32), offset); M_CopySize(world->props, props, n_props * sizeof(World_Prop));
offset += sizeof(U32);
base += (WORLD_PROP_MAX * sizeof(World_Prop));
}
// Hitboxes
//
{
U32 n_hitbox = *(U32 *) base; base += 4;
AABB *boxes = (AABB *) base;
world->hitboxCount = n_hitbox;
world->hitboxes = M_ArenaPush(arena, AABB, .count = WORLD_HITBOX_MAX); world->hitboxes = M_ArenaPush(arena, AABB, .count = WORLD_HITBOX_MAX);
FS_FileRead(file, world->hitboxes, sizeof(AABB)*WORLD_HITBOX_MAX, offset);
offset += sizeof(AABB)*WORLD_HITBOX_MAX; M_CopySize(world->hitboxes, boxes, n_hitbox * sizeof(AABB));
base += (WORLD_HITBOX_MAX * sizeof(AABB));
}
// Map
//
{
U32 *__map = (U32 *) base;
world->map = M_ArenaPush(arena, U32, .count = WORLD_MAP_MAX); world->map = M_ArenaPush(arena, U32, .count = WORLD_MAP_MAX);
FS_FileRead(file, world->map, sizeof(U32)*WORLD_MAP_MAX, offset); M_CopySize(world->map, __map, WORLD_MAP_MAX * sizeof(U32));
offset += sizeof(U32)*WORLD_MAP_MAX;
FS_FileClose(file); base += (WORLD_MAP_MAX * sizeof(U32));
printf("loaded world\n"); }
if (base != (data.data + data.count)) {
printf("--- OFFSET MISMATCH ---\n");
}
printf(" - %d props\n", world->propCount);
printf(" - %d hitboxes\n", world->hitboxCount);
printf("--- Loaded World ---\n");
}
} }
void GenerateNavMesh(M_Arena *arena, World *world) { void GenerateNavMesh(M_Arena *arena, World *world) {
@@ -186,15 +236,15 @@ void GenerateNavMesh(M_Arena *arena, World *world) {
U32 x = (i % 96); U32 x = (i % 96);
U32 y = (i / 96); U32 y = (i / 96);
bool skip = false; bool skip = false;
for(int hi = 0; hi < world->hitboxCount; hi++) { for(U32 hi = 0; hi < world->hitboxCount; hi++) {
if(AABB_Point(world->hitboxes[hi], V2F(x, y))) { if(AABB_Point(world->hitboxes[hi], V2F((F32) x, (F32) y))) {
skip = true; skip = true;
break; break;
} }
} }
if(skip) {continue;} if(skip) {continue;}
world->navMesh->nodes[world->navMesh->nodeCount].pos.x = x; world->navMesh->nodes[world->navMesh->nodeCount].pos.x = cast(F32) x;
world->navMesh->nodes[world->navMesh->nodeCount].pos.y = y; world->navMesh->nodes[world->navMesh->nodeCount].pos.y = cast(F32) y;
U32 cost = 20; U32 cost = 20;
if(Str8_Equal(world->tileTypes[world->map[i]].tag, S("path_middle"), STR8_EQUAL_IGNORE_CASE)) { if(Str8_Equal(world->tileTypes[world->map[i]].tag, S("path_middle"), STR8_EQUAL_IGNORE_CASE)) {
cost = 10; cost = 10;
@@ -210,8 +260,8 @@ void GenerateNavMesh(M_Arena *arena, World *world) {
continue; continue;
} }
// It's quad for loop time :D // It's quad for loop time :D
for(int hi = 0; hi < world->hitboxCount; hi++) { for(U32 hi = 0; hi < world->hitboxCount; hi++) {
if(AABB_Point(world->hitboxes[hi], V2F(x+nx, y+ny))) { if(AABB_Point(world->hitboxes[hi], V2F((F32) (x + nx), (F32) (y + ny)))) {
skip = true; skip = true;
break; break;
} }
@@ -220,7 +270,7 @@ void GenerateNavMesh(M_Arena *arena, World *world) {
U32 index = x+nx + (y+ny)*96; U32 index = x+nx + (y+ny)*96;
U32 nCount = world->navMesh->nodeCount; U32 nCount = world->navMesh->nodeCount;
world->navMesh->nodes[nCount].connections[world->navMesh->nodes[nCount].connectionCount].NodeIndex = index; world->navMesh->nodes[nCount].connections[world->navMesh->nodes[nCount].connectionCount].NodeIndex = index;
world->navMesh->nodes[nCount].connections[world->navMesh->nodes[nCount].connectionCount].Cost = cost; world->navMesh->nodes[nCount].connections[world->navMesh->nodes[nCount].connectionCount].Cost = cast(F32) cost;
world->navMesh->nodes[nCount].connectionCount++; world->navMesh->nodes[nCount].connectionCount++;
} }
} }

View File

@@ -82,7 +82,7 @@ function void UpdateNPC(F32 delta, NPC *npc, World *world);
function void UpdateBandit(F32 delta, Bandit *bandit, World *world); function void UpdateBandit(F32 delta, Bandit *bandit, World *world);
function void LoadWorld(M_Arena *arena, World *world); function void LoadWorld(M_Arena *arena, World *world);
function void SaveWorld(M_Arena *arena, World *world); function void SaveWorld(World *world);
function void GenerateNavMesh(M_Arena *arena, World *world); function void GenerateNavMesh(M_Arena *arena, World *world);
#endif // LD_GAME_WORLD_H_ #endif // LD_GAME_WORLD_H_