diff --git a/assets/npc_front_base_black.png b/assets/npc_front_base_black.png new file mode 100644 index 0000000..c459a8e Binary files /dev/null and b/assets/npc_front_base_black.png differ diff --git a/assets/npc_front_base_white.png b/assets/npc_front_base_white.png new file mode 100644 index 0000000..02ac99a Binary files /dev/null and b/assets/npc_front_base_white.png differ diff --git a/assets/npc_front_eyes_blue.png b/assets/npc_front_eyes_blue.png new file mode 100644 index 0000000..804c9b9 Binary files /dev/null and b/assets/npc_front_eyes_blue.png differ diff --git a/assets/npc_front_eyes_brown.png b/assets/npc_front_eyes_brown.png new file mode 100644 index 0000000..0bf1f02 Binary files /dev/null and b/assets/npc_front_eyes_brown.png differ diff --git a/assets/npc_front_eyes_closed.png b/assets/npc_front_eyes_closed.png new file mode 100644 index 0000000..8232550 Binary files /dev/null and b/assets/npc_front_eyes_closed.png differ diff --git a/assets/npc_front_eyes_green.png b/assets/npc_front_eyes_green.png new file mode 100644 index 0000000..611efef Binary files /dev/null and b/assets/npc_front_eyes_green.png differ diff --git a/assets/npc_front_face_glasses.png b/assets/npc_front_face_glasses.png new file mode 100644 index 0000000..0d0416f Binary files /dev/null and b/assets/npc_front_face_glasses.png differ diff --git a/assets/npc_front_face_moustache.png b/assets/npc_front_face_moustache.png new file mode 100644 index 0000000..212b130 Binary files /dev/null and b/assets/npc_front_face_moustache.png differ diff --git a/assets/npc_front_face_redMask.png b/assets/npc_front_face_redMask.png new file mode 100644 index 0000000..15e9979 Binary files /dev/null and b/assets/npc_front_face_redMask.png differ diff --git a/assets/npc_front_face_whiteMask.png b/assets/npc_front_face_whiteMask.png new file mode 100644 index 0000000..0d64149 Binary files /dev/null and b/assets/npc_front_face_whiteMask.png differ diff --git a/assets/npc_front_hair_blonde.png b/assets/npc_front_hair_blonde.png new file mode 100644 index 0000000..64b7a1e Binary files /dev/null and b/assets/npc_front_hair_blonde.png differ diff --git a/assets/npc_front_hair_brown.png b/assets/npc_front_hair_brown.png new file mode 100644 index 0000000..49e812e Binary files /dev/null and b/assets/npc_front_hair_brown.png differ diff --git a/assets/npc_front_hair_grey.png b/assets/npc_front_hair_grey.png new file mode 100644 index 0000000..af032a5 Binary files /dev/null and b/assets/npc_front_hair_grey.png differ diff --git a/assets/npc_front_hat_brown.png b/assets/npc_front_hat_brown.png new file mode 100644 index 0000000..f812fa7 Binary files /dev/null and b/assets/npc_front_hat_brown.png differ diff --git a/assets/npc_front_hat_white.png b/assets/npc_front_hat_white.png new file mode 100644 index 0000000..0531e4d Binary files /dev/null and b/assets/npc_front_hat_white.png differ diff --git a/assets/npc_front_shirt_brown.png b/assets/npc_front_shirt_brown.png new file mode 100644 index 0000000..489df79 Binary files /dev/null and b/assets/npc_front_shirt_brown.png differ diff --git a/assets/npc_front_shirt_white.png b/assets/npc_front_shirt_white.png new file mode 100644 index 0000000..ef20901 Binary files /dev/null and b/assets/npc_front_shirt_white.png differ diff --git a/assets/npc_front_shoes_brown.png b/assets/npc_front_shoes_brown.png new file mode 100644 index 0000000..18aff93 Binary files /dev/null and b/assets/npc_front_shoes_brown.png differ diff --git a/assets/npc_front_trousers_blue.png b/assets/npc_front_trousers_blue.png new file mode 100644 index 0000000..daf9375 Binary files /dev/null and b/assets/npc_front_trousers_blue.png differ diff --git a/assets/npc_front_trousers_white.png b/assets/npc_front_trousers_white.png new file mode 100644 index 0000000..9c91d1a Binary files /dev/null and b/assets/npc_front_trousers_white.png differ diff --git a/assets/outside_ambience.wav b/assets/outside_ambience.wav new file mode 100644 index 0000000..93fe0ae Binary files /dev/null and b/assets/outside_ambience.wav differ diff --git a/code/core/impl/string.c b/code/core/impl/string.c index 8c9a042..1dc3995 100644 --- a/code/core/impl/string.c +++ b/code/core/impl/string.c @@ -29,6 +29,20 @@ Str8 Str8_WrapZ(U8 *data) { return result; } +#define FNV_OFFSET_BIAS ((U64) 0xCBF29CE484222325) +#define FNV_PRIME ((U64) 0x100000001B3) + +U64 Str8_Hash(Str8 v) { + U64 result = FNV_OFFSET_BIAS; + + for (S64 it = 0; it < v.count; ++it) { + result ^= v.data[it]; + result *= FNV_PRIME; + } + + return result; +} + Str8 Str8_Copy(M_Arena *arena, Str8 s) { Str8 result; result.count = s.count; diff --git a/code/core/macros.h b/code/core/macros.h index 1ff0b56..2da314f 100644 --- a/code/core/macros.h +++ b/code/core/macros.h @@ -36,6 +36,11 @@ #define SLL_PopN(h, next) (((h) != 0) ? (h) = (h)->next : 0) #define SLL_Enqueue(h, t, n) SLL_EnqueueN(h, t, n, next) +#define SLL_EnqueueFront(h, t, n) SLL_EnqueueFrontN(h, t, n, next) +#define SLL_Dequeue(h, t) SLL_DequeueN(h, t, next) + +#define SLL_Push(h, n) SLL_PushN(h, n, next) +#define SLL_Pop(h) (((h) != 0) ? (h) = (h)->next : 0) #define function static #define internal static diff --git a/code/core/string.h b/code/core/string.h index 4adb71e..9eb73ea 100644 --- a/code/core/string.h +++ b/code/core/string.h @@ -11,6 +11,8 @@ function Str8 Str8_Wrap(S64 count, U8 *data); function Str8 Str8_WrapRange(U8 *start, U8 *end); function Str8 Str8_WrapZ(U8 *data); +function U64 Str8_Hash(Str8 v); + function Str8 Str8_Copy(M_Arena *arena, Str8 s); function Str8 Str8_Format(M_Arena *arena, const char *format, ...); diff --git a/code/draw/core.c b/code/draw/core.c index 0f70005..82d287b 100644 --- a/code/draw/core.c +++ b/code/draw/core.c @@ -1,3 +1,59 @@ + +U32 D_ImageHandle(D_Context *draw, Str8 name) { + U32 result = 0; + + U64 hash = Str8_Hash(name); + U64 index = hash & (D_ASSET_HASH_COUNT - 1); + + D_AssetHash *lookup = draw->lookup[index]; + while (lookup != 0) { + if (lookup->hash == hash && Str8_Equal(lookup->value, name, 0)) { + result = lookup->id; + break; + } + + lookup = lookup->next; + } + + return result; +} + + +void D_AnimationInit(D_Animation *a, U32 id, U32 rows, U32 cols, F32 time) { + a->id = id; + + a->rows = rows; + a->cols = cols; + + a->time = 0; + a->frame_time = time; + + a->frame = V2F(1.0f / (F32) cols, 1.0f / (F32) rows); + + a->index = 0; +} + +R2f D_AnimationFrame(D_Animation *a) { + R2f result = { 0 }; + + U32 row = a->index / a->cols; + U32 col = a->index % a->cols; + + result.min = V2F(a->frame.w * col, a->frame.h * row); + result.max = V2F(result.min.x + a->frame.w, result.min.y + a->frame.h); + return result; +} + +void D_AnimationUpdate(D_Animation *a, F32 dt) { + a->time += dt; + if (a->time >= a->frame_time) { + a->time = 0; + a->index += 1; + + if (a->index >= (a->rows * a->cols)) { a->index = 0; } + } +} + void D_Begin(D_Context *draw, Vk_Frame *frame, U32 max_rects) { Vk_Buffer *rbo = &frame->rbo; @@ -127,14 +183,19 @@ void _D_Rect(D_Context *draw, D_RectOpts *opts) { else { Vk_Image *image = &draw->images[opts->texture].image; - if (image->width > image->height) { - rect->w = opts->scale * ((F32) image->width / (F32) image->height); - rect->h = opts->scale; - } - else { - rect->w = opts->scale; - rect->h = opts->scale * ((F32) image->height / (F32) image->width); + F32 width = cast(F32) image->width; + F32 height = cast(F32) image->height; + + if (opts->flags & D_RECT_UV_ASPECT) { + width *= (opts->uv.max.x - opts->uv.min.x); + height *= (opts->uv.max.y - opts->uv.min.y); } + + F32 aspect_w = (width > height) ? (width / height) : 1.0f; + F32 aspect_h = (width > height) ? 1.0f : (height / width); + + rect->w = opts->scale * aspect_w; + rect->h = opts->scale * aspect_h; } draw->n_rects += 1; diff --git a/code/draw/core.h b/code/draw/core.h index a5f7b5b..c4756f6 100644 --- a/code/draw/core.h +++ b/code/draw/core.h @@ -48,8 +48,33 @@ struct D_Rect { StaticAssert(sizeof(D_Rect) == 64); +typedef struct D_Animation D_Animation; +struct D_Animation { + U32 id; + + U32 rows; + U32 cols; + F32 frame_time; + F32 time; + + V2f frame; // size of one frame + + U32 index; +}; + struct G_Camera; +#define D_ASSET_HASH_COUNT 128 + +typedef struct D_AssetHash D_AssetHash; +struct D_AssetHash { + D_AssetHash *next; + + Str8 value; + U64 hash; + U32 id; // texture id +}; + typedef struct D_Context D_Context; struct D_Context { Vk_Buffer *rbo; @@ -73,6 +98,8 @@ struct D_Context { U32 window_width; U32 window_height; + D_AssetHash *lookup[D_ASSET_HASH_COUNT]; + struct G_Camera *camera; }; @@ -80,6 +107,7 @@ typedef U32 D_RectFlags; enum D_RectFlags { 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_UV_ASPECT = (1 << 2), // get the aspect from the uv rect rather than the full image }; typedef struct D_RectOpts D_RectOpts; @@ -111,6 +139,12 @@ struct D_RectOpts { }; }; +function U32 D_ImageHandle(D_Context *draw, Str8 name); + +function void D_AnimationInit(D_Animation *a, U32 id, U32 rows, U32 cols, F32 time); +function R2f D_AnimationFrame(D_Animation *a); +function void D_AnimationUpdate(D_Animation *a, F32 dt); + function void D_Begin(D_Context *draw, Vk_Frame *frame, U32 max_rects); function void D_End(D_Context *draw, Vk_Frame *frame); diff --git a/code/first.c b/code/first.c index ddfc93e..5d45ab4 100644 --- a/code/first.c +++ b/code/first.c @@ -32,7 +32,7 @@ int main(int argc, char **argv) (void)argc; (void)argv; - if (!SDL_Init(SDL_INIT_VIDEO)) + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { printf("[Error] :: Failed to initialise SDL3 (%s)\n", SDL_GetError()); return 1; @@ -45,6 +45,30 @@ int main(int argc, char **argv) return 1; } + SDL_AudioStream *austream; + Str8 audio_data; + M_TempScope(0, 0) { + SDL_AudioSpec spec; + spec.format = SDL_AUDIO_S16LE; + spec.channels = 2; + spec.freq = 44100; + + austream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, 0, 0); + + if (!austream) { + printf("Failed to open audio stream (%s)\n", SDL_GetError()); + } + + Str8 exec = FS_SystemPath(temp.arena, FS_SYSTEM_PATH_EXE); + Str8 path = Sf(temp.arena, "%.*s/assets/outside_ambience.wav", Sv(exec)); + + SDL_AudioSpec wav_spec; + U32 count; + + SDL_LoadWAV((const char *) path.data, &wav_spec, &audio_data.data, &count); + audio_data.count = count; + } + Vk_Setup(window); G_State *game = 0; @@ -52,11 +76,12 @@ int main(int argc, char **argv) M_Arena *arena = M_ArenaAlloc(GB(64), .initial = MB(4)); game = M_ArenaPush(arena, G_State); - game->arena = arena; + game->arena = arena; game->draw.arena = arena; G_ImagesLoad(game); G_PipelinesLoad(game); + G_AudioLoad(game); G_Camera *camera = &game->camera; @@ -113,6 +138,13 @@ int main(int argc, char **argv) world->player.reloadTimer = 0; } + + 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; printf("%zu size in bytes\n", sizeof(TestNavMesh)); @@ -131,6 +163,7 @@ int main(int argc, char **argv) } UpdateWorld(1.0f / 60.0f, game->world); + D_AnimationUpdate(&animation, 1.0f / 250.0f); game->camera.p.x = game->world->player.pos.x; game->camera.p.y = game->world->player.pos.y; @@ -170,10 +203,15 @@ int main(int argc, char **argv) D_Begin(&game->draw, frame, D_MAX_RECTS); - RenderWorld(game->world, &game->draw); - D_Rect(&game->draw, 0.0f, 0.0f, .texture = 1); - D_Rect(&game->draw, -8.0f, 0.0f, .texture = 2, .scale = 2.0f); - D_Rect(&game->draw, 6.0f, 0.0f, .texture = 3); + //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); + + G_WorldDraw(game, game->world); + + R2f aframe = D_AnimationFrame(&animation); + D_Rect(&game->draw, 0, 0, .texture = animation.id, .uv = aframe, .flags = D_RECT_UV_ASPECT); D_End(&game->draw, frame); diff --git a/code/game/core.c b/code/game/core.c index 609555e..91bbbc6 100644 --- a/code/game/core.c +++ b/code/game/core.c @@ -1,5 +1,18 @@ // @Todo: These should move to draw/core.c // +internal void G_AssetNameHash(D_Context *draw, Str8 name, U32 id) { + D_AssetHash *result = M_ArenaPush(draw->arena, D_AssetHash); + + U64 hash = Str8_Hash(name); + U64 index = hash & (D_ASSET_HASH_COUNT - 1); + + result->value = name; + result->hash = hash; + result->id = id; + + SLL_Push(draw->lookup[index], result); +} + void G_ImagesLoad(G_State *game) { M_TempScope(0, 0) { D_Context *draw = &game->draw; @@ -59,6 +72,9 @@ void G_ImagesLoad(G_State *game) { white->name = S("_WHITE"); + // This doesn't _really_ need one because its just zero and always will be zero + G_AssetNameHash(draw, white->name, 0); + white->image.width = 2; white->image.height = 2; white->image.format = VK_FORMAT_R8G8B8A8_SRGB; @@ -71,7 +87,7 @@ void G_ImagesLoad(G_State *game) { // and submitting them in one go. It doesn't really matter for now // - VkImageMemoryBarrier2 transfer = { 0 }; + VkImageMemoryBarrier2 transfer = { 0 }; VkImageMemoryBarrier2 shader_read = { 0 }; transfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; @@ -147,10 +163,11 @@ void G_ImagesLoad(G_State *game) { Assert(offset <= staging->size); - draw->n_images += 1; - image->name = Str8_Copy(game->arena, Str8_RemoveAfterLast(it->basename, '.')); + G_AssetNameHash(draw, image->name, draw->n_images); + + draw->n_images += 1; printf("[Info] :: Loaded %.*s from %.*s\n", Sv(image->name), Sv(it->basename)); image->image.width = w; @@ -290,6 +307,22 @@ void G_PipelinesLoad(G_State *game) { Vk_PipelineCreate(basic); } +void G_AudioLoad(G_State *game) { + (void) game; + + M_TempScope(0, 0) { + Str8 exe_path = FS_SystemPath(temp.arena, FS_SYSTEM_PATH_EXE); + Str8 path = Sf(temp.arena, "%.*s/assets", Sv(exe_path)); + + FS_List assets = FS_PathList(temp.arena, path); + + // @Incomplete: finish this + + for (FS_Entry *it = assets.first; it != 0; it = it->next) { + } + } +} + void G_CalculateCamera(G_Camera *camera, F32 aspect) { Mat4x4FInv proj = M4x4F_Perspective(camera->fov, aspect, camera->nearp, camera->farp); Mat4x4FInv view = M4x4F_CameraView(camera->x, camera->y, camera->z, camera->p); diff --git a/code/game/core.h b/code/game/core.h index af23ec5..163c71a 100644 --- a/code/game/core.h +++ b/code/game/core.h @@ -25,6 +25,7 @@ struct G_State { function void G_ImagesLoad(G_State *game); function void G_PipelinesLoad(G_State *game); +function void G_AudioLoad(G_State *game); function void G_CalculateCamera(G_Camera *camera, F32 aspect); diff --git a/code/game/impl/world.c b/code/game/impl/world.c index 3734e08..92b6855 100644 --- a/code/game/impl/world.c +++ b/code/game/impl/world.c @@ -42,15 +42,17 @@ void G_WorldDraw(G_State *game, World *world) { (void) world; - for (F32 y = -128; y < 128; y += 1.1f) { - for (F32 x = -128; x < 128; x += 1.1f) { + U32 id = D_ImageHandle(&game->draw, S("tile_dirt_0")); + U32 alt_id = D_ImageHandle(&game->draw, S("tile_dirt_1")); + for (F32 y = -128; y < 128; y += 1.0f) { + for (F32 x = -128; x < 128; x += 1.0f) { U32 ux = (U32) x; U32 uy = (U32) y; - U32 tid = 15; + U32 tid = id; if ((ux % 11) == 0 || ((uy % 7) == 0)) { - tid = 16; + tid = alt_id; } D_Rect(draw, x, y, .texture = tid);