Compare commits

4 Commits

Author SHA1 Message Date
d9957eead1 feat: Nav mesh generation 2025-10-06 18:23:47 +01:00
c4cf8f532b feat: World loading that's broken 2025-10-06 16:35:22 +01:00
8a360df98a feat: Hitbox drawing 2025-10-06 14:50:32 +01:00
3a84947750 feat: Basic level editing 2025-10-06 14:26:00 +01:00
22 changed files with 431 additions and 35070 deletions

BIN
assets/barrel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

BIN
assets/can.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

BIN
assets/candle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

BIN
assets/clock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

BIN
assets/house.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
assets/house_int.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
assets/log_pile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

BIN
assets/nightstand.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

BIN
assets/pool_table.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

BIN
assets/rug0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

BIN
assets/rug1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/saloon_int.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
assets/skull.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

BIN
assets/table.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

View File

@@ -24,7 +24,6 @@
#include "game/impl/world.c" #include "game/impl/world.c"
#include "game/impl/npc.c" #include "game/impl/npc.c"
#include "game/impl/bandit.c" #include "game/impl/bandit.c"
#include "game/testnavmesh.h"
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
@@ -95,20 +94,22 @@ int main(int argc, char **argv)
camera->farp = 1000.0f; camera->farp = 1000.0f;
game->draw.camera = camera; game->draw.camera = camera;
World *world = LoadWorld(arena); World *world = M_ArenaPush(arena, World);
//LoadWorld(arena, world);
game->world = world; game->world = world;
world->arena = arena; world->arena = arena;
//world->navMesh = &TestNavMesh;
world->random = Random_Seed(29237489723847); world->random = Random_Seed(29237489723847);
world->npcCount = 2; world->npcCount = 127;
for(U32 i = 0; i < world->npcCount; i++) { for(U32 i = 0; i < world->npcCount; i++) {
NPC *npc1 = &world->npcs[i]; NPC *npc1 = &world->npcs[i];
npc1->collision.pos.x = 15; npc1->collision.pos.x = 0;
npc1->collision.pos.y = 15; npc1->collision.pos.y = 0;
npc1->collision.size.x = 1; npc1->collision.size.x = 1;
npc1->collision.size.y = 2; npc1->collision.size.y = 2;
npc1->name = S("Matt"); npc1->name = S("Matt");
npc1->mode = NPC_ACTION_WAITING; npc1->mode = NPC_ACTION_WAITING;
npc1->currentArea = i; npc1->currentArea = WORLD_AREA_OUTSIDE;
npc1->waitTime = 0; npc1->waitTime = 0;
npc1->maxWaitTime = 5; npc1->maxWaitTime = 5;
npc1->currentNavNode = 0; npc1->currentNavNode = 0;
@@ -133,8 +134,94 @@ int main(int argc, char **argv)
world->player.pos.y = 0; world->player.pos.y = 0;
world->player.bulletsLoaded = PLAYER_BULLET_COUNT; world->player.bulletsLoaded = PLAYER_BULLET_COUNT;
world->player.reloadTimer = 0; world->player.reloadTimer = 0;
world->player.currentArea = 0; world->player.currentArea = WORLD_AREA_OUTSIDE;
world->map = map;
world->tileTypes = M_ArenaPush(arena, World_Tile, .count=WORLD_TILE_TYPE_MAX);
world->tileTypes[0].rotation=0;
world->tileTypes[0].tag=S("tile_dirt_0");
world->tileTypes[1].rotation=0,
world->tileTypes[1].tag=S("path_middle");
world->tileTypes[2].rotation=0;
world->tileTypes[2].tag=S("path_middle_edge");
world->tileTypes[3].rotation=PI_F32/2;
world->tileTypes[3].tag=S("path_middle_edge");
world->tileTypes[4].rotation=PI_F32;
world->tileTypes[4].tag=S("path_middle_edge");
world->tileTypes[5].rotation=-PI_F32/2;
world->tileTypes[5].tag=S("path_middle_edge");
world->tileTypes[6].rotation=0;
world->tileTypes[6].tag=S("path_middle");
world->tileTypes[7].rotation=PI_F32/2;
world->tileTypes[7].tag=S("path_middle");
world->tileTypes[8].rotation=-PI_F32;
world->tileTypes[8].tag=S("path_middle");
world->tileTypes[9].rotation=-PI_F32/2;
world->tileTypes[9].tag=S("path_middle");
world->tileTypes[10].rotation=0;
world->tileTypes[10].tag=S("path_corner");
world->tileTypes[11].rotation=PI_F32/2;
world->tileTypes[11].tag=S("path_corner");
world->tileTypes[12].rotation=-PI_F32/2;
world->tileTypes[12].tag=S("path_corner");
world->tileTypes[13].rotation=PI_F32;
world->tileTypes[13].tag=S("path_corner");
world->tileTypes[14].rotation=0;
world->tileTypes[14].tag=S("tile_dirt_1");
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[1].tag=S("rug1");
world->propTypes[1].scale=1;
world->propTypes[2].tag=S("skull");
world->propTypes[2].scale=1;
world->propTypes[3].tag = S("table");
world->propTypes[3].scale=2;
world->propTypes[4].tag = S("barrel");
world->propTypes[4].scale=1;
world->propTypes[5].tag = S("can");
world->propTypes[5].scale=1;
world->propTypes[6].tag = S("candle");
world->propTypes[6].scale=1;
world->propTypes[7].tag = S("clock");
world->propTypes[7].scale=1;
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[11].tag = S("saloon_ext");
world->propTypes[11].scale=6.875f;
world->propTypes[12].tag = S("saloon_int");
world->propTypes[12].scale=2*6.875f;
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[15].tag=S("tile_detail_0");
world->propTypes[15].scale=1;
world->propTypes[16].tag = S("tile_detail_1");
world->propTypes[16].scale=1;
world->propTypes[17].tag = S("tile_detail_2");
world->propTypes[17].scale=1;
world->propTypes[18].tag= S("tile_detail_3");
world->propTypes[18].scale=1;
world->propTypes[19].tag= S("tile_detail_4");
world->propTypes[19].scale=1;
world->propTypes[20].tag=S("tile_detail_5");
world->propTypes[20].scale=1;
world->propTypes[21].tag=S("tile_detail_6");
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);
GenerateNavMesh(arena, world);
} }
game->editor.enabled = false;
game->editor.mode = G_EDITOR_MODE_TILE;
game->editor.currentLevel = WORLD_AREA_OUTSIDE;
D_Animation animation; D_Animation animation;
@@ -145,8 +232,6 @@ int main(int argc, char **argv)
bool running = true; bool running = true;
printf("%zu size in bytes\n", sizeof(TestNavMesh));
const int width = 1280; const int width = 1280;
const int height = 720; const int height = 720;
@@ -164,13 +249,106 @@ int main(int argc, char **argv)
V2F((F32) width, (F32) height) V2F((F32) width, (F32) height)
)); ));
game->world->mouseProjected = V2F(projection.x, projection.y); game->world->mouseProjected = V2F(projection.x, projection.y);
ProcessEvents(&e, game->world); if(e.type==SDL_EVENT_MOUSE_MOTION) {
game->editor.cursor = V2F(projection.x, projection.y);
}
if (!game->editor.enabled) {
ProcessEvents(&e, game->world);
} else {
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);
game->world->map[(S32)tilex + (S32)tiley * 96] = game->editor.currentAsset;
break;
}
case G_EDITOR_MODE_PROP: {
game->world->props[game->world->propCount].propType = game->editor.currentAsset;
game->world->props[game->world->propCount].area = game->editor.currentLevel;
game->world->props[game->world->propCount].pos = game->editor.cursor;
game->world->propCount++;
break;
}
case G_EDITOR_MODE_HITBOX: {
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) {
// 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(
Abs(game->editor.cursor.x-game->editor.dragStart.x),
Abs(game->editor.cursor.y-game->editor.dragStart.y)
);
game->world->hitboxCount++;
}
}
if (e.type == SDL_EVENT_KEY_DOWN) {
switch(e.key.key) {
case SDLK_F10: {
game->editor.enabled = !game->editor.enabled;
break;
}
case SDLK_RIGHT: {
game->editor.currentAsset = Min(game->editor.currentAsset+1, 64);
break;
}
case SDLK_LEFT: {
game->editor.currentAsset = Max(game->editor.currentAsset-1, 0);
break;
}
case SDLK_A: {
game->camera.p.x -= 5;
break;
}
case SDLK_D: {
game->camera.p.x += 5;
break;
}
case SDLK_W: {
game->camera.p.y -= 5;
break;
}
case SDLK_S: {
game->camera.p.y += 5;
break;
}
case SDLK_UP: {
game->editor.currentLevel++;
game->world->player.currentArea++;
break;
}
case SDLK_DOWN: {
game->editor.currentLevel--;
game->world->player.currentArea--;
break;
}
case SDLK_SPACE: {
game->editor.mode = (game->editor.mode + 1) % 4;
printf("EDITOR MODE %d\n", game->editor.mode);
break;
}
case SDLK_U: {
switch(game->editor.mode) {
case G_EDITOR_MODE_PROP: {game->world->propCount--;}
case G_EDITOR_MODE_HITBOX: {game->world->hitboxCount--;}
}
break;
}
}
}
} }
UpdateWorld(1.0f / 60.0f, game->world); if(!game->editor.enabled) {
D_AnimationUpdate(&animation, 1.0f / 250.0f); UpdateWorld(1.0f / 60.0f, game->world);
game->camera.p.x = game->world->player.pos.x; game->camera.p.x = game->world->player.pos.x;
game->camera.p.y = game->world->player.pos.y; game->camera.p.y = game->world->player.pos.y;
}
D_AnimationUpdate(&animation, 1.0f / 250.0f);
int w, h; int w, h;
SDL_GetWindowSizeInPixels(window, &w, &h); SDL_GetWindowSizeInPixels(window, &w, &h);
@@ -184,7 +362,7 @@ int main(int argc, char **argv)
VkCommandBuffer cmd = frame->cmd; VkCommandBuffer cmd = frame->cmd;
VkClearValue clear_colour; VkClearValue clear_colour;
clear_colour.color.float32[0] = 1.0f; clear_colour.color.float32[0] = 0.0f;
clear_colour.color.float32[1] = 0.0f; clear_colour.color.float32[1] = 0.0f;
clear_colour.color.float32[2] = 0.0f; clear_colour.color.float32[2] = 0.0f;
clear_colour.color.float32[3] = 1.0f; clear_colour.color.float32[3] = 1.0f;
@@ -208,14 +386,46 @@ int main(int argc, char **argv)
D_Begin(&game->draw, frame, D_MAX_RECTS); D_Begin(&game->draw, frame, D_MAX_RECTS);
//RenderWorld(game->world, &game->draw); RenderWorld(game->world, &game->draw);
// D_Rect(&game->draw, 0.0f, 0.0f, .texture = D_ImageHandle(&game->draw, S("saloon_ext")), .scale = 4.0f);
// D_Rect(&game->draw, -8.0f, 0.0f, .texture = 2, .scale = 2.0f);
// D_Rect(&game->draw, 6.0f, 0.0f, .texture = 3);
R2f aframe = D_AnimationFrame(&animation); R2f aframe = D_AnimationFrame(&animation);
D_Rect(&game->draw, 0, 0, .texture = animation.id, .uv = aframe, .flags = D_RECT_UV_ASPECT); D_Rect(&game->draw, 0, 0, .texture = animation.id, .uv = aframe, .flags = D_RECT_UV_ASPECT);
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);
switch(game->editor.mode) {
case G_EDITOR_MODE_TILE: {
World_Tile asset = game->world->tileTypes[editor.currentAsset];
D_Rect(&game->draw, tilex, tiley, .texture=D_ImageHandle(&game->draw, asset.tag), .angle=asset.rotation);
break;
}
case G_EDITOR_MODE_PROP: {
World_PropType prop = game->world->propTypes[editor.currentAsset];
D_Rect(&game->draw, editor.cursor.x, editor.cursor.y, .texture=D_ImageHandle(&game->draw, prop.tag), .scale=prop.scale);
break;
}
case G_EDITOR_MODE_HITBOX: {
for(int 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.7),
);
}
break;
}
case G_EDITOR_MODE_POI: {
break;
}
}
}
D_End(&game->draw, frame); D_End(&game->draw, frame);
vk.CmdEndRendering(cmd); vk.CmdEndRendering(cmd);

