diff --git a/assets/npc_back_base_0.png b/assets/npc_back_base_0.png new file mode 100644 index 0000000..9d0cab3 Binary files /dev/null and b/assets/npc_back_base_0.png differ diff --git a/assets/npc_back_base_1.png b/assets/npc_back_base_1.png new file mode 100644 index 0000000..10218cd Binary files /dev/null and b/assets/npc_back_base_1.png differ diff --git a/assets/npc_back_face_1.png b/assets/npc_back_face_1.png new file mode 100644 index 0000000..a1a9d87 Binary files /dev/null and b/assets/npc_back_face_1.png differ diff --git a/assets/npc_back_face_2.png b/assets/npc_back_face_2.png new file mode 100644 index 0000000..7306e8b Binary files /dev/null and b/assets/npc_back_face_2.png differ diff --git a/assets/npc_back_hair_1.png b/assets/npc_back_hair_1.png new file mode 100644 index 0000000..d8a7155 Binary files /dev/null and b/assets/npc_back_hair_1.png differ diff --git a/assets/npc_back_hair_2.png b/assets/npc_back_hair_2.png new file mode 100644 index 0000000..0a0290c Binary files /dev/null and b/assets/npc_back_hair_2.png differ diff --git a/assets/npc_back_hair_3.png b/assets/npc_back_hair_3.png new file mode 100644 index 0000000..75b2604 Binary files /dev/null and b/assets/npc_back_hair_3.png differ diff --git a/assets/npc_back_hat_1.png b/assets/npc_back_hat_1.png new file mode 100644 index 0000000..d7f2542 Binary files /dev/null and b/assets/npc_back_hat_1.png differ diff --git a/assets/npc_back_hat_2.png b/assets/npc_back_hat_2.png new file mode 100644 index 0000000..a46ddee Binary files /dev/null and b/assets/npc_back_hat_2.png differ diff --git a/assets/npc_back_shirt_0.png b/assets/npc_back_shirt_0.png new file mode 100644 index 0000000..9b22f72 Binary files /dev/null and b/assets/npc_back_shirt_0.png differ diff --git a/assets/npc_back_shirt_1.png b/assets/npc_back_shirt_1.png new file mode 100644 index 0000000..c2a8348 Binary files /dev/null and b/assets/npc_back_shirt_1.png differ diff --git a/assets/npc_back_shoes_0.png b/assets/npc_back_shoes_0.png new file mode 100644 index 0000000..b336446 Binary files /dev/null and b/assets/npc_back_shoes_0.png differ diff --git a/assets/npc_back_trousers_0.png b/assets/npc_back_trousers_0.png new file mode 100644 index 0000000..83662f6 Binary files /dev/null and b/assets/npc_back_trousers_0.png differ diff --git a/assets/npc_back_trousers_1.png b/assets/npc_back_trousers_1.png new file mode 100644 index 0000000..8dc87f4 Binary files /dev/null and b/assets/npc_back_trousers_1.png differ diff --git a/assets/npc_front_base_black.png b/assets/npc_front_base_0.png similarity index 100% rename from assets/npc_front_base_black.png rename to assets/npc_front_base_0.png diff --git a/assets/npc_front_base_white.png b/assets/npc_front_base_1.png similarity index 100% rename from assets/npc_front_base_white.png rename to assets/npc_front_base_1.png diff --git a/assets/npc_front_eyes_blue.png b/assets/npc_front_eyes_0.png similarity index 100% rename from assets/npc_front_eyes_blue.png rename to assets/npc_front_eyes_0.png diff --git a/assets/npc_front_eyes_brown.png b/assets/npc_front_eyes_1.png similarity index 100% rename from assets/npc_front_eyes_brown.png rename to assets/npc_front_eyes_1.png diff --git a/assets/npc_front_eyes_green.png b/assets/npc_front_eyes_2.png similarity index 100% rename from assets/npc_front_eyes_green.png rename to assets/npc_front_eyes_2.png diff --git a/assets/npc_front_face_redMask.png b/assets/npc_front_face_1.png similarity index 100% rename from assets/npc_front_face_redMask.png rename to assets/npc_front_face_1.png diff --git a/assets/npc_front_face_whiteMask.png b/assets/npc_front_face_2.png similarity index 100% rename from assets/npc_front_face_whiteMask.png rename to assets/npc_front_face_2.png diff --git a/assets/npc_front_face_glasses.png b/assets/npc_front_face_3.png similarity index 100% rename from assets/npc_front_face_glasses.png rename to assets/npc_front_face_3.png diff --git a/assets/npc_front_face_moustache.png b/assets/npc_front_face_4.png similarity index 100% rename from assets/npc_front_face_moustache.png rename to assets/npc_front_face_4.png diff --git a/assets/npc_front_hair_blonde.png b/assets/npc_front_hair_1.png similarity index 100% rename from assets/npc_front_hair_blonde.png rename to assets/npc_front_hair_1.png diff --git a/assets/npc_front_hair_brown.png b/assets/npc_front_hair_2.png similarity index 100% rename from assets/npc_front_hair_brown.png rename to assets/npc_front_hair_2.png diff --git a/assets/npc_front_hair_grey.png b/assets/npc_front_hair_3.png similarity index 100% rename from assets/npc_front_hair_grey.png rename to assets/npc_front_hair_3.png diff --git a/assets/npc_front_hat_brown.png b/assets/npc_front_hat_1.png similarity index 100% rename from assets/npc_front_hat_brown.png rename to assets/npc_front_hat_1.png diff --git a/assets/npc_front_hat_white.png b/assets/npc_front_hat_2.png similarity index 100% rename from assets/npc_front_hat_white.png rename to assets/npc_front_hat_2.png diff --git a/assets/npc_front_shirt_brown.png b/assets/npc_front_shirt_0.png similarity index 100% rename from assets/npc_front_shirt_brown.png rename to assets/npc_front_shirt_0.png diff --git a/assets/npc_front_shirt_white.png b/assets/npc_front_shirt_1.png similarity index 100% rename from assets/npc_front_shirt_white.png rename to assets/npc_front_shirt_1.png diff --git a/assets/npc_front_shoes_brown.png b/assets/npc_front_shoes_0.png similarity index 100% rename from assets/npc_front_shoes_brown.png rename to assets/npc_front_shoes_0.png diff --git a/assets/npc_front_trousers_blue.png b/assets/npc_front_trousers_0.png similarity index 100% rename from assets/npc_front_trousers_blue.png rename to assets/npc_front_trousers_0.png diff --git a/assets/npc_front_trousers_white.png b/assets/npc_front_trousers_1.png similarity index 100% rename from assets/npc_front_trousers_white.png rename to assets/npc_front_trousers_1.png diff --git a/assets/npc_side_base_0.png b/assets/npc_side_base_0.png new file mode 100644 index 0000000..e47df36 Binary files /dev/null and b/assets/npc_side_base_0.png differ diff --git a/assets/npc_side_base_1.png b/assets/npc_side_base_1.png new file mode 100644 index 0000000..927b80c Binary files /dev/null and b/assets/npc_side_base_1.png differ diff --git a/assets/npc_side_eyes_0.png b/assets/npc_side_eyes_0.png new file mode 100644 index 0000000..6534e3d Binary files /dev/null and b/assets/npc_side_eyes_0.png differ diff --git a/assets/npc_side_eyes_1.png b/assets/npc_side_eyes_1.png new file mode 100644 index 0000000..401e570 Binary files /dev/null and b/assets/npc_side_eyes_1.png differ diff --git a/assets/npc_side_eyes_2.png b/assets/npc_side_eyes_2.png new file mode 100644 index 0000000..c433cd0 Binary files /dev/null and b/assets/npc_side_eyes_2.png differ diff --git a/assets/npc_side_eyes_closed.png b/assets/npc_side_eyes_closed.png new file mode 100644 index 0000000..b3634d4 Binary files /dev/null and b/assets/npc_side_eyes_closed.png differ diff --git a/assets/npc_side_face_1.png b/assets/npc_side_face_1.png new file mode 100644 index 0000000..27b2ebe Binary files /dev/null and b/assets/npc_side_face_1.png differ diff --git a/assets/npc_side_face_2.png b/assets/npc_side_face_2.png new file mode 100644 index 0000000..15eedc4 Binary files /dev/null and b/assets/npc_side_face_2.png differ diff --git a/assets/npc_side_face_3.png b/assets/npc_side_face_3.png new file mode 100644 index 0000000..83295ba Binary files /dev/null and b/assets/npc_side_face_3.png differ diff --git a/assets/npc_side_face_4.png b/assets/npc_side_face_4.png new file mode 100644 index 0000000..8802f19 Binary files /dev/null and b/assets/npc_side_face_4.png differ diff --git a/assets/npc_side_hair_1.png b/assets/npc_side_hair_1.png new file mode 100644 index 0000000..78a216d Binary files /dev/null and b/assets/npc_side_hair_1.png differ diff --git a/assets/npc_side_hair_2.png b/assets/npc_side_hair_2.png new file mode 100644 index 0000000..1fc4c88 Binary files /dev/null and b/assets/npc_side_hair_2.png differ diff --git a/assets/npc_side_hair_3.png b/assets/npc_side_hair_3.png new file mode 100644 index 0000000..9041ffe Binary files /dev/null and b/assets/npc_side_hair_3.png differ diff --git a/assets/npc_side_hat_1.png b/assets/npc_side_hat_1.png new file mode 100644 index 0000000..c772643 Binary files /dev/null and b/assets/npc_side_hat_1.png differ diff --git a/assets/npc_side_hat_2.png b/assets/npc_side_hat_2.png new file mode 100644 index 0000000..693f857 Binary files /dev/null and b/assets/npc_side_hat_2.png differ diff --git a/assets/npc_side_shirt_0.png b/assets/npc_side_shirt_0.png new file mode 100644 index 0000000..d3abdcb Binary files /dev/null and b/assets/npc_side_shirt_0.png differ diff --git a/assets/npc_side_shirt_1.png b/assets/npc_side_shirt_1.png new file mode 100644 index 0000000..1913258 Binary files /dev/null and b/assets/npc_side_shirt_1.png differ diff --git a/assets/npc_side_shoes_0.png b/assets/npc_side_shoes_0.png new file mode 100644 index 0000000..7878df0 Binary files /dev/null and b/assets/npc_side_shoes_0.png differ diff --git a/assets/npc_side_trousers_0.png b/assets/npc_side_trousers_0.png new file mode 100644 index 0000000..da162cf Binary files /dev/null and b/assets/npc_side_trousers_0.png differ diff --git a/assets/npc_side_trousers_1.png b/assets/npc_side_trousers_1.png new file mode 100644 index 0000000..b5541fa Binary files /dev/null and b/assets/npc_side_trousers_1.png differ diff --git a/code/core/string.h b/code/core/string.h index 9eb73ea..14e813f 100644 --- a/code/core/string.h +++ b/code/core/string.h @@ -3,6 +3,7 @@ #define S(x) Str8_Wrap(sizeof(x) - sizeof(*(x)), (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 Sf(arena, fmt, ...) Str8_Format(arena, fmt, ##__VA_ARGS__) diff --git a/code/draw/core.c b/code/draw/core.c index 82d287b..e839afa 100644 --- a/code/draw/core.c +++ b/code/draw/core.c @@ -151,6 +151,8 @@ void _D_Rect(D_Context *draw, D_RectOpts *opts) { rect->texture = opts->texture; + F32 w, h; + rect->x = opts->p.x; 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) { - rect->w = opts->dim.w; - rect->h = opts->dim.h; + w = opts->dim.w; + h = opts->dim.h; } 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 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); } - F32 aspect_w = (width > height) ? (width / height) : 1.0f; - F32 aspect_h = (width > height) ? 1.0f : (height / width); + F32 aspect_w = (width > height) ? 1.0f : (width / height); + F32 aspect_h = (width > height) ? (height / width) : 1.0f; - rect->w = opts->scale * aspect_w; - rect->h = opts->scale * aspect_h; + w = opts->scale * aspect_w; + 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; } } void D_Text(D_Context *draw, D_Font *font, Str8 text, F32 x, F32 y) { 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) { if (text.data[it] >= ' ' && text.data[it] <= '~') { D_Glyph *glyph = &font->glyphs[text.data[it] - ' ']; - V2f size; - size.w = (glyph->box.max.x - glyph->box.min.x); - size.h = (glyph->box.max.y - glyph->box.min.y); + F32 image_scale = scale * Max(glyph->dim.w, glyph->dim.h); + F32 advance = scale * glyph->advance; - V2f dim; + V2f offset = V2f_Scale(glyph->offset, scale); - F32 scale = 150.0f / (font->ascent - font->descent); - - 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); } + 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 (!done) { printf("\n"); } - done = true; } 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_InitFont(&info, font_data.data, 0); - F32 scale = stbtt_ScaleForPixelHeight(&info, 20); + F32 scale = stbtt_ScaleForPixelHeight(&info, 256); U32 w = 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); - font->px = size; - S32 asc, desc, line; stbtt_GetFontVMetrics(&info, &asc, &desc, &line); - font->line_advance = cast(F32) line; - font->ascent = cast(F32) asc; - font->descent = cast(F32) desc; + font->line_advance = cast(F32) (scale * line); + font->ascent = cast(F32) (scale * asc); + font->descent = cast(F32) (scale * desc); 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; 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->offset = V2F(chr->xoff * scale, chr->yoff * scale); + glyph->advance = chr->xadvance; + 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; @@ -302,6 +303,8 @@ void D_FontLoad(D_Context *draw, Str8 name, F32 size) { Vk_CommandBuffer *cmds = Vk_CommandBufferPush(); + font->id = draw->n_images + draw->n_fonts; + font->image.width = w; font->image.height = h; diff --git a/code/draw/core.h b/code/draw/core.h index c4756f6..8db0a49 100644 --- a/code/draw/core.h +++ b/code/draw/core.h @@ -6,7 +6,10 @@ typedef struct D_Glyph D_Glyph; struct D_Glyph { F32 advance; + V2f offset; + V2f dim; + R2f box; }; @@ -14,13 +17,13 @@ typedef struct D_Font D_Font; struct D_Font { D_Font *next; - F32 px; + U32 id; F32 line_advance; F32 ascent; F32 descent; - F32 *kerning; + F32 *kerning; // @incomplete: we don't load this D_Glyph *glyphs; 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_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_FLIP_X = (1 << 3), + D_RECT_FLIP_Y = (1 << 4) }; typedef struct D_RectOpts D_RectOpts; diff --git a/code/first.c b/code/first.c index 6272ef7..f73d0e3 100644 --- a/code/first.c +++ b/code/first.c @@ -79,6 +79,8 @@ int main(int argc, char **argv) game->draw.arena = arena; G_ImagesLoad(game); + D_FontLoad(&game->draw, S("ubuntu"), 60); + G_PipelinesLoad(game); G_AudioLoad(game); @@ -87,7 +89,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, 48); + camera->p = V3F(0, 0, 16); camera->fov = 60.0f; @@ -129,12 +131,9 @@ int main(int argc, char **argv) badman->pointsOfInterest[1] = 12; world->npcPOI[0] = 100; - world->player.world = world; - world->player.pos.x = 0; - world->player.pos.y = 0; - world->player.bulletsLoaded = PLAYER_BULLET_COUNT; - world->player.reloadTimer = 0; - world->player.currentArea = WORLD_AREA_OUTSIDE; + + PlayerInit(game, &world->player); + for(int i =0; i< 4200; i++) { world->map[i] = map[i]; } @@ -220,17 +219,8 @@ int main(int argc, char **argv) game->editor.mode = G_EDITOR_MODE_TILE; 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; - printf("%zu size in bytes\n", sizeof(TestNavMesh)); - const int width = 1280; const int height = 720; @@ -243,6 +233,13 @@ int main(int argc, char **argv) { 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( V2F(e.button.x, e.button.y), V2F((F32) width, (F32) height) @@ -257,8 +254,8 @@ int main(int argc, char **argv) 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); + F32 tilex = (F32) (S32)(game->editor.cursor.x+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; break; } @@ -275,7 +272,7 @@ 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 + // 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( @@ -345,8 +342,7 @@ int main(int argc, char **argv) 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; - } - D_AnimationUpdate(&animation, 1.0f / 250.0f); + } int w, h; SDL_GetWindowSizeInPixels(window, &w, &h); @@ -386,17 +382,16 @@ int main(int argc, char **argv) RenderWorld(game->world, &game->draw); - R2f aframe = D_AnimationFrame(&animation); - D_Rect(&game->draw, 0, 0, .texture = animation.id, .uv = aframe, .flags = D_RECT_UV_ASPECT); + D_Text(&game->draw, game->draw.fonts, S("Small Test"), 0, 0); 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); + F32 tilex = cast(F32) floor(editor.cursor.x+TILE_SIZE/2); + F32 tiley = cast(F32) 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=asset.tile, .angle=asset.rotation); + D_Rect(&game->draw, tilex, tiley, .texture=asset.tile, .angle=(F32) asset.rotation); break; } case G_EDITOR_MODE_PROP: { @@ -405,7 +400,7 @@ int main(int argc, char **argv) break; } 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]); D_Rect(&game->draw, centre.x, centre.y, .texture=0, .dim=game->world->hitboxes[i].size, .flags=D_RECT_IGNORE_ASPECT); } diff --git a/code/game/core.h b/code/game/core.h index 028266e..5b918ce 100644 --- a/code/game/core.h +++ b/code/game/core.h @@ -1,6 +1,7 @@ #if !defined(LD_GAME_CORE_H_) #define LD_GAME_CORE_H_ -#include "world.h" + +typedef struct World World; typedef struct G_Camera G_Camera; struct G_Camera { @@ -44,6 +45,48 @@ struct G_State { 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_PipelinesLoad(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); +#include "world.h" #include "aabb.h" #include "player.h" #include "nav.h" diff --git a/code/game/impl/player.c b/code/game/impl/player.c index 8375d1e..2c430fd 100644 --- a/code/game/impl/player.c +++ b/code/game/impl/player.c @@ -3,6 +3,75 @@ #include #include +// @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; + + world->player.bulletsLoaded = PLAYER_BULLET_COUNT; + world->player.currentArea = WORLD_AREA_OUTSIDE; + + 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) { SDL_KeyboardEvent key = event->key; @@ -34,7 +103,7 @@ void PlayerInput(SDL_Event *event, Player *player) } } if ( - event->type == SDL_EVENT_MOUSE_BUTTON_DOWN + event->type == SDL_EVENT_MOUSE_BUTTON_DOWN && mouseBtn.button == SDL_BUTTON_LEFT ) { if(player->bulletsLoaded > 0) { @@ -47,7 +116,7 @@ void PlayerInput(SDL_Event *event, Player *player) player->reloadTimer = PLAYER_RELOAD_TIME; printf("reloading\n"); }; - } + } } void PlayerUpdate(F32 delta, Player *player) { @@ -55,16 +124,28 @@ void PlayerUpdate(F32 delta, Player *player) { V2f dir = V2F(0, 0); if(player->controls.upDown) { dir.y -= 1; + player->outfit.dir = G_OUTFIT_DIR_BACK; } if(player->controls.downDown) { dir.y += 1; + player->outfit.dir = G_OUTFIT_DIR_FRONT; } if(player->controls.leftDown) { dir.x -= 1; + player->outfit.dir = G_OUTFIT_DIR_SIDE | G_OUTFIT_DIR_FLIPPED; } if(player->controls.rightDown) { 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) { player->reloadTimer-=delta; if(player->reloadTimer <= 0) { @@ -76,3 +157,20 @@ void PlayerUpdate(F32 delta, Player *player) { player->pos.x += dir.x; player->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->pos.x, player->pos.y, .texture = tid, .uv = pframe, .flags = flags); + } + } +} diff --git a/code/game/impl/world.c b/code/game/impl/world.c index 63757c3..14a7fd7 100644 --- a/code/game/impl/world.c +++ b/code/game/impl/world.c @@ -47,7 +47,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) { D_Rect( draw, @@ -69,10 +69,13 @@ void RenderWorld(World *world, D_Context *draw) { V2f drawPos = AABB_Centre(world->bandit.collision); 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) { + (void) arena; + printf("Saving world\n"); OS_Handle file = FS_FileOpen(S("world.sgdat"), FS_ACCESS_WRITE); FS_FileWrite(file, world, sizeof(World)+sizeof(NavMesh), 0); diff --git a/code/game/player.h b/code/game/player.h index a727453..1756166 100644 --- a/code/game/player.h +++ b/code/game/player.h @@ -29,9 +29,14 @@ struct Player ControlState controls; V2f shotPos; + G_Outfit outfit; + 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 PlayerUpdate(F32 delta, Player *player);