#include "../world.h" #include "../npc.h" #include "../player.h" #include "../aabb.h" #include #include #include #include "../map.h" void UpdateWorld(F32 delta, World *world) { if(world->bandit.mode == BANDIT_SHOOTOUT){ delta = delta/4; } UpdateBandit(delta, &world->bandit, world); UpdateNPCs(delta, world); PlayerUpdate(delta, &world->player); } void UpdateNPCs(F32 delta, World *world) { for (U32 i = 0; i < world->npcCount; i++) { NPC *npc = &world->npcs[i]; UpdateNPC(delta, npc, world); if ( world->player.controls.shot && AABB_Slab(world->player.collision.pos, world->player.shotPos, npc->collision) && npc->currentArea == world->player.currentArea) { printf("You shot %*.s\n", Sv(world->npcs[i].name)); } } } 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); } if(event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_F6){ LoadWorld(world->arena, world); } } void RenderWorld(World *world, D_Context *draw) { if(world->player.currentArea == WORLD_AREA_OUTSIDE) { for (int i = 0; i < 4800; i++) { D_Rect( draw, (F32) (i % 96), (F32) (i / 96), .texture = D_ImageHandle(draw,world->tileTypes[world->map[i]].tag), .angle = (F32) world->tileTypes[world->map[i]].rotation, ); } } for (U32 i = 0; i < world->propCount; i++) { if(world->props[i].area == world->player.currentArea) { D_Rect( draw, world->props[i].pos.x, world->props[i].pos.y, .texture = D_ImageHandle(draw,world->propTypes[world->props[i].propType].tag), .scale = world->propTypes[world->props[i].propType].scale, ); } } for (int i = 0; i < world->navMesh->nodeCount; i++) { NavNode n = world->navMesh->nodes[i]; D_Rect( draw, n.pos.x, n.pos.y, .texture = 0, .scale = 0.2f, ); } for(U32 i = 0; i < world->npcCount; i++) { NPC npc = world->npcs[i]; if(npc.currentArea == world->player.currentArea) { V2f drawPos = AABB_Centre(npc.collision); D_Rect(draw, drawPos.x, drawPos.y, .texture = 1); } } if(world->bandit.currentArea == world->player.currentArea) { V2f drawPos = AABB_Centre(world->bandit.collision); D_Rect(draw, drawPos.x, drawPos.y, .texture = 9); } PlayerDraw(draw, &world->player); } void SaveWorld(M_Arena *arena, World *world) { (void) arena; printf("Saving world\n"); 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); } FS_FileWrite(file, &world->propCount, sizeof(U32), offset); offset += sizeof(U32); FS_FileWrite(file, world->props, sizeof(World_Prop)*WORLD_PROP_MAX, offset); offset += sizeof(World_Prop)*WORLD_PROP_MAX; FS_FileWrite(file, &world->hitboxCount, sizeof(U32), offset); offset += sizeof(U32); 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; FS_FileClose(file); printf("Saved world :)\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; 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); } FS_FileRead(file, &world->propCount, sizeof(U32), offset); offset += sizeof(U32); 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); offset += sizeof(U32); 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; 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; FS_FileClose(file); printf("loaded world\n"); } void GenerateNavMesh(M_Arena *arena, World *world) { world->navMesh = M_ArenaPush(arena, NavMesh); world->navMesh->nodeCount = 0; for(int i = 0; i < WORLD_MAP_MAX; i++) { U32 x = (i % 96); U32 y = (i / 96); bool skip = false; for(int hi = 0; hi < world->hitboxCount; hi++) { if(AABB_Point(world->hitboxes[hi], V2F(x, y))) { skip = true; break; } } if(skip) {continue;} world->navMesh->nodes[world->navMesh->nodeCount].pos.x = x; world->navMesh->nodes[world->navMesh->nodeCount].pos.y = y; U32 cost = 20; if(Str8_Equal(world->tileTypes[world->map[i]].tag, S("path_middle"), STR8_EQUAL_IGNORE_CASE)) { cost = 10; } world->navMesh->nodes[world->navMesh->nodeCount].connectionCount = 0; for(int nx = -1; nx < 2; nx++){ for(int ny = -1; ny < 2; ny++){ if((nx==ny) && nx==0) {continue;} if(x+nx < 0 || x+nx > 95) { continue; } if(y+ny < 0 || y+ny > 49) { continue; } // It's quad for loop time :D for(int hi = 0; hi < world->hitboxCount; hi++) { if(AABB_Point(world->hitboxes[hi], V2F(x+nx, y+ny))) { skip = true; break; } } if(skip) {continue;} U32 index = x+nx + (y+ny)*96; 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].Cost = cost; world->navMesh->nodes[nCount].connectionCount++; } } world->navMesh->nodeCount++; } }