diff --git a/art/demo_icemaker.aseprite b/art/demo_icemaker.aseprite new file mode 100644 index 0000000..9cd099d Binary files /dev/null and b/art/demo_icemaker.aseprite differ diff --git a/art/gen/demo_icemaker.png b/art/gen/demo_icemaker.png new file mode 100644 index 0000000..4a579b1 Binary files /dev/null and b/art/gen/demo_icemaker.png differ diff --git a/code/game/CMakeLists.txt b/code/game/CMakeLists.txt index 06f9c24..d3ffbeb 100644 --- a/code/game/CMakeLists.txt +++ b/code/game/CMakeLists.txt @@ -11,6 +11,7 @@ add_executable(eco2d src/prediction.c src/assets.c + src/items.c src/compress.c src/entity.c src/entity_view.c diff --git a/code/game/src/assets.h b/code/game/src/assets.h index f170be8..caa311c 100644 --- a/code/game/src/assets.h +++ b/code/game/src/assets.h @@ -4,9 +4,13 @@ #define ASSET_INVALID 0xFF typedef enum { + // NOTE(zaklaus): entities ASSET_PLAYER, ASSET_THING, + // NOTE(zaklaus): items + ASSET_DEMO_ICEMAKER, + MAX_ASSETS, FORCE_ASSET_UINT16 = UINT16_MAX } asset_id; @@ -26,3 +30,7 @@ uint16_t assets_find(asset_id id); asset_kind assets_get_kind(uint16_t id); void *assets_get_snd(uint16_t id); void *assets_get_tex(uint16_t id); + +// NOTE(zaklaus): client only +#define ASSET_SRC_RECT() ((Rectangle){0, 0, 64, 64}) +#define ASSET_DST_RECT(x,y) ((Rectangle){x, y, 64, 64}) diff --git a/code/game/src/assets_list.c b/code/game/src/assets_list.c index aedec5a..5a272a3 100644 --- a/code/game/src/assets_list.c +++ b/code/game/src/assets_list.c @@ -1,5 +1,8 @@ #include "assets.h" static asset assets[] = { - + { + .id = ASSET_DEMO_ICEMAKER, + .kind = AKIND_TEXTURE, + } }; diff --git a/code/game/src/debug_ui.c b/code/game/src/debug_ui.c index 61c3108..07c5673 100644 --- a/code/game/src/debug_ui.c +++ b/code/game/src/debug_ui.c @@ -113,6 +113,7 @@ static debug_item items[] = { { .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar }, { .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink }, { .kind = DITEM_BUTTON, .name = "spawn circling driver", .on_click = ActSpawnCirclingDriver }, + { .kind = DITEM_BUTTON, .name = "spawn icemaker item", .on_click = ActSpawnIcemaker }, { .kind = DITEM_LIST, .name = "demo npcs", diff --git a/code/game/src/debug_ui_actions.c b/code/game/src/debug_ui_actions.c index 013cfef..74753b8 100644 --- a/code/game/src/debug_ui_actions.c +++ b/code/game/src/debug_ui_actions.c @@ -1,5 +1,6 @@ #include "debug_ui.h" #include "world/blocks.h" +#include "items.h" void ActExitGame(void) { @@ -18,6 +19,16 @@ ActSpawnCar(void) { debug_replay_special_action(RPKIND_SPAWN_CAR); } +void +ActSpawnIcemaker(void) { + ecs_entity_t e = item_spawn(IKIND_DEMO_ICEMAKER, 1); + ecs_entity_t plr = camera_get().ent_id; + + Position const* origin = ecs_get(world_ecs(), plr, Position); + Position * dest = ecs_get_mut(world_ecs(), e, Position, NULL); + *dest = *origin; +} + void ActSpawnCirclingDriver(void) { ecs_entity_t plr = camera_get().ent_id; diff --git a/code/game/src/entity_view.c b/code/game/src/entity_view.c index 39312c1..fac1a3f 100644 --- a/code/game/src/entity_view.c +++ b/code/game/src/entity_view.c @@ -25,6 +25,9 @@ pkt_desc pkt_entity_view_desc[] = { { PKT_KEEP_IF(entity_view, kind, EKIND_VEHICLE, 1) }, // NOTE(zaklaus): keep for vehicles { PKT_HALF(entity_view, heading) }, + { PKT_KEEP_IF(entity_view, kind, EKIND_ITEM, 1) }, + { PKT_UINT(entity_view, asset) }, + { PKT_END }, }; diff --git a/code/game/src/entity_view.h b/code/game/src/entity_view.h index dd2b8a4..4af337a 100644 --- a/code/game/src/entity_view.h +++ b/code/game/src/entity_view.h @@ -1,5 +1,6 @@ #pragma once #include "system.h" +#include "assets.h" #define ZPL_PICO #include "zpl.h" @@ -7,6 +8,7 @@ typedef enum { EKIND_SERVER = 0, EKIND_PLAYER, + EKIND_ITEM, EKIND_VEHICLE, EKIND_DEMO_NPC, EKIND_MONSTER, @@ -52,6 +54,9 @@ typedef struct entity_view { // NOTE(zaklaus): vehicle float heading, theading; + // NOTE(zaklaus): items, ... + asset_id asset; + // NOTE(zaklaus): internals uint8_t layer_id; uint64_t last_update; diff --git a/code/game/src/gen/texgen.c b/code/game/src/gen/texgen.c index 1244a9a..0f6c002 100644 --- a/code/game/src/gen/texgen.c +++ b/code/game/src/gen/texgen.c @@ -13,30 +13,16 @@ Texture2D LoadImageEco(const char *name) { } Texture2D texgen_build_block(uint32_t biome, uint32_t kind) { - // TODO(zaklaus): - switch (biome) { case BLOCK_BIOME_DEV: { switch (kind) { - case BLOCK_KIND_GROUND:{ - return LoadImageEco("grass"); - }break; - case BLOCK_KIND_DIRT:{ - return LoadImageEco("dirt"); - }break; - case BLOCK_KIND_WALL:{ - return LoadImageEco("asphalt"); - }break; + case BLOCK_KIND_GROUND: return LoadImageEco("grass"); + case BLOCK_KIND_DIRT: return LoadImageEco("dirt"); + case BLOCK_KIND_WALL: return LoadImageEco("asphalt"); case BLOCK_KIND_HILL_SNOW: - case BLOCK_KIND_HILL:{ - return LoadImageEco("rock"); - }break; - case BLOCK_KIND_WATER:{ - return LoadImageEco("water"); - }break; - case BLOCK_KIND_LAVA:{ - return LoadImageEco("lava"); - }break; + case BLOCK_KIND_HILL: return LoadImageEco("rock"); + case BLOCK_KIND_WATER: return LoadImageEco("water"); + case BLOCK_KIND_LAVA: return LoadImageEco("lava"); } } } @@ -48,11 +34,16 @@ Texture2D texgen_build_block(uint32_t biome, uint32_t kind) { } Texture2D texgen_build_sprite(asset_id id) { - // TODO(zaklaus): - (void)id; - Image img = GenImageColor(1, 1, RAYWHITE); - Texture2D tex = LoadTextureFromImage(img); - UnloadImage(img); + switch (id) { + case ASSET_DEMO_ICEMAKER: return LoadImageEco("demo_icemaker"); + + default: { + Image img = GenImageColor(1, 1, RAYWHITE); + Texture2D tex = LoadTextureFromImage(img); + UnloadImage(img); + return tex; + }break; + } - return tex; + ZPL_PANIC("unreachable code"); } diff --git a/code/game/src/items.c b/code/game/src/items.c new file mode 100644 index 0000000..17fcaf9 --- /dev/null +++ b/code/game/src/items.c @@ -0,0 +1,31 @@ +#include "items.h" +#include "entity.h" +#include "entity_view.h" +#include "world/world.h" + +#include "modules/components.h" + +uint64_t item_spawn(item_kind kind, uint32_t qty) { + ecs_entity_t e = entity_spawn(EKIND_ITEM); + + ItemDrop *d = ecs_get_mut(world_ecs(), e, ItemDrop, NULL); + *d = (ItemDrop){ + .kind = kind, + .quantity = qty, + }; + + return (uint64_t)e; +} + +void item_despawn(uint64_t id) { + entity_despawn(id); +} + +asset_id item_get_asset(item_kind kind) { + switch (kind) { + case IKIND_DEMO_ICEMAKER: return ASSET_DEMO_ICEMAKER; + } + + ZPL_PANIC("unreachable code"); + return 0; +} \ No newline at end of file diff --git a/code/game/src/items.h b/code/game/src/items.h new file mode 100644 index 0000000..a751a65 --- /dev/null +++ b/code/game/src/items.h @@ -0,0 +1,14 @@ +#pragma once +#include "system.h" +#include "assets.h" + +typedef enum { + IKIND_DEMO_ICEMAKER, +} item_kind; + +uint64_t item_spawn(item_kind kind, uint32_t qty); +void item_despawn(uint64_t id); + +// NOTE(zaklaus): client + +asset_id item_get_asset(item_kind kind); \ No newline at end of file diff --git a/code/game/src/renderer_3d.c b/code/game/src/renderer_3d.c index af00e68..cc6d6c1 100644 --- a/code/game/src/renderer_3d.c +++ b/code/game/src/renderer_3d.c @@ -64,15 +64,6 @@ void DEBUG_draw_entities_3d(uint64_t key, entity_view * data) { float y = data->y; DrawSphere((Vector3){x,ground_offset,y}, size, ColorAlpha(PURPLE, data->tran_time)); }break; - - default:break; - } -} - -void DEBUG_draw_entities_low_3d(uint64_t key, entity_view * data) { - (void)key; - - switch (data->kind) { case EKIND_VEHICLE: { float x = data->x; float y = data->y; @@ -80,11 +71,16 @@ void DEBUG_draw_entities_low_3d(uint64_t key, entity_view * data) { float const h = 150; EcoDrawCube((Vector3){x,15.0f,y}, w/2.0f, 10.f, h/2.0f, -zpl_to_degrees(data->heading), ColorAlpha(RED, data->tran_time)); }break; - default:break; + case EKIND_CHUNK:break; + + default:{ + float x = data->x; + float y = data->y; + EcoDrawCube((Vector3){x, 15.0f, y}, 16, 16, 16, 0.0f, ColorAlpha(PINK, data->tran_time)); + }break; } } - void renderer_draw_3d(void) { cam_zoom = zpl_min(zpl_lerp(cam_zoom, target_zoom, 0.18), 9.98f); camera_update(); @@ -100,7 +96,6 @@ void renderer_draw_3d(void) { ClearBackground(GetColor(0x222034)); BeginMode3D(render_camera_3d); game_world_view_active_entity_map(DEBUG_draw_ground_3d); - game_world_view_active_entity_map(DEBUG_draw_entities_low_3d); game_world_view_active_entity_map(DEBUG_draw_entities_3d); EndMode3D(); } diff --git a/code/game/src/renderer_v0.c b/code/game/src/renderer_v0.c index 7f25cf1..97bce58 100644 --- a/code/game/src/renderer_v0.c +++ b/code/game/src/renderer_v0.c @@ -2,7 +2,7 @@ static Camera2D render_camera; static float zoom_overlay_tran = 0.0f; #define CAM_OVERLAY_ZOOM_LEVEL 0.80f - +#define ALPHA(x) ColorAlpha(x, data->tran_time) float zpl_lerp(float,float,float); float zpl_to_degrees(float); @@ -66,6 +66,11 @@ void DEBUG_draw_entities(uint64_t key, entity_view * data) { DrawTextEco(title, x-title_w/2, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(BLACK, data->tran_time), font_spacing); DrawCircleEco(x, y, size, ColorAlpha(PURPLE, data->tran_time)); }break; + case EKIND_ITEM: { + float x = data->x; + float y = data->y; + DrawTexturePro(GetSpriteTexture2D(assets_find(data->asset)), ASSET_SRC_RECT(), ASSET_DST_RECT(x,y), (Vector2){0.5f,0.5f}, 0.0f, ALPHA(WHITE)); + }break; default:break; } } diff --git a/code/game/src/utils/raylib_helpers.h b/code/game/src/utils/raylib_helpers.h index 0b7dc34..a4cbfec 100644 --- a/code/game/src/utils/raylib_helpers.h +++ b/code/game/src/utils/raylib_helpers.h @@ -68,8 +68,8 @@ RenderTexture2D GetChunkTexture(uint64_t id) { } static inline -Image GetSpriteImage(uint16_t id) { - return *(Image*)assets_get_tex(id); +Texture2D GetSpriteTexture2D(uint16_t id) { + return *(Texture2D*)assets_get_tex(id); } static inline diff --git a/code/game/src/world/world.c b/code/game/src/world/world.c index 21aa195..150bbda 100644 --- a/code/game/src/world/world.c +++ b/code/game/src/world/world.c @@ -5,6 +5,7 @@ #include "world/world.h" #include "entity_view.h" #include "debug_replay.h" +#include "items.h" #include "world/worldgen/worldgen.h" #include "platform.h" #include "profiler.h" @@ -51,6 +52,11 @@ entity_view world_build_entity_view(int64_t e) { view.heading = veh->heading; } + if (ecs_get(world_ecs(), e, ItemDrop)) { + ItemDrop const* dr = ecs_get(world_ecs(), e, ItemDrop); + view.asset = item_get_asset(dr->kind); + } + Chunk *chpos = 0; if ((chpos = ecs_get_mut_if(world_ecs(), e, Chunk))) { view.x = chpos->x; diff --git a/code/game/src/world/world.h b/code/game/src/world/world.h index c861e94..d379c01 100644 --- a/code/game/src/world/world.h +++ b/code/game/src/world/world.h @@ -53,7 +53,7 @@ int32_t world_read(void* data, uint32_t datalen, void *udata); int32_t world_write(pkt_header *pkt, void *udata); uint32_t world_buf(uint8_t const **ptr, uint32_t *width); -ecs_world_t *world_ecs(void); +ecs_world_t *world_ecs(void); // TODO(zaklaus): add staging support librg_world *world_tracker(void); uint16_t world_chunk_size(void); diff --git a/code/modules/modules/components.c b/code/modules/modules/components.c index 998a6fc..c17544a 100644 --- a/code/modules/modules/components.c +++ b/code/modules/modules/components.c @@ -11,6 +11,7 @@ ECS_COMPONENT_DECLARE(Health); ECS_COMPONENT_DECLARE(Classify); ECS_COMPONENT_DECLARE(Vehicle); ECS_COMPONENT_DECLARE(IsInVehicle); +ECS_COMPONENT_DECLARE(ItemDrop); ECS_TAG_DECLARE(EcsActor); ECS_TAG_DECLARE(EcsDemoNPC); ECS_TYPE_DECLARE(Player); @@ -35,6 +36,7 @@ void ComponentsImport(ecs_world_t *ecs) { ECS_META_DEFINE(ecs, Vehicle); ECS_COMPONENT_DEFINE(ecs, IsInVehicle); + ECS_COMPONENT_DEFINE(ecs, ItemDrop); ECS_TAG_DEFINE(ecs, Walking); ECS_TAG_DEFINE(ecs, Flying); @@ -56,6 +58,7 @@ void ComponentsImport(ecs_world_t *ecs) { ECS_SET_COMPONENT(Classify); ECS_SET_COMPONENT(Vehicle); ECS_SET_COMPONENT(IsInVehicle); + ECS_SET_COMPONENT(ItemDrop); ECS_SET_ENTITY(Walking); ECS_SET_ENTITY(Flying); ECS_SET_ENTITY(EcsActor); diff --git a/code/modules/modules/components.h b/code/modules/modules/components.h index dfcc72c..c33bd9b 100644 --- a/code/modules/modules/components.h +++ b/code/modules/modules/components.h @@ -1,9 +1,9 @@ #pragma once #include "flecs/flecs.h" #include "flecs/flecs_meta.h" +#include "items.h" - -// NOTE(zaklaus): custom macro to define meta components outside the current scope +//NOTE(zaklaus): custom macro to define meta components outside the current scope #ifndef ECS_META_DEFINE #define ECS_META_DEFINE(world, T)\ @@ -52,7 +52,7 @@ ECS_STRUCT(Health, { float hp; float max_hp; - // NOTE(zaklaus): Intentionally global, to allow for creative use of damage combos + //NOTE(zaklaus): Intentionally global, to allow for creative use of damage combos float pain_time; float heal_time; }); @@ -74,6 +74,11 @@ typedef struct { ecs_entity_t veh; } IsInVehicle; +typedef struct { + item_kind kind; + uint32_t quantity; +} ItemDrop; + ECS_COMPONENT_EXTERN(Chunk); ECS_COMPONENT_EXTERN(Position); ECS_COMPONENT_EXTERN(Vector2D); @@ -85,6 +90,7 @@ ECS_COMPONENT_EXTERN(Health); ECS_COMPONENT_EXTERN(Classify); ECS_COMPONENT_EXTERN(Vehicle); ECS_COMPONENT_EXTERN(IsInVehicle); +ECS_COMPONENT_EXTERN(ItemDrop); ECS_TAG_EXTERN(EcsActor); ECS_TAG_EXTERN(EcsDemoNPC); ECS_TYPE_EXTERN(Player); @@ -106,6 +112,7 @@ typedef struct { ECS_DECLARE_COMPONENT(Classify); ECS_DECLARE_COMPONENT(Vehicle); ECS_DECLARE_COMPONENT(IsInVehicle); + ECS_DECLARE_COMPONENT(ItemDrop); ECS_DECLARE_ENTITY(EcsActor); ECS_DECLARE_ENTITY(EcsDemoNPC); ECS_DECLARE_TYPE(Player); @@ -128,6 +135,7 @@ ECS_IMPORT_COMPONENT(handles, Health);\ ECS_IMPORT_COMPONENT(handles, Classify);\ ECS_IMPORT_COMPONENT(handles, Vehicle);\ ECS_IMPORT_COMPONENT(handles, IsInVehicle);\ +ECS_IMPORT_COMPONENT(handles, ItemDrop);\ ECS_IMPORT_TYPE(handles, Player);\ ECS_IMPORT_TYPE(handles, Builder);\ ECS_IMPORT_TYPE(handles, Movement);\