diff --git a/code/first.c b/code/first.c index d541795..30c84bd 100644 --- a/code/first.c +++ b/code/first.c @@ -60,7 +60,7 @@ int main(int argc, char **argv) G_AudioLoad(game); Audio_Context *audio = M_ArenaPush(game->arena, Audio_Context); - Audio_Init(game->arena, audio, 0.15f); + Audio_Init(game->arena, audio, 0.0f); // disabled audio U32 bgm = Audio_Play(audio, 0); U32 saloon_music = Audio_Play(audio, 1); @@ -72,7 +72,7 @@ int main(int argc, char **argv) camera->x = V3F(1, 0, 0); camera->y = V3F(0, 1, 0); camera->z = V3F(0, 0, 1); - camera->p = V3F(0, 0, 16); + camera->p = V3F(0, 0, 48); camera->fov = 60.0f; @@ -101,7 +101,7 @@ int main(int argc, char **argv) npc1->mode = NPC_ACTION_WAITING; npc1->currentArea = WORLD_AREA_OUTSIDE; npc1->waitTime = 0; - npc1->maxWaitTime = 5; + npc1->maxWaitTime = 1; npc1->currentNavNode = 0; } @@ -163,9 +163,9 @@ int main(int argc, char **argv) world->propTypes = M_ArenaPush(arena, World_PropType, .count=WORLD_PROP_TYPE_MAX); world->propTypes[0].tag=S("rug0"); - world->propTypes[0].scale=1; + world->propTypes[0].scale=3; world->propTypes[1].tag=S("rug1"); - world->propTypes[1].scale=1; + world->propTypes[1].scale=3; world->propTypes[2].tag=S("skull"); world->propTypes[2].scale=1; world->propTypes[3].tag = S("table"); @@ -173,17 +173,17 @@ int main(int argc, char **argv) world->propTypes[4].tag = S("barrel"); world->propTypes[4].scale=1; world->propTypes[5].tag = S("can"); - world->propTypes[5].scale=1; + world->propTypes[5].scale=0.5; world->propTypes[6].tag = S("candle"); - world->propTypes[6].scale=1; + world->propTypes[6].scale=0.5; world->propTypes[7].tag = S("clock"); - world->propTypes[7].scale=1; + world->propTypes[7].scale=1.5; world->propTypes[8].tag = S("log_pile"); world->propTypes[8].scale=1; world->propTypes[9].tag = S("nightstand"); world->propTypes[9].scale=1; world->propTypes[10].tag = S("pool_table"); - world->propTypes[10].scale=2; + world->propTypes[10].scale=3; world->propTypes[11].tag = S("saloon_ext"); world->propTypes[11].scale=6.875f; world->propTypes[12].tag = S("saloon_int"); @@ -191,7 +191,7 @@ int main(int argc, char **argv) world->propTypes[13].tag = S("house"); world->propTypes[13].scale=6.875f; world->propTypes[14].tag = S("house_int"); - world->propTypes[14].scale=6.875f; + world->propTypes[14].scale=12.875f; world->propTypes[15].tag=S("tile_detail_0"); world->propTypes[15].scale=1; world->propTypes[16].tag = S("tile_detail_1"); @@ -208,12 +208,15 @@ int main(int argc, char **argv) world->propTypes[21].scale=1; world->propCount = 0; world->props = M_ArenaPush(arena, World_Prop, .count=WORLD_PROP_MAX); - world->hitboxes = M_ArenaPush(arena, AABB, .count=WORLD_HITBOX_MAX); + world->hitboxes = M_ArenaPush(arena, World_Hitbox, .count=WORLD_HITBOX_MAX); + world->portals = M_ArenaPush(arena, World_Portal, .count=64); + world->portalCount=0; GenerateNavMesh(arena, world); } - game->editor.enabled = false; + game->editor.enabled = true; game->editor.mode = G_EDITOR_MODE_TILE; game->editor.currentLevel = WORLD_AREA_OUTSIDE; + game->editor.selectedNode = 0; bool running = true; @@ -263,20 +266,33 @@ int main(int argc, char **argv) break; } case G_EDITOR_MODE_HITBOX: { + case G_EDITOR_MODE_PORTAL: { game->editor.dragStart = game->editor.cursor; break; } } - } else if(e.type==SDL_EVENT_MOUSE_BUTTON_UP && e.button.button == SDL_BUTTON_LEFT && game->editor.mode == G_EDITOR_MODE_HITBOX) { + }} else if(e.type==SDL_EVENT_MOUSE_BUTTON_UP && e.button.button == SDL_BUTTON_LEFT && game->editor.mode == G_EDITOR_MODE_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( + game->world->hitboxes[game->world->hitboxCount].box.pos = topLeft; + game->world->hitboxes[game->world->hitboxCount].box.size = V2F( Abs(game->editor.cursor.x-game->editor.dragStart.x), Abs(game->editor.cursor.y-game->editor.dragStart.y) ); + game->world->hitboxes[game->world->hitboxCount].area = game->editor.currentAsset; game->world->hitboxCount++; GenerateNavMesh(game->arena, game->world); + } else if(e.type==SDL_EVENT_MOUSE_BUTTON_UP && e.button.button == SDL_BUTTON_LEFT && game->editor.mode == G_EDITOR_MODE_PORTAL) { + // Add portal + V2f topLeft = V2F(Min(game->editor.cursor.x, game->editor.dragStart.x), Min(game->editor.cursor.y, game->editor.dragStart.y)); + game->world->portals[game->world->portalCount].box.pos = topLeft; + game->world->portals[game->world->portalCount].box.size = V2F( + Abs(game->editor.cursor.x-game->editor.dragStart.x), + Abs(game->editor.cursor.y-game->editor.dragStart.y) + ); + game->world->portals[game->world->portalCount].area = game->editor.currentAsset; + game->world->portalCount++; + GenerateNavMesh(game->arena, game->world); } } @@ -288,10 +304,12 @@ int main(int argc, char **argv) } case SDLK_RIGHT: { game->editor.currentAsset = Min(game->editor.currentAsset+1, 64); + printf("editing with %d\n", game->editor.currentAsset); break; } case SDLK_LEFT: { game->editor.currentAsset = Max(game->editor.currentAsset-1, 0); + printf("editing with %d\n", game->editor.currentAsset); break; } case SDLK_A: { @@ -320,6 +338,16 @@ int main(int argc, char **argv) game->world->player.currentArea--; break; } + case SDLK_E: { + game->editor.selectedNode++; + printf("selected %d\n", game->editor.selectedNode); + break; + } + case SDLK_Q: { + game->editor.selectedNode--; + printf("selected %d\n", game->editor.selectedNode); + break; + } case SDLK_SPACE: { game->editor.mode = (game->editor.mode + 1) % 4; printf("EDITOR MODE %d\n", game->editor.mode); @@ -329,6 +357,7 @@ int main(int argc, char **argv) switch(game->editor.mode) { case G_EDITOR_MODE_PROP: {game->world->propCount--;} case G_EDITOR_MODE_HITBOX: {game->world->hitboxCount--;} + case G_EDITOR_MODE_PORTAL: {game->world->portalCount--;} } break; } @@ -387,7 +416,39 @@ int main(int argc, char **argv) G_Editor editor = game->editor; F32 tilex = cast(F32) floor(editor.cursor.x+TILE_SIZE/2); F32 tiley = cast(F32) floor(editor.cursor.y+TILE_SIZE/2); - + for (U32 i = 0; i < game->world->navMesh->nodeCount; i++) { + NavNode n = game->world->navMesh->nodes[i]; + D_Rect( + &game->draw, + n.pos.x, + n.pos.y, + .texture = 0, + .scale = 0.2f, + ); + } + for (U32 i = 0; i < game->world->navMesh->nodeCount; i++) { + NavNode n = game->world->navMesh->nodes[i]; + if(i == editor.selectedNode) { + D_Rect( + &game->draw, + n.pos.x, + n.pos.y, + .texture = 0, + .scale = 0.2f, + .c = V4F(100, 255, 0, 100), + ); + for(int j = 0; j < n.connectionCount; j++) { + D_Rect( + &game->draw, + game->world->navMesh->nodes[n.connections[j].NodeIndex].pos.x, + game->world->navMesh->nodes[n.connections[j].NodeIndex].pos.y, + .texture = 0, + .scale = 0.2f, + .c = V4F(0, 100, 0, 100), + ); + } + } + } switch(game->editor.mode) { case G_EDITOR_MODE_TILE: { World_Tile asset = game->world->tileTypes[editor.currentAsset]; @@ -401,22 +462,36 @@ int main(int argc, char **argv) } case G_EDITOR_MODE_HITBOX: { for(U32 i = 0; i < game->world->hitboxCount; i++) { - V2f centre = AABB_Centre(game->world->hitboxes[i]); + if(game->world->player.currentArea == game->world->hitboxes[i].area) { + V2f centre = AABB_Centre(game->world->hitboxes[i].box); + D_Rect( + &game->draw, + centre.x, + centre.y, + .texture=0, + .dim=game->world->hitboxes[i].box.size, + .flags=D_RECT_IGNORE_ASPECT, + .c=V4F(100,0,0,0.7f), + ); + } + } + break; + } + case G_EDITOR_MODE_PORTAL: { + for(U32 i = 0; i < game->world->portalCount; i++) { + V2f centre = AABB_Centre(game->world->portals[i].box); D_Rect( &game->draw, centre.x, centre.y, .texture=0, - .dim=game->world->hitboxes[i].size, + .dim=game->world->portals[i].box.size, .flags=D_RECT_IGNORE_ASPECT, - .c=V4F(100,0,0,0.7f), + .c=V4F(0,0,100,0.7f), ); } break; } - case G_EDITOR_MODE_POI: { - break; - } } } D_End(&game->draw, frame); diff --git a/code/game/core.h b/code/game/core.h index 5b918ce..efa3448 100644 --- a/code/game/core.h +++ b/code/game/core.h @@ -21,7 +21,7 @@ enum G_EDITOR_MODE { G_EDITOR_MODE_TILE, G_EDITOR_MODE_PROP, G_EDITOR_MODE_HITBOX, - G_EDITOR_MODE_POI, + G_EDITOR_MODE_PORTAL, }; typedef struct G_Editor G_Editor; @@ -32,6 +32,7 @@ struct G_Editor { G_EDITOR_MODE mode; V2f cursor; V2f dragStart; + U32 selectedNode; }; typedef struct G_State G_State; diff --git a/code/game/impl/aabb.c b/code/game/impl/aabb.c index b7d475d..40c6e46 100644 --- a/code/game/impl/aabb.c +++ b/code/game/impl/aabb.c @@ -11,7 +11,7 @@ bool AABB_Collide(AABB a, AABB b) bool AABB_Point(AABB a, V2f v) { bool collision_x = a.pos.x + a.size.x >= v.x && a.pos.x <= v.x; - bool collision_y = a.pos.x + a.size.y >= v.y && a.pos.y <= v.y; + bool collision_y = a.pos.y + a.size.y >= v.y && a.pos.y <= v.y; return collision_x && collision_y; } @@ -45,4 +45,4 @@ bool AABB_Circle(F32 rad, V2f radOrigin, AABB a) F32 xSq = (Abs(aCentre.x) - Abs(radOrigin.x)) * (Abs(aCentre.x) - Abs(radOrigin.x)); F32 ySq = (Abs(aCentre.y) - Abs(radOrigin.y)) * (Abs(aCentre.y) - Abs(radOrigin.y)); return SDL_sqrt(xSq + ySq) < rad; -} \ No newline at end of file +} diff --git a/code/game/impl/bandit.c b/code/game/impl/bandit.c index 02f4314..2c22d6a 100644 --- a/code/game/impl/bandit.c +++ b/code/game/impl/bandit.c @@ -10,6 +10,11 @@ V2f shootTowards(Bandit *bandit, V2f target, Random* r) } void UpdateBandit(F32 delta, Bandit *bandit, World *world) { + for(U32 i = 0; i < world->portalCount; i++) { + if(AABB_Collide(world->portals[0].box, bandit->collision)) { + bandit->currentArea = world->portals[0].area; + } + } if ( world->player.controls.shot && AABB_Slab(world->player.collision.pos, world->player.shotPos, bandit->collision) && bandit->currentArea == world->player.currentArea) { diff --git a/code/game/impl/npc.c b/code/game/impl/npc.c index 3ea5599..c3febc6 100644 --- a/code/game/impl/npc.c +++ b/code/game/impl/npc.c @@ -4,6 +4,11 @@ #include "core/math.h" void UpdateNPC(F32 delta, NPC *npc, World *world) { + for(U32 i = 0; i < world->portalCount; i++) { + if(AABB_Collide(world->portals[0].box, npc->collision)) { + npc->currentArea = world->portals[0].area; + } + } switch (npc->mode) { case NPC_ACTION_WAITING: npc->waitTime+=delta; diff --git a/code/game/impl/player.c b/code/game/impl/player.c index a98b698..7b95b5e 100644 --- a/code/game/impl/player.c +++ b/code/game/impl/player.c @@ -165,6 +165,12 @@ void PlayerUpdate(F32 delta, Player *player) { player->collision.pos.x += dir.x; player->collision.pos.y += dir.y; + for(U32 i = 0; i < player->world->portalCount; i++) { + if(AABB_Collide(player->world->portals[i].box, player->collision)) { + player->currentArea = player->world->portals[i].area; + } + } + V2f test; test.x = player->collision.pos.x - 14; test.y = player->collision.pos.y - 14; @@ -174,6 +180,7 @@ void PlayerUpdate(F32 delta, Player *player) { Audio_ChangeVolume(player->world->audio, player->world->audio_handles[1], vol); Audio_ChangeVolume(player->world->audio, player->world->audio_handles[0], 1.0f - vol); + } void PlayerDraw(D_Context *draw, Player *player) { diff --git a/code/game/impl/world.c b/code/game/impl/world.c index bacdbb9..2a67b6d 100644 --- a/code/game/impl/world.c +++ b/code/game/impl/world.c @@ -64,16 +64,6 @@ void RenderWorld(World *world, D_Context *draw) { ); } } - for (U32 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) { @@ -124,6 +114,8 @@ void SaveWorld(World *world) { WRITEN(world->map, WORLD_MAP_MAX); + WRITE(world->portalCount); + WRITEN(world->portals, WORLD_PORTAL_MAX); FS_FileClose(file); printf("--- World Saved ---\n"); @@ -197,14 +189,14 @@ void LoadWorld(M_Arena *arena, World *world) { // { U32 n_hitbox = *(U32 *) base; base += 4; - AABB *boxes = (AABB *) base; + World_Hitbox *boxes = (World_Hitbox *) base; world->hitboxCount = n_hitbox; - world->hitboxes = M_ArenaPush(arena, AABB, .count = WORLD_HITBOX_MAX); + world->hitboxes = M_ArenaPush(arena, World_Hitbox, .count = WORLD_HITBOX_MAX); - M_CopySize(world->hitboxes, boxes, n_hitbox * sizeof(AABB)); + M_CopySize(world->hitboxes, boxes, n_hitbox * sizeof(World_Hitbox)); - base += (WORLD_HITBOX_MAX * sizeof(AABB)); + base += (WORLD_HITBOX_MAX * sizeof(World_Hitbox)); } // Map @@ -217,11 +209,24 @@ void LoadWorld(M_Arena *arena, World *world) { base += (WORLD_MAP_MAX * sizeof(U32)); } + { + U32 n_portals = *(U32 *) base; base += 4; + World_Portal *portals = (World_Portal *) base; + + world->portalCount = n_portals; + world->portals = M_ArenaPush(arena, World_Portal, .count = WORLD_PORTAL_MAX); + + M_CopySize(world->portals, portals, n_portals * sizeof(World_Portal)); + + base += (WORLD_PORTAL_MAX * sizeof(World_Portal)); + } if (base != (data.data + data.count)) { printf("--- OFFSET MISMATCH ---\n"); } + printf("loaded world\n"); + printf(" - %d props\n", world->propCount); printf(" - %d hitboxes\n", world->hitboxCount); @@ -237,7 +242,7 @@ void GenerateNavMesh(M_Arena *arena, World *world) { U32 y = (i / 96); bool skip = false; for(U32 hi = 0; hi < world->hitboxCount; hi++) { - if(AABB_Point(world->hitboxes[hi], V2F((F32) x, (F32) y))) { + if(AABB_Point(world->hitboxes[hi].box, V2F((F32) x, (F32) y))) { skip = true; break; } @@ -245,14 +250,10 @@ void GenerateNavMesh(M_Arena *arena, World *world) { if(skip) {continue;} world->navMesh->nodes[world->navMesh->nodeCount].pos.x = cast(F32) x; world->navMesh->nodes[world->navMesh->nodeCount].pos.y = cast(F32) 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(nx==0 && ny==0) {continue;} if(x+nx < 0 || x+nx > 95) { continue; } @@ -261,19 +262,47 @@ void GenerateNavMesh(M_Arena *arena, World *world) { } // It's quad for loop time :D for(U32 hi = 0; hi < world->hitboxCount; hi++) { - if(AABB_Point(world->hitboxes[hi], V2F((F32) (x + nx), (F32) (y + ny)))) { + if(AABB_Point(world->hitboxes[hi].box, V2F((F32) (x + nx), (F32) (y + ny)))) { skip = true; break; } } - if(skip) {continue;} - U32 index = x+nx + (y+ny)*96; U32 nCount = world->navMesh->nodeCount; + S32 index = -1; + for (U32 ohgod = 0; ohgod < nCount; ohgod++) { + if(world->navMesh->nodes[ohgod].pos.x == nx+x&& world->navMesh->nodes[ohgod].pos.y == y+ny) { + index=ohgod; + break; + } + } + F32 cost = 20; + if(ny+nx == 2) { + cost = 40; + }; + if(Str8_Equal(world->tileTypes[world->map[i]].tag, S("path_middle"), STR8_EQUAL_IGNORE_CASE)) { + cost = 1; + if(Abs(ny+nx) == 2) { + cost = 4; + }; + } + if(index < 0) {continue;} + skip |= (index > (S32) nCount); + if(skip) {continue;} world->navMesh->nodes[nCount].connections[world->navMesh->nodes[nCount].connectionCount].NodeIndex = index; - world->navMesh->nodes[nCount].connections[world->navMesh->nodes[nCount].connectionCount].Cost = cast(F32) cost; + world->navMesh->nodes[nCount].connections[world->navMesh->nodes[nCount].connectionCount].Cost = cost; + world->navMesh->nodes[index].connections[world->navMesh->nodes[index].connectionCount].NodeIndex = nCount; + world->navMesh->nodes[index].connections[world->navMesh->nodes[index].connectionCount].Cost = cost; world->navMesh->nodes[nCount].connectionCount++; + world->navMesh->nodes[index].connectionCount++; } } world->navMesh->nodeCount++; } + for(U32 i = 0; i < world->npcCount; i++) { + world->npcs[i].mode = NPC_ACTION_WAITING; + world->npcs[i].maxWaitTime = Random_F32(&world->random, 20, 140); + world->npcs[i].waitTime = 0; + world->npcs[i].currentNavNode=0; + world->npcs[i].pathIndex = 0; + } } diff --git a/code/game/world.h b/code/game/world.h index df710c3..e68fdfd 100644 --- a/code/game/world.h +++ b/code/game/world.h @@ -2,19 +2,21 @@ #define LD_GAME_WORLD_H_ #include "../core/math.h" +#include "./aabb.h" #define WORLD_HITBOX_MAX 4096 #define WORLD_PROP_MAX 2048 #define WORLD_PROP_TYPE_MAX 64 #define WORLD_TILE_TYPE_MAX 64 #define WORLD_MAP_MAX 4800 +#define WORLD_PORTAL_MAX 64 // Areas are which typedef U32 World_Area; enum World_Area { - WORLD_AREA_OUTSIDE = (1 << 0), - WORLD_AREA_SALOON = (1 << 1), + WORLD_AREA_OUTSIDE = 1, + WORLD_AREA_SALOON = 2, }; typedef struct World_Tile World_Tile; @@ -37,6 +39,15 @@ struct World_Prop V2f pos; }; +typedef struct World_Portal World_Portal; +struct World_Portal +{ + AABB box; + World_Area area; +}; +typedef World_Portal World_Hitbox; + + typedef struct World World; #include "player.h" #include "npc.h" @@ -53,10 +64,12 @@ struct World { World_Tile *tileTypes; World_PropType *propTypes; World_Prop *props; - AABB *hitboxes; + World_Hitbox *hitboxes; + World_Portal *portals; U32 *map; U32 propCount; + U32 portalCount; U32 hitboxCount; Audio_Context *audio; diff --git a/code/world.sgdat b/code/world.sgdat index b02130a..3feb28a 100644 Binary files a/code/world.sgdat and b/code/world.sgdat differ