From c1fb705f68b36415ee10ba60aa72ffc969d14475 Mon Sep 17 00:00:00 2001 From: James Bulman Date: Mon, 6 Oct 2025 19:36:41 +0100 Subject: [PATCH] Fixed level saving and loading --- code/first.c | 16 ++-- code/game/impl/world.c | 193 ++++++++++++++++++++++++++--------------- code/game/world.h | 6 +- 3 files changed, 132 insertions(+), 83 deletions(-) diff --git a/code/first.c b/code/first.c index 990619a..3fbd630 100644 --- a/code/first.c +++ b/code/first.c @@ -260,8 +260,8 @@ int main(int argc, char **argv) if(e.type==SDL_EVENT_MOUSE_BUTTON_DOWN && e.button.button == SDL_BUTTON_LEFT) { switch(game->editor.mode){ case G_EDITOR_MODE_TILE: { - F32 tilex = (S32)(game->editor.cursor.x+TILE_SIZE/2); - F32 tiley = (S32)(game->editor.cursor.y+TILE_SIZE/2); + F32 tilex = (F32) (S32)(game->editor.cursor.x+TILE_SIZE/2); + F32 tiley = (F32) (S32)(game->editor.cursor.y+TILE_SIZE/2); game->world->map[(S32)tilex + (S32)tiley * 96] = game->editor.currentAsset; break; } @@ -278,7 +278,7 @@ int main(int argc, char **argv) } } } else if(e.type==SDL_EVENT_MOUSE_BUTTON_UP && e.button.button == SDL_BUTTON_LEFT && game->editor.mode == G_EDITOR_MODE_HITBOX) { - // Add hitbox + // Add hitbox V2f topLeft = V2F(Min(game->editor.cursor.x, game->editor.dragStart.x), Min(game->editor.cursor.y, game->editor.dragStart.y)); game->world->hitboxes[game->world->hitboxCount].pos = topLeft; game->world->hitboxes[game->world->hitboxCount].size = V2F( @@ -349,7 +349,7 @@ int main(int argc, char **argv) UpdateWorld(1.0f / 60.0f, game->world); game->camera.p.x = game->world->player.pos.x; game->camera.p.y = game->world->player.pos.y; - } + } D_AnimationUpdate(&animation, 1.0f / 250.0f); int w, h; @@ -395,8 +395,8 @@ int main(int argc, char **argv) if(game->editor.enabled) { G_Editor editor = game->editor; - F32 tilex = floor(editor.cursor.x+TILE_SIZE/2); - F32 tiley = floor(editor.cursor.y+TILE_SIZE/2); + F32 tilex = (F32) floor(editor.cursor.x+TILE_SIZE/2); + F32 tiley = (F32) floor(editor.cursor.y+TILE_SIZE/2); switch(game->editor.mode) { case G_EDITOR_MODE_TILE: { World_Tile asset = game->world->tileTypes[editor.currentAsset]; @@ -409,7 +409,7 @@ int main(int argc, char **argv) break; } case G_EDITOR_MODE_HITBOX: { - for(int i = 0; i < game->world->hitboxCount; i++) { + for(U32 i = 0; i < game->world->hitboxCount; i++) { V2f centre = AABB_Centre(game->world->hitboxes[i]); D_Rect( &game->draw, @@ -418,7 +418,7 @@ int main(int argc, char **argv) .texture=0, .dim=game->world->hitboxes[i].size, .flags=D_RECT_IGNORE_ASPECT, - .c=V4F(100,0,0,0.7), + .c=V4F(100,0,0,0.7f), ); } break; diff --git a/code/game/impl/world.c b/code/game/impl/world.c index e2d6638..930ee8a 100644 --- a/code/game/impl/world.c +++ b/code/game/impl/world.c @@ -32,7 +32,7 @@ void ProcessEvents(SDL_Event *event, World *world) { PlayerInput(event, &world->player); 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){ LoadWorld(world->arena, world); @@ -50,7 +50,7 @@ void RenderWorld(World *world, D_Context *draw) { ); } } - for (int i = 0; i < world->propCount; i++) { + for (U32 i = 0; i < world->propCount; i++) { if(world->props[i].area == world->player.currentArea) { D_Rect( draw, @@ -75,93 +75,142 @@ void RenderWorld(World *world, D_Context *draw) { D_Rect(draw, world->player.pos.x, world->player.pos.y, .texture = 1); } -void SaveWorld(M_Arena *arena, World *world) { - printf("Saving world\n"); +#define WRITE(v) FS_FileWrite(file, &(v), sizeof(v), offset); offset += sizeof(v) +#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); + OS_Handle file = FS_FileOpen(S("world.sgdat"), FS_ACCESS_WRITE); - U32 offset = 0; - for(int i = 0; i < WORLD_TILE_TYPE_MAX; i++) { - FS_FileWrite(file, &world->tileTypes[i].tag.count, sizeof(S64), offset); - offset += sizeof(S64); - FS_FileWrite(file, world->tileTypes[i].tag.data, world->tileTypes[i].tag.count, offset); - offset += sizeof(U8) * world->tileTypes[i].tag.count; - FS_FileWrite(file, &world->tileTypes[i].rotation, sizeof(F32), offset); - offset += sizeof(F32); - } - 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); + U64 offset = 0; + + for (U32 i = 0; i < WORLD_TILE_TYPE_MAX; i++) { + World_Tile *tile = &world->tileTypes[i]; + + WRITE(tile->tag.count); + WRITEN(tile->tag.data, tile->tag.count); + WRITE(tile->rotation); } - FS_FileWrite(file, world->propTypes, sizeof(World_PropType)*WORLD_PROP_TYPE_MAX, offset); - offset += sizeof(World_PropType)*WORLD_PROP_TYPE_MAX; + for (U32 i = 0; i < WORLD_PROP_TYPE_MAX; i++) { + World_PropType *type = &world->propTypes[i]; - FS_FileWrite(file, &world->propCount, sizeof(U32), offset); - offset += sizeof(U32); + WRITE(type->tag.count); + WRITEN(type->tag.data, type->tag.count); + WRITE(type->scale); + } - FS_FileWrite(file, world->props, sizeof(World_Prop)*WORLD_PROP_MAX, offset); - offset += sizeof(World_Prop)*WORLD_PROP_MAX; + WRITE(world->propCount); + WRITEN(world->props, WORLD_PROP_MAX); - FS_FileWrite(file, &world->hitboxCount, sizeof(U32), offset); - offset += sizeof(U32); + WRITE(world->hitboxCount); + WRITEN(world->hitboxes, WORLD_HITBOX_MAX); - FS_FileWrite(file, world->hitboxes, sizeof(AABB)*WORLD_HITBOX_MAX, offset); - offset += sizeof(AABB)*WORLD_HITBOX_MAX; - - FS_FileWrite(file, world->map, sizeof(U32)*WORLD_MAP_MAX, offset); - offset += sizeof(U32)*WORLD_MAP_MAX; + WRITEN(world->map, WORLD_MAP_MAX); FS_FileClose(file); - printf("Saved world :)\n"); + + printf("--- World Saved ---\n"); } void LoadWorld(M_Arena *arena, World *world) { - printf("loading world\n"); - OS_Handle file = FS_FileOpen(S("world.sgdat"), FS_ACCESS_READ); - U32 offset = 0; + printf("--- Loading World ---\n"); - world->tileTypes = M_ArenaPush(arena, World_Tile, .count=WORLD_TILE_TYPE_MAX); - for(int i = 0; i < WORLD_TILE_TYPE_MAX; i++) { - FS_FileRead(file, &world->tileTypes[i].tag.count, sizeof(S64), offset); - offset += sizeof(S64); - world->tileTypes[i].tag.data = M_ArenaPush(arena, U8, .count=world->tileTypes[i].tag.count); - FS_FileRead(file, world->tileTypes[i].tag.data, world->tileTypes[i].tag.count, offset); - offset += sizeof(U8) * world->tileTypes[i].tag.count; - FS_FileRead(file, &world->tileTypes[i].rotation, sizeof(F32), offset); - offset += sizeof(F32); - } - world->propTypes = M_ArenaPush(arena, World_PropType, .count=WORLD_PROP_TYPE_MAX); - for(int i = 0; i < WORLD_PROP_TYPE_MAX; i++) { - FS_FileRead(file, &world->propTypes[i].tag.count, sizeof(S64), offset); - offset += sizeof(S64); - world->propTypes[i].tag.data = M_ArenaPush(arena, U8, .count=world->propTypes[i].tag.count); - FS_FileRead(file, world->propTypes[i].tag.data, world->propTypes[i].tag.count, offset); - offset += sizeof(U8) * world->propTypes[i].tag.count; - FS_FileRead(file, &world->propTypes[i].scale, sizeof(F32), offset); - offset += sizeof(F32); - } + M_TempScope(0, 0) { + Str8 data = FS_ReadEntireFile(temp.arena, S("world.sgdat")); - FS_FileRead(file, &world->propCount, sizeof(U32), offset); - offset += sizeof(U32); + U8 *base = data.data; - 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->propCount; + // Load tile types + // + world->tileTypes = M_ArenaPush(arena, World_Tile, .count = WORLD_TILE_TYPE_MAX); + for (U32 it = 0; it < WORLD_TILE_TYPE_MAX; ++it) { + World_Tile *type = &world->tileTypes[it]; - FS_FileRead(file, &world->hitboxCount, sizeof(U32), offset); - offset += sizeof(U32); + Str8 name; + name.count = *(S64 *) base; + name.data = base + 8; - 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->hitboxCount; + base += 8; + base += name.count; - world->map = M_ArenaPush(arena, U32, .count=WORLD_MAP_MAX); - FS_FileRead(file, world->map, sizeof(U32)*WORLD_MAP_MAX, offset); - offset += sizeof(U32)*WORLD_MAP_MAX; + if (name.count != 0) { + // Means we likely got a vaild tag + type->tag = Str8_Copy(arena, name); + type->rotation = *(F32 *) base; + } - FS_FileClose(file); - printf("loaded world\n"); + base += 4; + } + + // Load prop types + // + world->propTypes = M_ArenaPush(arena, World_PropType, .count = WORLD_PROP_TYPE_MAX); + for (U32 it = 0; it < WORLD_PROP_TYPE_MAX; ++it) { + World_PropType *type = &world->propTypes[it]; + + Str8 name; + name.count = *(S64 *) base; + name.data = base + 8; + + base += 8; + base += name.count; + + if (name.count != 0) { + type->tag = Str8_Copy(arena, name); + type->scale = *(F32 *) base; + } + + base += 4; + } + + // 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); + + M_CopySize(world->props, props, n_props * sizeof(World_Prop)); + + 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); + + 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); + M_CopySize(world->map, __map, WORLD_MAP_MAX * sizeof(U32)); + + base += (WORLD_MAP_MAX * sizeof(U32)); + } + + 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"); + } } diff --git a/code/game/world.h b/code/game/world.h index 5fda8ec..0023dad 100644 --- a/code/game/world.h +++ b/code/game/world.h @@ -52,8 +52,8 @@ struct World { //// Loaded from world file World_Tile *tileTypes; World_PropType *propTypes; - World_Prop *props; - AABB *hitboxes; + World_Prop *props; + AABB *hitboxes; U32 *map; U32 propCount; @@ -82,6 +82,6 @@ function void UpdateNPC(F32 delta, NPC *npc, World *world); function void UpdateBandit(F32 delta, Bandit *bandit, World *world); function void LoadWorld(M_Arena *arena, World *world); -function void SaveWorld(M_Arena *arena, World *world); +function void SaveWorld(World *world); #endif // LD_GAME_WORLD_H_