View File

@@ -13,6 +13,26 @@ struct G_Camera {
Mat4x4FInv proj; Mat4x4FInv proj;
}; };
#define TILE_SIZE 1.0
typedef enum G_EDITOR_MODE G_EDITOR_MODE;
enum G_EDITOR_MODE {
G_EDITOR_MODE_TILE,
G_EDITOR_MODE_PROP,
G_EDITOR_MODE_HITBOX,
G_EDITOR_MODE_POI,
};
typedef struct G_Editor G_Editor;
struct G_Editor {
bool enabled;
U32 currentLevel;
S32 currentAsset;
G_EDITOR_MODE mode;
V2f cursor;
V2f dragStart;
};
typedef struct G_State G_State; typedef struct G_State G_State;
struct G_State { struct G_State {
M_Arena *arena; M_Arena *arena;
@@ -20,6 +40,7 @@ struct G_State {
D_Context draw; D_Context draw;
G_Camera camera; G_Camera camera;
G_Editor editor;
World *world; World *world;
}; };

View File

@@ -34,13 +34,42 @@ void ProcessEvents(SDL_Event *event, World *world)
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->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) { void RenderWorld(World *world, D_Context *draw) {
World_Tile tileTypes[] = {dirt, middlePath, middlePathEdgeTop, middlePathEdgeRight, middlePathEdgeBottom, middlePathEdgeLeft, middlePathCornerTopLeft, middlePathCornerTopRight, middlePathCornerBottomRight, middlePathCornerTurnBottomLeft}; if(world->player.currentArea == WORLD_AREA_OUTSIDE) {
for (int i = 0; i < 4800; i++) for (int i = 0; i < 4800; i++) {
{ D_Rect(
D_Rect(draw, (F32) (i % 96), (F32) (i / 96), .texture = tileTypes[map[i]].tile, .angle = (F32) tileTypes[map[i]].rotation); 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 (int 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++) { for(U32 i = 0; i < world->npcCount; i++) {
NPC npc = world->npcs[i]; NPC npc = world->npcs[i];
@@ -59,23 +88,123 @@ void RenderWorld(World *world, D_Context *draw) {
void SaveWorld(M_Arena *arena, World *world) { void SaveWorld(M_Arena *arena, World *world) {
printf("Saving world\n"); 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);
FS_FileWrite(file, world, sizeof(World)+sizeof(NavMesh), 0); U32 offset = 0;
FS_FileWrite(file, world->navMesh, sizeof(World)+sizeof(NavMesh), sizeof(World)); 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->propTypes, sizeof(World_PropType)*WORLD_PROP_TYPE_MAX, offset);
offset += sizeof(World_PropType)*WORLD_PROP_TYPE_MAX;
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); FS_FileClose(file);
printf("Saved world :)\n"); printf("Saved world :)\n");
} }
World *LoadWorld(M_Arena *arena) { 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); OS_Handle file = FS_FileOpen(S("world.sgdat"), FS_ACCESS_READ);
World *world = M_ArenaPush(arena, World); U32 offset = 0;
NavMesh *navMesh = M_ArenaPush(arena, NavMesh);
FS_FileRead(file, world, sizeof(World), 0); world->tileTypes = M_ArenaPush(arena, World_Tile, .count=WORLD_TILE_TYPE_MAX);
FS_FileRead(file, navMesh, sizeof(NavMesh), sizeof(World)); 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->propCount;
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->hitboxCount;
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); FS_FileClose(file);
world->navMesh = navMesh;
world->arena = arena;
world->player.world = world;
printf("loaded world\n"); printf("loaded world\n");
return world; }
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);
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;
}
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++;
}
} }

