From 680d375b8cfdd05263e58b6bfcca322fa09db509 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 6 Oct 2025 21:07:55 +0100 Subject: [PATCH 1/4] feat: Added portals --- code/first.c | 94 +++++++++++++++++++++++++++++++++++----- code/game/core.h | 3 +- code/game/impl/aabb.c | 4 +- code/game/impl/bandit.c | 5 +++ code/game/impl/npc.c | 5 +++ code/game/impl/player.c | 5 +++ code/game/impl/world.c | 59 +++++++++++++++++-------- code/game/world.h | 16 ++++++- code/world.sgdat | Bin 120960 -> 120960 bytes 9 files changed, 158 insertions(+), 33 deletions(-) diff --git a/code/first.c b/code/first.c index cbdc4b4..2bae5da 100644 --- a/code/first.c +++ b/code/first.c @@ -88,7 +88,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; @@ -112,7 +112,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; } @@ -174,9 +174,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"); @@ -184,17 +184,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"); @@ -220,11 +220,14 @@ int main(int argc, char **argv) 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->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; @@ -274,11 +277,12 @@ 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; @@ -288,6 +292,17 @@ int main(int argc, char **argv) ); 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); } } @@ -299,10 +314,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: { @@ -331,6 +348,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); @@ -398,6 +425,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 (int 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 (int 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]; @@ -424,7 +484,19 @@ int main(int argc, char **argv) } break; } - case G_EDITOR_MODE_POI: { + 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->portals[i].box.size, + .flags=D_RECT_IGNORE_ASPECT, + .c=V4F(0,0,100,0.7), + ); + } break; } } 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 d24f62c..f66af50 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(int 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..7be61d0 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(int 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 4ebdfc3..6585f3f 100644 --- a/code/game/impl/player.c +++ b/code/game/impl/player.c @@ -165,6 +165,11 @@ void PlayerUpdate(F32 delta, Player *player) { dir = V2f_Scale(NormaliseV2F(dir), PLAYER_SPEED*delta); player->collision.pos.x += dir.x; player->collision.pos.y += dir.y; + for(int i = 0; i < player->world->portalCount; i++) { + if(AABB_Collide(player->world->portals[0].box, player->collision)) { + player->currentArea = player->world->portals[0].area; + } + } } void PlayerDraw(D_Context *draw, Player *player) { diff --git a/code/game/impl/world.c b/code/game/impl/world.c index 2b96290..0f01f33 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 (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) { @@ -127,6 +117,11 @@ void SaveWorld(M_Arena *arena, World *world) { FS_FileWrite(file, world->map, sizeof(U32)*WORLD_MAP_MAX, offset); offset += sizeof(U32)*WORLD_MAP_MAX; + FS_FileWrite(file, &world->portalCount, sizeof(U32), offset); + offset += sizeof(U32); + + FS_FileWrite(file, world->hitboxes, sizeof(World_Portal)*WORLD_PORTAL_MAX, offset); + FS_FileClose(file); printf("Saved world :)\n"); } @@ -175,6 +170,12 @@ void LoadWorld(M_Arena *arena, World *world) { FS_FileRead(file, world->map, sizeof(U32)*WORLD_MAP_MAX, offset); offset += sizeof(U32)*WORLD_MAP_MAX; + FS_FileRead(file, &world->portalCount, sizeof(U32), offset); + offset += sizeof(U32); + + world->portals = M_ArenaPush(arena, World_Portal, .count=WORLD_PORTAL_MAX); + FS_FileRead(file, world->hitboxes, sizeof(World_Portal)*WORLD_PORTAL_MAX, offset); + FS_FileClose(file); printf("loaded world\n"); } @@ -195,14 +196,10 @@ void GenerateNavMesh(M_Arena *arena, World *world) { 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(nx==0 && ny==0) {continue;} if(x+nx < 0 || x+nx > 95) { continue; } @@ -216,14 +213,42 @@ void GenerateNavMesh(M_Arena *arena, World *world) { break; } } - if(skip) {continue;} - U32 index = x+nx + (y+ny)*96; U32 nCount = world->navMesh->nodeCount; + S32 index = -1; + for(int 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 > 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 = 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(int 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 e86c95d..03e5ba7 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,13 @@ struct World_Prop V2f pos; }; +typedef struct World_Portal World_Portal; +struct World_Portal +{ + AABB box; + World_Area area; +}; + typedef struct World World; #include "player.h" #include "npc.h" @@ -54,11 +63,14 @@ struct World { World_PropType *propTypes; World_Prop *props; AABB *hitboxes; + World_Portal *portals; U32 *map; U32 propCount; + U32 portalCount; U32 hitboxCount; + //// Player Player player; diff --git a/code/world.sgdat b/code/world.sgdat index b02130a630b497ef065c279f72151fa4db8f7565..5788440ab0fd31cd515a47837ea2518f790e8265 100644 GIT binary patch delta 103 zcmZqJ$lkD#eZz5PAqNK*1_&rBO*dpli5*)!JZ8&oSc}Kl9LML*t5b!a`Kb2 n85j;swqvnpbZD+)* Date: Mon, 6 Oct 2025 21:30:13 +0100 Subject: [PATCH 2/4] chore: fix \n --- code/first.c | 2 +- code/game/impl/bandit.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/first.c b/code/first.c index f4221eb..9799124 100644 --- a/code/first.c +++ b/code/first.c @@ -202,7 +202,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"); diff --git a/code/game/impl/bandit.c b/code/game/impl/bandit.c index f66af50..858eda1 100644 --- a/code/game/impl/bandit.c +++ b/code/game/impl/bandit.c @@ -23,7 +23,7 @@ void UpdateBandit(F32 delta, Bandit *bandit, World *world) { } if (AABB_Circle(bandit->agroRadius, AABB_Centre(bandit->collision), world->player.collision) && !(bandit->mode == BANDIT_SHOOTING || bandit->mode == BANDIT_SHOOTOUT)) { - printf("begin shootout"); + printf("begin shootout\n"); // shootout time o.o bandit->mode = BANDIT_SHOOTOUT; } @@ -71,17 +71,17 @@ void UpdateBandit(F32 delta, Bandit *bandit, World *world) { bandit->reloadTimer -= delta; if (bandit->shootCooldownTimer < 0 && bandit->reloadTimer < 0) { - printf("shoot at player"); + printf("shoot at player\n"); bandit->bullets--; bandit->shootCooldownTimer = bandit->shootDelay; V2f banditShot = shootTowards(bandit, world->player.collision.pos, &world->random); if(AABB_Slab(bandit->collision.pos, banditShot, world->player.collision)){ // gets shot lmao - printf("hit"); + printf("hit\n"); world->player.health--; } if(bandit->bullets == 0){ - printf("enemy reload"); + printf("enemy reload\n"); bandit->bullets = 6; bandit->reloadTimer = bandit->reloadTime; } From c01a6be4e583f65393d74861cddfd49b785694d4 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 6 Oct 2025 21:35:32 +0100 Subject: [PATCH 3/4] feat: Initial prop placement --- code/world.sgdat | Bin 120960 -> 120960 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/code/world.sgdat b/code/world.sgdat index 804a7141cbfa4482bdb532e4d819f9752f4c0fdf..e3a124fc5b13537f321f85882e503079a654699e 100644 GIT binary patch literal 120960 zcmeI&Ux-{+9l-HZleF8${IOOXiQ3VYvVz!2nzmcDnR{;plb3cyN&^OWw#kxRI^7+1 zC%7WoQ9%~LI*OKkuq)8R*5GW)sWvS2>(uWbD`XCse+^68VyL0aE=63#^ znYnZ4ZuT1(?)=U<_nhDFbMC#nd&yq4^{+fvoS8a1w^*La`3-xU&86w`?9?-JXU`UA z{FZ|sZl0Psd#+>O)dN@Z?asS;;H1;O@5&o((rD4_uhO#lWW8l`WbQKyi}N#!eswpD z-fI5P+(Gk=37Y1Uj+sPM4>#pFAP|ed?&d6u=g;Xo)^S3yzSbOPPqTmN>GQ>+QkA@E zC{I7Nc{4k=Hb*=)y|_5DIb>I}<;?WF{+2fbbhvf@2XmY$E}VHuJ{%FuQPm zNiX!ib9-~4&4#JXQIEO%nvGkx-b{IVuIN9~D*09&TB>!&k#-#qwCgz9uH(UW9S`{( z&1^aBFo9=uz5Y+WTl~69Z@6k@-3{VQ)>9ilmw4mXo?3lZ;>Js!x^_Y0YcF`};PVn^ z|LCd8KP6Uw^3*Gz^n&?w&v{CXOPnows&>D`^~d%6ha@ii&sCFmOI*L;s>~N9F6CV{ z9-42m92j&QEPvde5#MRYB^M&bKOyTjv&AKi>}HYb3SH#oOM^#pOv_=U(bJ4 z;zGq$PQeYvuVr<#60BO1xU|RIVoTkF9tr zvrFRjZ+WWzqU2M*O^^SL#ErM~{Ey4{OwLm!N8%H^JypFZ@z^hQzRyWqxTyE*xWu*J z>hrJ5{2RJ|@@|PwT+sQ2@>j3w{r`%0r}51ES?_ONV&`YN-Y-j>`<15(2PDou>!}l; zlDPJ;r!Mc4ICFUO`U&R0_HS2Bg!=vKVdXP2zINPIt8co&_{tSWRmu`q-*eU4eG)e^ zI-kEe!T3gAdp|6(I_9ah|4Mx7w5KNWa{lBGwCCIT;QWanX`gRP|K(rk`RpOgN{ziY3TC2q{QN?me-@r~1te}4pVVSbp5YNTtDQhSAHn5^Q3xeug2t6Vkvfb>_tr`JCc ziZ^upsKm>9zc(I~cy`iL?>!{(#uM7-3lcZJt9?H&acNFJ{|`xg`FVYQXuZ{{zWy@O zzq+R535heWc`EyYpd#*nErWDEl50}_qUpLg8D1p(C6Q!P5Fla0tg_000Iag zfB*srAbeE_{#NP-d zb2Qh6e-G@|pMA+Jo9HU0#yGDnbN!k^qOoc3b{s}--PTOHKg~6!Ik&j>X;?M(d(DUI ziZi!3@(Je_*Y`MUjOJuhbEh%3xpkT&np4{1ZZ-P-?S3|d>kfa9tHy4*#kI~T=P@lKcum{yan)$MUN06& z=Vn_&oa5rCu@}=`a*rdoR_nFPw_SUyIpS)wtuf8H#bq&yd2Id3Z8!q``X_Ne^qbpo zq=qwVnre*hsmaa%|B>c>$jx^2Ya8|d|BSkuD=qAA^1NA(?cP852JQNc)3A=C@V{Lb zlk~^Grdqw@^zZdn??01x_v!EHPV(>N{pYaWeMX-{JITMFXN>VONB^3&`DZ&m>~Hf< zd^?WupF92h{IxZ-*$;nAtNDz7Ki7usx}zSK<{HzSTU`5QQ)8=ZGp_YJ&0~{Wr}GEt zi=*aNb41%lSz|Y!ICJysj@EA0Z`W@6hk1;%#(whbRQn*gb(*)IJco6TO^u_f#U{65 zxg<63C~CCb&rZ4dbC^$3R>N4QQ;ow|ua`Ny5Pl6VJXa_e{hlXUE4+^Nsh*vtDL|L=U8cR+*IZ*uF` zKU{Y-muMUw8~684YsFdPAbGdSF)g_bQdhTg(_CYkbL-}6+n?qd)0~^FZ?|!2t})HI qb#t}tAEd@s&urUuZN?3fo6Y=b7_$> Date: Mon, 6 Oct 2025 21:57:06 +0100 Subject: [PATCH 4/4] feat: made hitboxes area dependent --- code/first.c | 30 +++++++++++++++++------------- code/game/impl/world.c | 12 ++++++------ code/game/world.h | 4 +++- code/world.sgdat | Bin 120960 -> 137092 bytes 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/code/first.c b/code/first.c index 9799124..6f2762c 100644 --- a/code/first.c +++ b/code/first.c @@ -219,7 +219,7 @@ 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); @@ -285,11 +285,12 @@ 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 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) { @@ -367,6 +368,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; } @@ -471,16 +473,18 @@ 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]); - D_Rect( - &game->draw, - centre.x, - centre.y, - .texture=0, - .dim=game->world->hitboxes[i].size, - .flags=D_RECT_IGNORE_ASPECT, - .c=V4F(100,0,0,0.7f), - ); + 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; } diff --git a/code/game/impl/world.c b/code/game/impl/world.c index cebe920..e979e52 100644 --- a/code/game/impl/world.c +++ b/code/game/impl/world.c @@ -189,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 @@ -242,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; } @@ -262,7 +262,7 @@ 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; } diff --git a/code/game/world.h b/code/game/world.h index 32cf62e..6977581 100644 --- a/code/game/world.h +++ b/code/game/world.h @@ -45,6 +45,8 @@ struct World_Portal AABB box; World_Area area; }; +typedef World_Portal World_Hitbox; + typedef struct World World; #include "player.h" @@ -62,7 +64,7 @@ struct World { World_Tile *tileTypes; World_PropType *propTypes; World_Prop *props; - AABB *hitboxes; + World_Hitbox *hitboxes; World_Portal *portals; U32 *map; diff --git a/code/world.sgdat b/code/world.sgdat index e3a124fc5b13537f321f85882e503079a654699e..3feb28ad6f33faf6f7249708f495a5a05b85e1d7 100644 GIT binary patch delta 149 qcmZqJ$lkJ^qhSl1bMp|eF2So=52Zam{5)>R990F!=2sEJ3#idj@ z4h{})=u%8Th=Y6bUNQt1TjYdYX}lVV3vs->=tcZ#sLxNkjYXQ5X+9=0VmoG< z;v@~czfnpPb`~kLR8+ksQm}Y5{8l$#ask#A%*8ZGqp6UwGQe#I4E2#{n`nvXgs4Q6 z?Z*pY@3BV18VyESrf7#M#{?Hfu+`hAEcS3NPvm@t-pau1eZ^-bhtxyt_wFXnmKnd& zSA1S#W;@>h1KZfUf8du&cUZ6X(N}z|cv@NNO?;4>CbqPslK(}@+mZu6qaAwP-p3