Compare commits

..
Author SHA1 Message Date
bulmanator 87d3c9087e Merge branch 'debug'
Fixed some warnings
2025-10-06 19:52:28 +01:00
bulmanator 0c33944721 Merge branch 'debug/world_change' of yibble.dev:bulmanator/ld58 into debug 2025-10-06 19:38:14 +01:00
bulmanator c1fb705f68 Fixed level saving and loading 2025-10-06 19:36:41 +01:00
matt be49003a8d Merge remote-tracking branch 'origin' 2025-10-06 19:32:12 +01:00
matt 7b7f088116 fix: save/load 2025-10-06 19:27:45 +01:00
bulmanator cb10bd10b6 Merge branch 'main' of yibble.dev:bulmanator/ld58 2025-10-06 17:55:32 +01:00
bulmanator a6577f520b Fixed ???
Some files have been renamed
2025-10-06 17:49:08 +01:00
declan d54b4df4c2 player health 2025-10-06 17:45:58 +01:00
declan fcc7adfb22 added badman shooting and reloading 2025-10-06 17:30:49 +01:00
67 changed files with 454 additions and 157 deletions

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

+1
View File
@@ -3,6 +3,7 @@
#define S(x) Str8_Wrap(sizeof(x) - sizeof(*(x)), (U8 *) (x)) #define S(x) Str8_Wrap(sizeof(x) - sizeof(*(x)), (U8 *) (x))
#define Sz(x) Str8_WrapZ((U8 *) (x)) #define Sz(x) Str8_WrapZ((U8 *) (x))
#define Sl(x) { sizeof(x) - sizeof(*(x)), (U8 *) (x) }
#define Sv(x) (int) (x).count, (x).data #define Sv(x) (int) (x).count, (x).data
#define Sf(arena, fmt, ...) Str8_Format(arena, fmt, ##__VA_ARGS__) #define Sf(arena, fmt, ...) Str8_Format(arena, fmt, ##__VA_ARGS__)
+44 -41
View File
@@ -151,6 +151,8 @@ void _D_Rect(D_Context *draw, D_RectOpts *opts) {
rect->texture = opts->texture; rect->texture = opts->texture;
F32 w, h;
rect->x = opts->p.x; rect->x = opts->p.x;
rect->y = opts->p.y; rect->y = opts->p.y;
@@ -177,11 +179,19 @@ void _D_Rect(D_Context *draw, D_RectOpts *opts) {
} }
if (opts->flags & D_RECT_IGNORE_ASPECT) { if (opts->flags & D_RECT_IGNORE_ASPECT) {
rect->w = opts->dim.w; w = opts->dim.w;
rect->h = opts->dim.h; h = opts->dim.h;
} }
else { else {
Vk_Image *image = &draw->images[opts->texture].image; Vk_Image *image = 0;
if (opts->texture >= draw->n_images) {
// @hack: first font texture
//
image = &draw->fonts->image;
}
else {
image = &draw->images[opts->texture].image;
}
F32 width = cast(F32) image->width; F32 width = cast(F32) image->width;
F32 height = cast(F32) image->height; F32 height = cast(F32) image->height;
@@ -191,53 +201,42 @@ void _D_Rect(D_Context *draw, D_RectOpts *opts) {
height *= (opts->uv.max.y - opts->uv.min.y); height *= (opts->uv.max.y - opts->uv.min.y);
} }
F32 aspect_w = (width > height) ? (width / height) : 1.0f; F32 aspect_w = (width > height) ? 1.0f : (width / height);
F32 aspect_h = (width > height) ? 1.0f : (height / width); F32 aspect_h = (width > height) ? (height / width) : 1.0f;
rect->w = opts->scale * aspect_w; w = opts->scale * aspect_w;
rect->h = opts->scale * aspect_h; h = opts->scale * aspect_h;
} }
if (opts->flags & D_RECT_FLIP_X) { w *= -1.0f; }
if (opts->flags & D_RECT_FLIP_Y) { h *= -1.0f; }
rect->w = w;
rect->h = h;
draw->n_rects += 1; draw->n_rects += 1;
} }
} }
void D_Text(D_Context *draw, D_Font *font, Str8 text, F32 x, F32 y) { void D_Text(D_Context *draw, D_Font *font, Str8 text, F32 x, F32 y) {
F32 xoff = x; F32 xoff = x;
local_persist B32 done = 0;
// @Todo: control scale
F32 scale = 1.0f / (font->ascent - font->descent);
for (S64 it = 0; it < text.count; ++it) { for (S64 it = 0; it < text.count; ++it) {
if (text.data[it] >= ' ' && text.data[it] <= '~') { if (text.data[it] >= ' ' && text.data[it] <= '~') {
D_Glyph *glyph = &font->glyphs[text.data[it] - ' ']; D_Glyph *glyph = &font->glyphs[text.data[it] - ' '];
V2f size; F32 image_scale = scale * Max(glyph->dim.w, glyph->dim.h);
size.w = (glyph->box.max.x - glyph->box.min.x); F32 advance = scale * glyph->advance;
size.h = (glyph->box.max.y - glyph->box.min.y);
V2f dim; V2f offset = V2f_Scale(glyph->offset, scale);
F32 scale = 150.0f / (font->ascent - font->descent); D_Rect(draw, xoff + offset.x, y + offset.y, .texture = font->id, .uv = glyph->box, .scale = image_scale, .flags = D_RECT_UV_ASPECT);
xoff += advance;
if (size.w > size.h) {
dim.w = scale * (size.w / size.h);
dim.h = scale;
}
else {
dim.w = scale;
dim.h = scale * (size.h / size.w);
}
// @Hardcode: need font index in font struct
D_Rect(draw, xoff, y, .texture = 0, .c = V4F(0, 1, 1, 1), .dim = dim, .flags = D_RECT_IGNORE_ASPECT);
D_Rect(draw, xoff, y, .texture = draw->n_images, .uv = glyph->box, .dim = dim, .flags = D_RECT_IGNORE_ASPECT);
xoff += (1.05f * dim.w); // glyph->advance; //+ glyph->offset.x;
if (!done) { printf(" %f (%f, %f)", xoff, dim.w, dim.h); }
} }
} }
if (!done) { printf("\n"); }
done = true;
} }
void D_FontLoad(D_Context *draw, Str8 name, F32 size) { void D_FontLoad(D_Context *draw, Str8 name, F32 size) {
@@ -252,7 +251,7 @@ void D_FontLoad(D_Context *draw, Str8 name, F32 size) {
stbtt_fontinfo info = { 0 }; stbtt_fontinfo info = { 0 };
stbtt_InitFont(&info, font_data.data, 0); stbtt_InitFont(&info, font_data.data, 0);
F32 scale = stbtt_ScaleForPixelHeight(&info, 20); F32 scale = stbtt_ScaleForPixelHeight(&info, 256);
U32 w = 512; U32 w = 512;
U32 h = 512; U32 h = 512;
@@ -268,14 +267,12 @@ void D_FontLoad(D_Context *draw, Str8 name, F32 size) {
D_Font *font = M_ArenaPush(draw->arena, D_Font); D_Font *font = M_ArenaPush(draw->arena, D_Font);
font->px = size;
S32 asc, desc, line; S32 asc, desc, line;
stbtt_GetFontVMetrics(&info, &asc, &desc, &line); stbtt_GetFontVMetrics(&info, &asc, &desc, &line);
font->line_advance = cast(F32) line; font->line_advance = cast(F32) (scale * line);
font->ascent = cast(F32) asc; font->ascent = cast(F32) (scale * asc);
font->descent = cast(F32) desc; font->descent = cast(F32) (scale * desc);
font->glyphs = M_ArenaPush(draw->arena, D_Glyph, .count = count); font->glyphs = M_ArenaPush(draw->arena, D_Glyph, .count = count);
@@ -286,10 +283,14 @@ void D_FontLoad(D_Context *draw, Str8 name, F32 size) {
S32 left, width; S32 left, width;
stbtt_GetCodepointHMetrics(&info, ' ' + it, &width, &left); stbtt_GetCodepointHMetrics(&info, ' ' + it, &width, &left);
glyph->box = R2F(V2F(chr->x0 / (F32) w, chr->y0 / (F32) h), V2F(chr->x1 / (F32) w, chr->y1 / (F32) h)); glyph->box.min = V2F(chr->x0 / (F32) w, chr->y0 / (F32) h);
glyph->box.max = V2F(chr->x1 / (F32) w, chr->y1 / (F32) h);
glyph->advance = glyph->box.max.x - glyph->box.min.x; //chr->xadvance * scale; glyph->advance = chr->xadvance;
glyph->offset = V2F(chr->xoff * scale, chr->yoff * scale); glyph->dim.w = cast(F32) (chr->x1 - chr->x0);
glyph->dim.h = cast(F32) (chr->y1 - chr->y0);
glyph->offset.x = (0.5f * glyph->dim.w) + chr->xoff;
glyph->offset.y = (0.5f * glyph->dim.h) + chr->yoff;
} }
Vk_Buffer *staging = &draw->staging; Vk_Buffer *staging = &draw->staging;
@@ -302,6 +303,8 @@ void D_FontLoad(D_Context *draw, Str8 name, F32 size) {
Vk_CommandBuffer *cmds = Vk_CommandBufferPush(); Vk_CommandBuffer *cmds = Vk_CommandBufferPush();
font->id = draw->n_images + draw->n_fonts;
font->image.width = w; font->image.width = w;
font->image.height = h; font->image.height = h;
+7 -2
View File
@@ -6,7 +6,10 @@
typedef struct D_Glyph D_Glyph; typedef struct D_Glyph D_Glyph;
struct D_Glyph { struct D_Glyph {
F32 advance; F32 advance;
V2f offset; V2f offset;
V2f dim;
R2f box; R2f box;
}; };
@@ -14,13 +17,13 @@ typedef struct D_Font D_Font;
struct D_Font { struct D_Font {
D_Font *next; D_Font *next;
F32 px; U32 id;
F32 line_advance; F32 line_advance;
F32 ascent; F32 ascent;
F32 descent; F32 descent;
F32 *kerning; F32 *kerning; // @incomplete: we don't load this
D_Glyph *glyphs; D_Glyph *glyphs;
Vk_Image image; Vk_Image image;
@@ -108,6 +111,8 @@ enum D_RectFlags {
D_RECT_IGNORE_ASPECT = (1 << 0), // by default only width is used as a "dimension" D_RECT_IGNORE_ASPECT = (1 << 0), // by default only width is used as a "dimension"
D_RECT_PER_VERTEX_COLOUR = (1 << 1), // split colours per vertex D_RECT_PER_VERTEX_COLOUR = (1 << 1), // split colours per vertex
D_RECT_UV_ASPECT = (1 << 2), // get the aspect from the uv rect rather than the full image D_RECT_UV_ASPECT = (1 << 2), // get the aspect from the uv rect rather than the full image
D_RECT_FLIP_X = (1 << 3),
D_RECT_FLIP_Y = (1 << 4)
}; };
typedef struct D_RectOpts D_RectOpts; typedef struct D_RectOpts D_RectOpts;
+32 -28
View File
@@ -78,6 +78,8 @@ int main(int argc, char **argv)
game->draw.arena = arena; game->draw.arena = arena;
G_ImagesLoad(game); G_ImagesLoad(game);
//D_FontLoad(&game->draw, S("ubuntu"), 60);
G_PipelinesLoad(game); G_PipelinesLoad(game);
G_AudioLoad(game); G_AudioLoad(game);
@@ -86,7 +88,7 @@ int main(int argc, char **argv)
camera->x = V3F(1, 0, 0); camera->x = V3F(1, 0, 0);
camera->y = V3F(0, 1, 0); camera->y = V3F(0, 1, 0);
camera->z = V3F(0, 0, 1); camera->z = V3F(0, 0, 1);
camera->p = V3F(0, 0, 48); camera->p = V3F(0, 0, 16);
camera->fov = 60.0f; camera->fov = 60.0f;
@@ -95,10 +97,9 @@ int main(int argc, char **argv)
game->draw.camera = camera; game->draw.camera = camera;
World *world = M_ArenaPush(arena, World); World *world = M_ArenaPush(arena, World);
//LoadWorld(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 = 127; world->npcCount = 127;
for(U32 i = 0; i < world->npcCount; i++) { for(U32 i = 0; i < world->npcCount; i++) {
@@ -125,17 +126,19 @@ int main(int argc, char **argv)
badman->waitTime = 0; badman->waitTime = 0;
badman->maxWaitTime = 2; badman->maxWaitTime = 2;
badman->poiCount = 2; badman->poiCount = 2;
badman->shootoutTimer = 1.5;
badman->agroRadius = 600.0;
badman->bullets = 6;
badman->shootDelay = 1;
badman->accuracyRange = 0.25;
badman->reloadTime = 2.5;
badman->reloadTimer = 0;
badman->pointsOfInterest[0] = 937; badman->pointsOfInterest[0] = 937;
badman->pointsOfInterest[1] = 12; badman->pointsOfInterest[1] = 12;
world->npcPOI[0] = 100; world->npcPOI[0] = 100;
world->player.world = world;
world->player.pos.x = 0; PlayerInit(game, &world->player);
world->player.pos.y = 0;
world->player.bulletsLoaded = PLAYER_BULLET_COUNT;
world->player.reloadTimer = 0;
world->player.currentArea = WORLD_AREA_OUTSIDE;
world->map = map;
world->tileTypes = M_ArenaPush(arena, World_Tile, .count=WORLD_TILE_TYPE_MAX); world->tileTypes = M_ArenaPush(arena, World_Tile, .count=WORLD_TILE_TYPE_MAX);
world->tileTypes[0].rotation=0; world->tileTypes[0].rotation=0;
@@ -223,13 +226,6 @@ int main(int argc, char **argv)
game->editor.mode = G_EDITOR_MODE_TILE; game->editor.mode = G_EDITOR_MODE_TILE;
game->editor.currentLevel = WORLD_AREA_OUTSIDE; game->editor.currentLevel = WORLD_AREA_OUTSIDE;
D_Animation animation;
{
U32 id = D_ImageHandle(&game->draw, S("npc_front_base_white"));
D_AnimationInit(&animation, id, 1, 4, 1.0f / 20.0f);
}
bool running = true; bool running = true;
const int width = 1280; const int width = 1280;
@@ -244,6 +240,13 @@ int main(int argc, char **argv)
{ {
running = false; running = false;
} }
else if (e.type == SDL_EVENT_KEY_DOWN) {
Player *player = &game->world->player;
switch (e.key.key) {
case SDLK_R: { PlayerInit(game, player); } break;
}
}
V3f projection = G_CameraUnproject(&game->camera, V2f_Clip( V3f projection = G_CameraUnproject(&game->camera, V2f_Clip(
V2F(e.button.x, e.button.y), V2F(e.button.x, e.button.y),
V2F((F32) width, (F32) height) V2F((F32) width, (F32) height)
@@ -258,8 +261,8 @@ int main(int argc, char **argv)
if(e.type==SDL_EVENT_MOUSE_BUTTON_DOWN && e.button.button == SDL_BUTTON_LEFT) { if(e.type==SDL_EVENT_MOUSE_BUTTON_DOWN && e.button.button == SDL_BUTTON_LEFT) {
switch(game->editor.mode){ switch(game->editor.mode){
case G_EDITOR_MODE_TILE: { case G_EDITOR_MODE_TILE: {
F32 tilex = (S32)(game->editor.cursor.x+TILE_SIZE/2); F32 tilex = (F32) (S32)(game->editor.cursor.x+TILE_SIZE/2);
F32 tiley = (S32)(game->editor.cursor.y+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; game->world->map[(S32)tilex + (S32)tiley * 96] = game->editor.currentAsset;
break; break;
} }
@@ -284,6 +287,7 @@ int main(int argc, char **argv)
Abs(game->editor.cursor.y-game->editor.dragStart.y) Abs(game->editor.cursor.y-game->editor.dragStart.y)
); );
game->world->hitboxCount++; game->world->hitboxCount++;
GenerateNavMesh(game->arena, game->world);
} }
} }
@@ -345,10 +349,10 @@ int main(int argc, char **argv)
if(!game->editor.enabled) { if(!game->editor.enabled) {
UpdateWorld(1.0f / 60.0f, game->world); 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; game->camera.p.x = game->world->player.collision.pos.x;
game->camera.p.y = game->world->player.collision.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);
@@ -388,13 +392,13 @@ int main(int argc, char **argv)
RenderWorld(game->world, &game->draw); RenderWorld(game->world, &game->draw);
R2f aframe = D_AnimationFrame(&animation); //D_Text(&game->draw, game->draw.fonts, S("Small Test"), 0, 0);
D_Rect(&game->draw, 0, 0, .texture = animation.id, .uv = aframe, .flags = D_RECT_UV_ASPECT);
if(game->editor.enabled) { if(game->editor.enabled) {
G_Editor editor = game->editor; G_Editor editor = game->editor;
F32 tilex = floor(editor.cursor.x+TILE_SIZE/2); F32 tilex = cast(F32) floor(editor.cursor.x+TILE_SIZE/2);
F32 tiley = floor(editor.cursor.y+TILE_SIZE/2); F32 tiley = cast(F32) floor(editor.cursor.y+TILE_SIZE/2);
switch(game->editor.mode) { switch(game->editor.mode) {
case G_EDITOR_MODE_TILE: { case G_EDITOR_MODE_TILE: {
World_Tile asset = game->world->tileTypes[editor.currentAsset]; World_Tile asset = game->world->tileTypes[editor.currentAsset];
@@ -407,7 +411,7 @@ int main(int argc, char **argv)
break; break;
} }
case G_EDITOR_MODE_HITBOX: { 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]); V2f centre = AABB_Centre(game->world->hitboxes[i]);
D_Rect( D_Rect(
&game->draw, &game->draw,
@@ -416,7 +420,7 @@ int main(int argc, char **argv)
.texture=0, .texture=0,
.dim=game->world->hitboxes[i].size, .dim=game->world->hitboxes[i].size,
.flags=D_RECT_IGNORE_ASPECT, .flags=D_RECT_IGNORE_ASPECT,
.c=V4F(100,0,0,0.7), .c=V4F(100,0,0,0.7f),
); );
} }
break; break;
+1
View File
@@ -14,5 +14,6 @@ function bool AABB_Collide(AABB a, AABB b);
function bool AABB_Point(AABB a, V2f v); function bool AABB_Point(AABB a, V2f v);
function bool AABB_Slab(V2f origin, V2f point, AABB a); function bool AABB_Slab(V2f origin, V2f point, AABB a);
function V2f AABB_Centre(AABB a); function V2f AABB_Centre(AABB a);
function bool AABB_Circle(F32 rad, V2f radOrigin, AABB a);
#endif // LD_GAME_AABB_H_ #endif // LD_GAME_AABB_H_
+9 -1
View File
@@ -2,11 +2,13 @@
#define LD_GAME_BANDIT_H_ #define LD_GAME_BANDIT_H_
typedef enum BANDIT_ACTION BANDIT_ACTION; typedef enum BANDIT_ACTION BANDIT_ACTION;
enum BANDIT_ACTION { enum BANDIT_ACTION
{
BANDIT_WAITING, BANDIT_WAITING,
BANDIT_WALKING, BANDIT_WALKING,
BANDIT_RUNNING, BANDIT_RUNNING,
BANDIT_SHOOTING, BANDIT_SHOOTING,
BANDIT_SHOOTOUT,
}; };
typedef struct Bandit Bandit; typedef struct Bandit Bandit;
@@ -50,12 +52,18 @@ struct Bandit {
F32 shootDelay; F32 shootDelay;
// After each shot this is set to shootDelay; // After each shot this is set to shootDelay;
F32 shootCooldownTimer; F32 shootCooldownTimer;
// Countdown to shootout
F32 shootoutTimer;
// How long it takes them to reload. // How long it takes them to reload.
F32 reloadTime; F32 reloadTime;
// When gun is empty this is set to reloadTime.
F32 reloadTimer;
// Accuracy, their shots can vary between this angle either side (rads) // Accuracy, their shots can vary between this angle either side (rads)
F32 accuracyRange; F32 accuracyRange;
// A the circle around the bandit where they will trigger the quicktime reaction scene // A the circle around the bandit where they will trigger the quicktime reaction scene
F32 agroRadius; F32 agroRadius;
}; };
function V2f shootTowards(Bandit* bandit, V2f target, Random* r);
#endif // LD_GAME_BANDIT_H_ #endif // LD_GAME_BANDIT_H_
+45 -1
View File
@@ -1,6 +1,7 @@
#if !defined(LD_GAME_CORE_H_) #if !defined(LD_GAME_CORE_H_)
#define LD_GAME_CORE_H_ #define LD_GAME_CORE_H_
#include "world.h"
typedef struct World World;
typedef struct G_Camera G_Camera; typedef struct G_Camera G_Camera;
struct G_Camera { struct G_Camera {
@@ -44,6 +45,48 @@ struct G_State {
World *world; World *world;
}; };
typedef U32 G_OutfitDirection;
enum {
G_OUTFIT_DIR_FRONT = 0,
G_OUTFIT_DIR_SIDE,
G_OUTFIT_DIR_BACK,
G_OUTFIT_DIR_FLIPPED = (1 << 16)
};
typedef union G_OutfitSet G_OutfitSet;
union G_OutfitSet {
struct {
U32 base;
U32 eyes;
U32 face;
U32 hair;
U32 hat;
U32 shirt;
U32 shoes;
U32 trousers;
};
U32 e[8];
};
typedef struct G_Outfit G_Outfit;
struct G_Outfit {
D_Animation state; // .id in here isn't used for drawing
G_OutfitDirection dir;
union {
struct {
G_OutfitSet front;
G_OutfitSet side;
G_OutfitSet back;
};
G_OutfitSet e[3];
};
};
function void G_ImagesLoad(G_State *game); function void G_ImagesLoad(G_State *game);
function void G_PipelinesLoad(G_State *game); function void G_PipelinesLoad(G_State *game);
function void G_AudioLoad(G_State *game); function void G_AudioLoad(G_State *game);
@@ -56,6 +99,7 @@ function V3f G_CameraUnproject(G_Camera *camera, V2f clip);
function R3f G_CameraBounds(G_Camera *camera); function R3f G_CameraBounds(G_Camera *camera);
#include "world.h"
#include "aabb.h" #include "aabb.h"
#include "player.h" #include "player.h"
#include "nav.h" #include "nav.h"
+8
View File
@@ -38,3 +38,11 @@ bool AABB_Slab(V2f origin, V2f point, AABB a)
V2f AABB_Centre(AABB a) { V2f AABB_Centre(AABB a) {
return V2F(a.pos.x + a.size.x/2, a.pos.y + a.size.y/2); return V2F(a.pos.x + a.size.x/2, a.pos.y + a.size.y/2);
} }
bool AABB_Circle(F32 rad, V2f radOrigin, AABB a)
{
V2f aCentre = AABB_Centre(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;
}
+42 -2
View File
@@ -1,13 +1,27 @@
#include "game/world.h" #include "game/world.h"
#include "game/bandit.h" #include "game/bandit.h"
V2f shootTowards(Bandit *bandit, V2f target, Random* r)
{
V2f shooterV2 = bandit->collision.pos;
F32 randX = Random_F32(r, -bandit->accuracyRange, bandit->accuracyRange);
F32 randY = Random_F32(r, -bandit->accuracyRange, bandit->accuracyRange);
return V2F(shooterV2.x + (target.x - shooterV2.x) * (1 + randX), shooterV2.x + (target.y - shooterV2.y) * (1 + randY));
}
void UpdateBandit(F32 delta, Bandit *bandit, World *world) { void UpdateBandit(F32 delta, Bandit *bandit, World *world) {
if ( if (
world->player.controls.shot && AABB_Slab(world->player.pos, world->player.shotPos, bandit->collision) && bandit->currentArea == world->player.currentArea) world->player.controls.shot && AABB_Slab(world->player.collision.pos, world->player.shotPos, bandit->collision) && bandit->currentArea == world->player.currentArea)
{ {
printf("You shot the bandit %*.s\n", Sv(bandit->name)); printf("You shot the bandit %*.s\n", Sv(bandit->name));
bandit->health--; bandit->health--;
} }
if (AABB_Circle(bandit->agroRadius, AABB_Centre(bandit->collision), world->player.collision) && !(bandit->mode == BANDIT_SHOOTING || bandit->mode == BANDIT_SHOOTOUT))
{
printf("begin shootout");
// shootout time o.o
bandit->mode = BANDIT_SHOOTOUT;
}
switch (bandit->mode) { switch (bandit->mode) {
case BANDIT_WAITING: case BANDIT_WAITING:
bandit->waitTime+=delta; bandit->waitTime+=delta;
@@ -41,7 +55,33 @@ void UpdateBandit(F32 delta, Bandit *bandit, World *world) {
bandit->collision.pos.x = cNav.pos.x * (1 - bandit->walkTimer/NPC_SPEED) + tNav.pos.x * bandit->walkTimer/NPC_SPEED; bandit->collision.pos.x = cNav.pos.x * (1 - bandit->walkTimer/NPC_SPEED) + tNav.pos.x * bandit->walkTimer/NPC_SPEED;
bandit->collision.pos.y = cNav.pos.y * (1 - bandit->walkTimer/NPC_SPEED) + tNav.pos.y * bandit->walkTimer/NPC_SPEED; bandit->collision.pos.y = cNav.pos.y * (1 - bandit->walkTimer/NPC_SPEED) + tNav.pos.y * bandit->walkTimer/NPC_SPEED;
break; break;
// TODO Shooting case BANDIT_SHOOTOUT:
bandit->shootoutTimer-=delta;
if(bandit->shootoutTimer < 0){
bandit->mode=BANDIT_SHOOTING;
}
break;
case BANDIT_SHOOTING:
bandit->shootCooldownTimer -= delta;
bandit->reloadTimer -= delta;
if (bandit->shootCooldownTimer < 0 && bandit->reloadTimer < 0)
{
printf("shoot at player");
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");
world->player.health--;
}
if(bandit->bullets == 0){
printf("enemy reload");
bandit->bullets = 6;
bandit->reloadTimer = bandit->reloadTime;
}
}
break;
// TODO Running away // TODO Running away
} }
} }
+109 -2
View File
@@ -3,6 +3,80 @@
#include <SDL3/SDL_keycode.h> #include <SDL3/SDL_keycode.h>
#include <stdio.h> #include <stdio.h>
// @Todo: move/extern these so the npc/bandit can use them
//
#define G_OUTFIT_COMPONENT_COUNT 8
global_var Str8 __outfit_names[] = {
Sl("npc_%s_base_%d"),
Sl("npc_%s_eyes_%d"),
Sl("npc_%s_face_%d"),
Sl("npc_%s_hair_%d"),
Sl("npc_%s_hat_%d"),
Sl("npc_%s_shirt_%d"),
Sl("npc_%s_shoes_%d"),
Sl("npc_%s_trousers_%d")
};
global_var U32 __outfit_counts[] = {
2, // base
3, // eyes
5, // face
4, // hair
3, // hat
2, // shirt
1, // shoes
2 // trousers
};
global_var U32 __outfit_back_counts[] = {
2, // base
0, // eyes
3, // face
4, // hair
3, // hat
2, // shirt
1, // shoes
2 // trousers
};
StaticAssert(ArraySize(__outfit_names) == ArraySize(__outfit_counts));
#define OUTFIT_IMG(dir, n) D_ImageHandle(&game->draw, Sf(temp.arena, (const char *) __outfit_names[it].data, #dir, n))
void PlayerInit(G_State *game, Player *player) {
World *world = game->world;
player->world = world;
player->bulletsLoaded = PLAYER_BULLET_COUNT;
player->currentArea = WORLD_AREA_OUTSIDE;
player->health = 3;
player->collision.size.x = 1;
player->collision.size.x = 2;
G_Outfit *outfit = &player->outfit;
D_AnimationInit(&outfit->state, 0, 1, 4, 1.0f / 6.0f);
M_TempScope(0, 0) {
for (U32 it = 0; it < G_OUTFIT_COMPONENT_COUNT; ++it) {
U32 idx = Random_Next(&world->random) % __outfit_counts[it];
// We just allow face, hair and hat to default to 0 meaning the player doesn't have one
if (idx != 0 || it < 2 || it > 4) {
outfit->front.e[it] = OUTFIT_IMG(front, idx);
outfit->side.e[it] = OUTFIT_IMG(side, idx);
if ((idx + 1) <= __outfit_counts[it]) {
outfit->back.e[it] = OUTFIT_IMG(back, idx);
}
}
}
}
}
void PlayerInput(SDL_Event *event, Player *player) void PlayerInput(SDL_Event *event, Player *player)
{ {
SDL_KeyboardEvent key = event->key; SDL_KeyboardEvent key = event->key;
@@ -53,18 +127,34 @@ void PlayerInput(SDL_Event *event, Player *player)
void PlayerUpdate(F32 delta, Player *player) { void PlayerUpdate(F32 delta, Player *player) {
player->controls.shot = false; player->controls.shot = false;
V2f dir = V2F(0, 0); V2f dir = V2F(0, 0);
if(player->health == 0){
printf("dead :(");
player->health = 3;
}
if(player->controls.upDown) { if(player->controls.upDown) {
dir.y -= 1; dir.y -= 1;
player->outfit.dir = G_OUTFIT_DIR_BACK;
} }
if(player->controls.downDown) { if(player->controls.downDown) {
dir.y += 1; dir.y += 1;
player->outfit.dir = G_OUTFIT_DIR_FRONT;
} }
if(player->controls.leftDown) { if(player->controls.leftDown) {
dir.x -= 1; dir.x -= 1;
player->outfit.dir = G_OUTFIT_DIR_SIDE | G_OUTFIT_DIR_FLIPPED;
} }
if(player->controls.rightDown) { if(player->controls.rightDown) {
dir.x += 1; dir.x += 1;
player->outfit.dir = G_OUTFIT_DIR_SIDE;
} }
if (dir.x != 0 || dir.y != 0) {
D_AnimationUpdate(&player->outfit.state, delta);
}
else {
player->outfit.state.index = 0;
}
if(player->reloadTimer > 0) { if(player->reloadTimer > 0) {
player->reloadTimer-=delta; player->reloadTimer-=delta;
if(player->reloadTimer <= 0) { if(player->reloadTimer <= 0) {
@@ -73,6 +163,23 @@ void PlayerUpdate(F32 delta, Player *player) {
} }
} }
dir = V2f_Scale(NormaliseV2F(dir), PLAYER_SPEED*delta); dir = V2f_Scale(NormaliseV2F(dir), PLAYER_SPEED*delta);
player->pos.x += dir.x; player->collision.pos.x += dir.x;
player->pos.y += dir.y; player->collision.pos.y += dir.y;
}
void PlayerDraw(D_Context *draw, Player *player) {
G_Outfit *outfit = &player->outfit;
R2f pframe = D_AnimationFrame(&outfit->state);
for (U32 it = 0; it < G_OUTFIT_COMPONENT_COUNT; ++it) {
U32 flipped = (outfit->dir & G_OUTFIT_DIR_FLIPPED) != 0;
U32 dir = (outfit->dir & ~G_OUTFIT_DIR_FLIPPED);
U32 tid = outfit->e[dir].e[it];
if (tid != 0) {
U32 flags = D_RECT_UV_ASPECT | (flipped ? D_RECT_FLIP_X : 0);
D_Rect(draw, player->collision.pos.x, player->collision.pos.y, .texture = tid, .uv = pframe, .flags = flags);
}
}
} }
+147 -78
View File
@@ -9,6 +9,9 @@
void UpdateWorld(F32 delta, World *world) void UpdateWorld(F32 delta, World *world)
{ {
if(world->bandit.mode == BANDIT_SHOOTOUT){
delta = delta/4;
}
UpdateBandit(delta, &world->bandit, world); UpdateBandit(delta, &world->bandit, world);
UpdateNPCs(delta, world); UpdateNPCs(delta, world);
PlayerUpdate(delta, &world->player); PlayerUpdate(delta, &world->player);
@@ -21,7 +24,7 @@ void UpdateNPCs(F32 delta, World *world)
NPC *npc = &world->npcs[i]; NPC *npc = &world->npcs[i];
UpdateNPC(delta, npc, world); UpdateNPC(delta, npc, world);
if ( if (
world->player.controls.shot && AABB_Slab(world->player.pos, world->player.shotPos, npc->collision) && npc->currentArea == world->player.currentArea) 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)); printf("You shot %*.s\n", Sv(world->npcs[i].name));
} }
@@ -32,7 +35,7 @@ void ProcessEvents(SDL_Event *event, World *world)
{ {
PlayerInput(event, &world->player); PlayerInput(event, &world->player);
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);
} }
if(event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_F6){ if(event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_F6){
LoadWorld(world->arena, world); LoadWorld(world->arena, world);
@@ -50,7 +53,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) { if(world->props[i].area == world->player.currentArea) {
D_Rect( D_Rect(
draw, draw,
@@ -61,7 +64,7 @@ void RenderWorld(World *world, D_Context *draw) {
); );
} }
} }
for (int i = 0; i < world->navMesh->nodeCount; i++) { for (U32 i = 0; i < world->navMesh->nodeCount; i++) {
NavNode n = world->navMesh->nodes[i]; NavNode n = world->navMesh->nodes[i];
D_Rect( D_Rect(
draw, draw,
@@ -82,98 +85,148 @@ void RenderWorld(World *world, D_Context *draw) {
V2f drawPos = AABB_Centre(world->bandit.collision); V2f drawPos = AABB_Centre(world->bandit.collision);
D_Rect(draw, drawPos.x, drawPos.y, .texture = 9); D_Rect(draw, drawPos.x, drawPos.y, .texture = 9);
} }
D_Rect(draw, world->player.pos.x, world->player.pos.y, .texture = 1);
PlayerDraw(draw, &world->player);
} }
void SaveWorld(M_Arena *arena, World *world) { #define WRITE(v) FS_FileWrite(file, &(v), sizeof(v), offset); offset += sizeof(v)
printf("Saving world\n"); #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); OS_Handle file = FS_FileOpen(S("world.sgdat"), FS_ACCESS_WRITE);
U32 offset = 0; U64 offset = 0;
for(int i = 0; i < WORLD_TILE_TYPE_MAX; i++) {
FS_FileWrite(file, &world->tileTypes[i].tag.count, sizeof(S64), offset); for (U32 i = 0; i < WORLD_TILE_TYPE_MAX; i++) {
offset += sizeof(S64); World_Tile *tile = &world->tileTypes[i];
FS_FileWrite(file, world->tileTypes[i].tag.data, world->tileTypes[i].tag.count, offset);
offset += sizeof(U8) * world->tileTypes[i].tag.count; WRITE(tile->tag.count);
FS_FileWrite(file, &world->tileTypes[i].rotation, sizeof(F32), offset); WRITEN(tile->tag.data, tile->tag.count);
offset += sizeof(F32); WRITE(tile->rotation);
}
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); for (U32 i = 0; i < WORLD_PROP_TYPE_MAX; i++) {
offset += sizeof(World_PropType)*WORLD_PROP_TYPE_MAX; World_PropType *type = &world->propTypes[i];
FS_FileWrite(file, &world->propCount, sizeof(U32), offset); WRITE(type->tag.count);
offset += sizeof(U32); WRITEN(type->tag.data, type->tag.count);
WRITE(type->scale);
}
FS_FileWrite(file, world->props, sizeof(World_Prop)*WORLD_PROP_MAX, offset); WRITE(world->propCount);
offset += sizeof(World_Prop)*WORLD_PROP_MAX; WRITEN(world->props, WORLD_PROP_MAX);
FS_FileWrite(file, &world->hitboxCount, sizeof(U32), offset); WRITE(world->hitboxCount);
offset += sizeof(U32); WRITEN(world->hitboxes, WORLD_HITBOX_MAX);
FS_FileWrite(file, world->hitboxes, sizeof(AABB)*WORLD_HITBOX_MAX, offset); WRITEN(world->map, WORLD_MAP_MAX);
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("--- World Saved ---\n");
} }
void LoadWorld(M_Arena *arena, World *world) { 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);
U32 offset = 0;
world->tileTypes = M_ArenaPush(arena, World_Tile, .count=WORLD_TILE_TYPE_MAX); M_TempScope(0, 0) {
for(int i = 0; i < WORLD_TILE_TYPE_MAX; i++) { Str8 data = FS_ReadEntireFile(temp.arena, S("world.sgdat"));
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); U8 *base = data.data;
offset += sizeof(U32);
world->props = M_ArenaPush(arena, World_Prop, .count=WORLD_PROP_MAX); // Load tile types
FS_FileRead(file, world->props, sizeof(World_Prop)*WORLD_PROP_MAX, offset); //
offset += sizeof(World_Prop)*world->propCount; 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); Str8 name;
offset += sizeof(U32); name.count = *(S64 *) base;
name.data = base + 8;
world->hitboxes = M_ArenaPush(arena, AABB, .count=WORLD_HITBOX_MAX); base += 8;
FS_FileRead(file, world->hitboxes, sizeof(AABB)*WORLD_HITBOX_MAX, offset); base += name.count;
offset += sizeof(AABB)*world->hitboxCount;
world->map = M_ArenaPush(arena, U32, .count=WORLD_MAP_MAX); if (name.count != 0) {
FS_FileRead(file, world->map, sizeof(U32)*WORLD_MAP_MAX, offset); // Means we likely got a vaild tag
offset += sizeof(U32)*WORLD_MAP_MAX; type->tag = Str8_Copy(arena, name);
type->rotation = *(F32 *) base;
}
FS_FileClose(file); base += 4;
printf("loaded world\n"); }
// 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");
}
} }
void GenerateNavMesh(M_Arena *arena, World *world) { void GenerateNavMesh(M_Arena *arena, World *world) {
@@ -182,8 +235,16 @@ void GenerateNavMesh(M_Arena *arena, World *world) {
for(int i = 0; i < WORLD_MAP_MAX; i++) { for(int i = 0; i < WORLD_MAP_MAX; i++) {
U32 x = (i % 96); U32 x = (i % 96);
U32 y = (i / 96); U32 y = (i / 96);
world->navMesh->nodes[world->navMesh->nodeCount].pos.x = x; bool skip = false;
world->navMesh->nodes[world->navMesh->nodeCount].pos.y = y; for(U32 hi = 0; hi < world->hitboxCount; hi++) {
if(AABB_Point(world->hitboxes[hi], V2F((F32) x, (F32) y))) {
skip = true;
break;
}
}
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; U32 cost = 20;
if(Str8_Equal(world->tileTypes[world->map[i]].tag, S("path_middle"), STR8_EQUAL_IGNORE_CASE)) { if(Str8_Equal(world->tileTypes[world->map[i]].tag, S("path_middle"), STR8_EQUAL_IGNORE_CASE)) {
cost = 10; cost = 10;
@@ -198,10 +259,18 @@ void GenerateNavMesh(M_Arena *arena, World *world) {
if(y+ny < 0 || y+ny > 49) { if(y+ny < 0 || y+ny > 49) {
continue; continue;
} }
// 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)))) {
skip = true;
break;
}
}
if(skip) {continue;}
U32 index = x+nx + (y+ny)*96; U32 index = x+nx + (y+ny)*96;
U32 nCount = world->navMesh->nodeCount; 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].NodeIndex = index;
world->navMesh->nodes[nCount].connections[world->navMesh->nodes[nCount].connectionCount].Cost = cost; world->navMesh->nodes[nCount].connections[world->navMesh->nodes[nCount].connectionCount].Cost = cast(F32) cost;
world->navMesh->nodes[nCount].connectionCount++; world->navMesh->nodes[nCount].connectionCount++;
} }
} }
+8 -1
View File
@@ -5,6 +5,7 @@
#include "../core/macros.h" #include "../core/macros.h"
#include <SDL3/SDL_events.h> #include <SDL3/SDL_events.h>
#include "aabb.h"
#define PLAYER_SPEED 10.0f #define PLAYER_SPEED 10.0f
#define PLAYER_RELOAD_TIME 1.5f #define PLAYER_RELOAD_TIME 1.5f
@@ -23,15 +24,21 @@ typedef struct Player Player;
struct Player struct Player
{ {
World *world; World *world;
V2f pos; AABB collision;
World_Area currentArea; World_Area currentArea;
U32 bulletsLoaded; U32 bulletsLoaded;
ControlState controls; ControlState controls;
V2f shotPos; V2f shotPos;
G_Outfit outfit;
U32 health;
F32 reloadTimer; F32 reloadTimer;
}; };
function void PlayerInit(G_State *game, Player *player);
function void PlayerDraw(D_Context *draw, Player *player);
function void PlayerInput(SDL_Event *event, Player *player); function void PlayerInput(SDL_Event *event, Player *player);
function void PlayerUpdate(F32 delta, Player *player); function void PlayerUpdate(F32 delta, Player *player);
+1 -1
View File
@@ -82,7 +82,7 @@ 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 void LoadWorld(M_Arena *arena, World *world); function void LoadWorld(M_Arena *arena, World *world);
function void SaveWorld(M_Arena *arena, World *world); function void SaveWorld(World *world);
function void GenerateNavMesh(M_Arena *arena, World *world); function void GenerateNavMesh(M_Arena *arena, World *world);
#endif // LD_GAME_WORLD_H_ #endif // LD_GAME_WORLD_H_
BIN
View File
Binary file not shown.