View File

@@ -1,17 +1,6 @@
#include "world.h" #include "world.h"
U32 map[] = {
World_Tile dirt = {.rotation=0,.collision=false,.tile=16};//0
World_Tile middlePath = {.rotation=0,.collision=false,.tile=6};//1
World_Tile middlePathEdgeTop = {.rotation=0,.collision=false,.tile=7};//2
World_Tile middlePathEdgeRight = {.rotation=PI_F32/2,.collision=false,.tile=7};//3
World_Tile middlePathEdgeBottom = {.rotation=PI_F32,.collision=false,.tile=7};//4
World_Tile middlePathEdgeLeft = {.rotation=-PI_F32/2,.collision=false,.tile=7};//5
World_Tile middlePathCornerTopLeft = {.rotation=0,.collision=false,.tile=5};//6
World_Tile middlePathCornerTopRight = {.rotation=PI_F32/2,.collision=false,.tile=5};//7
World_Tile middlePathCornerBottomRight = {.rotation=-PI_F32,.collision=false,.tile=5};//8
World_Tile middlePathCornerTurnBottomLeft = {.rotation=-PI_F32/2,.collision=false,.tile=5};//9
int map[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

View File

@@ -6,7 +6,7 @@
#define NAV_MAX_PATH 1024 #define NAV_MAX_PATH 1024
#define NAV_MAX_CONNECTIONS 8 #define NAV_MAX_CONNECTIONS 8
#define NAV_MAX_NODES 4096 #define NAV_MAX_NODES 4800
typedef struct NavNode NavNode; typedef struct NavNode NavNode;

File diff suppressed because it is too large Load Diff

View File

@@ -3,24 +3,38 @@
#include "../core/math.h" #include "../core/math.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
// Areas are which // Areas are which
typedef U32 World_Area; typedef U32 World_Area;
enum World_Area enum World_Area
{ {
WORLD_AREA_OUTSIDE = (1 << 0), WORLD_AREA_OUTSIDE = (1 << 0),
WORLD_AREA_SALOON = (1 << 1), WORLD_AREA_SALOON = (1 << 1),
WORLD_PATH_MIDDLE_EDGE = (1 << 2),
WORLD_PATH_MIDDLE = (1 << 3),
WORLD_PATH_CORNER = (1 << 4),
WORLD_PATH_CORNER_EDGE = (1 << 5),
}; };
typedef struct World_Tile World_Tile; typedef struct World_Tile World_Tile;
struct World_Tile struct World_Tile {
Str8 tag;
F32 rotation;
};
typedef struct World_PropType World_PropType;
struct World_PropType {
Str8 tag;
F32 scale;
};
typedef struct World_Prop World_Prop;
struct World_Prop
{ {
World_Area tile; U32 propType;
double rotation; World_Area area;
bool collision; V2f pos;
}; };
typedef struct World World; typedef struct World World;
@@ -35,6 +49,15 @@ struct World {
NavMesh *navMesh; NavMesh *navMesh;
Random random; Random random;
V2f mouseProjected; V2f mouseProjected;
//// Loaded from world file
World_Tile *tileTypes;
World_PropType *propTypes;
World_Prop *props;
AABB *hitboxes;
U32 *map;
U32 propCount;
U32 hitboxCount;
//// Player //// Player
Player player; Player player;
@@ -58,7 +81,8 @@ function void UpdateNPCs(F32 delta, World *world);
function void UpdateNPC(F32 delta, NPC *npc, World *world); 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 World *LoadWorld(M_Arena *arena); function void LoadWorld(M_Arena *arena, World *world);
function void SaveWorld(M_Arena *arena, World *world); function void SaveWorld(M_Arena *arena, World *world);
function void GenerateNavMesh(M_Arena *arena, World *world);
#endif // LD_GAME_WORLD_H_ #endif // LD_GAME_WORLD_H_

BIN
code/world.sgdat Normal file

Binary file not shown.