diff --git a/code/games/survival/src/main.c b/code/games/survival/src/main.c index 7a7b901..5e2c5cd 100644 --- a/code/games/survival/src/main.c +++ b/code/games/survival/src/main.c @@ -10,6 +10,7 @@ typedef int efd_app; typedef uint16_t efd_entity_type; typedef int32_t efd_result; typedef void * efd_world; +typedef int efd_entid; // define amount of memeory reserved for??? // custom data within COMMAND (cli->ser) and SNAPSHOT (ser->cli) @@ -21,46 +22,70 @@ typedef void * efd_world; #define EFD_TYPE(id) ((id - 1) >> EFD_TYPE_SHIFT) #define EFD_END 0 -typedef enum efd_asset_type { - EFD_NONE = 0, - EFD_TEXTURE, - EFD_TEXTURE_ATLAS, - EFD_ANIMATION, - EFD_SOUND, - EFD_FONT, - EFD_SHADER, -} efd_asset_type; +typedef enum efd_instance_type { + EFD_TYPE_NONE = 0, -typedef enum efd_object_type { - EFD_TYPE_NONE, + /* chunk */ EFD_TYPE_TILE, EFD_TYPE_BLOCK, - EFD_TYPE_ENTITY, - EFD_TYPE_ITEM, - EFD_TYPE_CRAFT, EFD_TYPE_CHUNK, - EFD_TYPE_TYPE_LAST, - EFD_TYPE_TYPE_MAX = 0xFFFF, -} efd_object_type; + /* entities */ + EFD_TYPE_ITEM, + EFD_TYPE_OBJECT, + EFD_TYPE_DEVICE, + EFD_TYPE_VEHICLE, + EFD_TYPE_MOB, + EFD_TYPE_PLAYER, + + /* other */ + EFD_TYPE_OTHER, + + /* utils */ + EFD_TYPE_LAST, + EFD_TYPE_MAX = 0xFFFF, +} efd_instance_type; typedef enum efd_flags { EFD_FLAG_COLLISION = (1 << 1), EFD_FLAG_HAZARD = (1 << 2), EFD_FLAG_ESSENTIAL = (1 << 3), EFD_FLAG_DESTROY_ON_COLLISION = (1 << 4), - EFD_FLAG_AI = (1 << 5), - EFD_FLAG_PLAYER = (1 << 6), - EFD_FLAG_VEHICLE = (1 << 7), } efd_flags; + +// assets + +typedef enum efd_asset_type { + EFD_NONE = 0, + EFD_TEXTURE, + EFD_ANIMATION, + EFD_SOUND, + EFD_FONT, + EFD_SHADER, +} efd_asset_type; + +typedef enum efd_asset_flags { + EFD_FLAG_ATLAS = (1 << 1), // texture is an atlas and has multiple frames + EFD_FLAG_LOOPED = (1 << 2), // frames are looped sequentially (requrires EFD_FLAG_ATLAS, can be combined with EFD_FLAG_RANDOM) + EFD_FLAG_RANDOM = (1 << 3), // one of the frames is randomly chosen (requrires EFD_FLAG_ATLAS, can be combined with EFD_FLAG_LOOPED) + EFD_FLAG_COMPLEX = (1 << 4), // frames have a complex state system and require a separate asset with EFD_ANIMATION type +} efd_asset_flags; + typedef struct efd_asset { efd_asset_type type; int id; const char *path; - void *data; /* TODO: make a union */ + int32_t flags; + struct { + int size_x; + int size_y; + } atlas; + void *data; } efd_asset; +// objects + typedef struct efd_tile { int id; int flags; @@ -76,27 +101,16 @@ typedef struct efd_block { int vely; } efd_block; -typedef struct efd_entity { - int id; - int flags; -} efd_entity; - -typedef struct efd_item { - int id; - const char *t1; - const char *t2; -} efd_item; - -typedef struct efd_craft_item { +typedef struct efd_item_list { int id; int qty; -} efd_craft_item; +} efd_item_list; typedef struct efd_craft { int producer; int ticks; - efd_craft_item *input; - efd_craft_item *output; + efd_item_list *input; + efd_item_list *output; } efd_craft; typedef struct efd_tooltip { @@ -104,6 +118,19 @@ typedef struct efd_tooltip { const char *description; } efd_tooltip; +typedef struct efd_entity { + int id; + int flags; + int stack; + union { + int durability; + int health; + }; + efd_result (*spawn_cb)(efd_entid); + efd_item_list *drop; +} efd_entity; + + typedef struct efd_app_desc { const char *name; int debug_ui; @@ -123,8 +150,8 @@ typedef struct efd_app_desc { efd_result (*system_cb)(); efd_result (*update_cb)(); efd_result (*render_cb)(efd_entity_type type); - efd_result (*player_join_cb)(efd_entity player_id); - efd_result (*player_leave_cb)(efd_entity player_id); + efd_result (*player_join_cb)(efd_entid player_id); + efd_result (*player_leave_cb)(efd_entid player_id); efd_result (*cleanup_cb)(); struct { @@ -139,7 +166,6 @@ typedef struct efd_app_desc { efd_tile *tiles; efd_block *blocks; efd_entity *entities; - efd_item *items; efd_craft *crafting; efd_tooltip *tooltips; } efd_app_desc; @@ -155,64 +181,50 @@ enum { TILE_WATER, TILE_LAVA, - BLOCK_STONE = EFD_ID(EFD_TYPE_BLOCK), - BLOCK_BRICK, + BLOCK_AIR = EFD_ID(EFD_TYPE_BLOCK), + BLOCK_WOOD, BLOCK_HILL, BLOCK_HILL_SNOW, - BLOCK_FENCE, - BLOCK_WOOD, - BLOCK_WALL, + BLOCK_FENCE_LEFT, + BLOCK_FENCE_RIGHT, + BLOCK_FENCE_UP, + BLOCK_FENCE_DOWN, + BLOCK_WALL_LEFT, + BLOCK_WALL_RIGHT, + BLOCK_WALL_UP, + BLOCK_WALL_DOWN, BLOCK_BELT_LEFT, BLOCK_BELT_RIGHT, BLOCK_BELT_UP, BLOCK_BELT_DOWN, - ENTITY_PLAYER = EFD_ID(EFD_TYPE_ENTITY), - ENTITY_MONSTER, - ENTITY_TRUCK, - ENTITY_TREE, - ENTITY_CHEST, + ENTITY_IRON_ORE = EFD_ID(EFD_TYPE_ITEM), + ENTITY_IRON_INGOT, + ENTITY_IRON_PLATE, + ENTITY_SCREW, + ENTITY_BELT, + + ENTITY_FIR_TREE = EFD_ID(EFD_TYPE_OBJECT), + ENTITY_OAK_TREE, + + ENTITY_CHEST = EFD_ID(EFD_TYPE_DEVICE), ENTITY_FURNACE, ENTITY_CRAFTBENCH, ENTITY_ASSEMBLER, - ITEM_IRON_ORE = EFD_ID(EFD_TYPE_ITEM), - ITEM_IRON_INGOT, - ITEM_IRON_PLATE, - ITEM_SCREW, - ITEM_BELT, + ENTITY_MONSTER = EFD_ID(EFD_TYPE_MOB), + ENTITY_RABBIT, + ENTITY_BOAR, + ENTITY_BIZON, + ENTITY_BEAR, + + ENTITY_TRUCK = EFD_ID(EFD_TYPE_VEHICLE), + ENTITY_CAR, + + ENTITY_PLAYER = EFD_ID(EFD_TYPE_PLAYER), }; -// void Move(ecs_iter_t *it) { -// // Get fields from system query -// Position *p = ecs_field(it, Position, 1); -// Velocity *v = ecs_field(it, Velocity, 2); - -// // Iterate matched entities -// for (int i = 0; i < it->count, i++) { -// p[i].x += v[i].x; -// p[i].y += v[i].y; -// } -// } - efd_result init() { - // NOTE: control sets could be implemented later on - // // register game specific input bindings - // // pre-defined bindings and controlsets - // efd_controlset_apply(EFD_ACTION_MOVE, EFD_CONTROLSET_WASD | EFD_CONTROLSET_ARROWS | EFD_CONTROLSET_GAMEPAD_LEFT); - // efd_controlset_apply(EFD_ACTION_POINT, EFD_CONTROLSET_MOUSE | EFD_CONTROLSET_GAMEPAD_RIGHT); - - // // custom bindings and controlsets - // efd_controlset_keyboard(CONTROLSET_ACCELERATE, EFD_KEY_DOWN, EFD_KEY_SHIFT_LEFT | EFD_KEY_SHIFT_RIGHT); - // efd_controlset_gamepad(CONTROLSET_ACCELERATE, EFD_GAMEPAD_LEFT_TRIGGER, 0.5f); - // efd_controlset_apply(EFD_ACTION_SPRINT, CONTROLSET_ACCERLATE); - - // // custom input bindings for custom actions - // efd_controlset_register(ACTION_USE); - // efd_controlset_keyboard(CONTROLSET_USE, EFD_KEY_DOWN, EFD_KEY_E); - // efd_controlset_gamepad(CONTROLSET_USE, EFD_GAMEPAD_BUTTON_A, 0.5f); - // efd_controlset_apply(ACTION_USE, CONTROLSET_USE); - return 0; } @@ -228,7 +240,7 @@ efd_result update() { efd_result render(efd_entity_type type) { // switch (type) { - // case EFD_ENTITY_PLAYER: + // case ENTITY_PLAYER: // /* additional/replacable rendering code on top of what EFD provides for built-in types */ // efd_render_texture(ENTITY_PLAYER, 0, 0, 0, 0, 0, 0, 0, 0); @@ -248,12 +260,12 @@ efd_result render(efd_entity_type type) { return 0; } -efd_result player_join(efd_entity player) { +efd_result player_join(efd_entid player) { // efd_notify_push(player, "Test", "Welcome to the game!", 5.0f); return 0; } -efd_result player_leave(efd_entity player) { +efd_result player_leave(efd_entid player) { return 0; } @@ -261,6 +273,14 @@ efd_result cleanup() { return 0; } +efd_result chest_spawn(efd_entid id) { + return 0; +} + +efd_result furnace_spawn(efd_entid id) { + return 0; +} + efd_app_desc efd_main() { return (efd_app_desc){ .name = "Survival", @@ -297,13 +317,24 @@ efd_app_desc efd_main() { }, .assets = (efd_asset[]){ - {EFD_TEXTURE, ENTITY_TREE, "assets/tree.png"}, + {EFD_TEXTURE, TILE_GRASS, "assets/grass.png", EFD_FLAG_ATLAS | EFD_FLAG_RANDOM, .atlas = {4, 1}}, + {EFD_TEXTURE, TILE_DIRT, "assets/dirt.png", EFD_FLAG_ATLAS | EFD_FLAG_RANDOM, .atlas = {4, 1}}, + {EFD_TEXTURE, TILE_LAVA, "assets/lava.png", EFD_FLAG_ATLAS | EFD_FLAG_LOOPED, .atlas = {4, 1}}, + {EFD_TEXTURE, TILE_WATER, "assets/water.png", EFD_FLAG_ATLAS | EFD_FLAG_RANDOM | EFD_FLAG_LOOPED, .atlas = {4, 1}}, + + {EFD_TEXTURE, ENTITY_OAK_TREE, "assets/tree.png"}, {EFD_TEXTURE, ENTITY_CHEST, "assets/chest.png"}, {EFD_TEXTURE, ENTITY_FURNACE, "assets/furnace.png"}, - {EFD_TEXTURE, ENTITY_PLAYER, "assets/player.png"}, + {EFD_TEXTURE, ENTITY_PLAYER, "assets/player.png", EFD_FLAG_ATLAS | EFD_FLAG_COMPLEX}, {EFD_TEXTURE, ENTITY_MONSTER, "assets/monster.png"}, + /* animations */ + {EFD_ANIMATION, ENTITY_PLAYER, "assets/player.anim"}, + + /* sounds */ + {EFD_SOUND, ENTITY_PLAYER, "assets/player.wav"}, + {EFD_END}, }, @@ -318,12 +349,21 @@ efd_app_desc efd_main() { }, .blocks = (efd_block[]){ - {BLOCK_WALL, EFD_FLAG_COLLISION, .bounce = 1.0f}, + {BLOCK_AIR}, {BLOCK_HILL, EFD_FLAG_COLLISION}, {BLOCK_HILL_SNOW, EFD_FLAG_COLLISION}, - {BLOCK_FENCE, EFD_FLAG_COLLISION, .bounce = 1.0f}, {BLOCK_WOOD, EFD_FLAG_COLLISION, .bounce = 0.0f}, + {BLOCK_WALL_LEFT, EFD_FLAG_COLLISION, .bounce = 1.0f}, + {BLOCK_WALL_RIGHT, EFD_FLAG_COLLISION, .bounce = 1.0f}, + {BLOCK_WALL_UP, EFD_FLAG_COLLISION, .bounce = 1.0f}, + {BLOCK_WALL_DOWN, EFD_FLAG_COLLISION, .bounce = 1.0f}, + + {BLOCK_FENCE_LEFT, EFD_FLAG_COLLISION, .bounce = 1.0f}, + {BLOCK_FENCE_RIGHT, EFD_FLAG_COLLISION, .bounce = 1.0f}, + {BLOCK_FENCE_UP, EFD_FLAG_COLLISION, .bounce = 1.0f}, + {BLOCK_FENCE_DOWN, EFD_FLAG_COLLISION, .bounce = 1.0f}, + {BLOCK_BELT_LEFT, .velx = -150.0f}, {BLOCK_BELT_RIGHT, .velx = 150.0f}, {BLOCK_BELT_UP, .vely = -150.0f}, @@ -333,20 +373,22 @@ efd_app_desc efd_main() { }, .entities = (efd_entity[]){ - {ENTITY_TREE, EFD_FLAG_DESTROY_ON_COLLISION}, - {ENTITY_CHEST}, - {ENTITY_FURNACE}, + {ENTITY_IRON_ORE, .stack = 32}, + {ENTITY_IRON_PLATE, .stack = 32}, + {ENTITY_SCREW, .stack = 256}, - {ENTITY_PLAYER, EFD_FLAG_PLAYER}, - {ENTITY_TRUCK, EFD_FLAG_VEHICLE}, - {ENTITY_MONSTER, EFD_FLAG_AI}, + {ENTITY_OAK_TREE, EFD_FLAG_DESTROY_ON_COLLISION, .drop = (efd_item_list[]){ + {ENTITY_SCREW, 1}, + {EFD_END}, + }}, - {EFD_END}, - }, + {ENTITY_CHEST, .spawn_cb = chest_spawn}, + {ENTITY_FURNACE, .spawn_cb = furnace_spawn}, + + {ENTITY_MONSTER, .health = 256}, + {ENTITY_TRUCK}, + {ENTITY_PLAYER}, - .items = (efd_item[]){ - // {ITEM_WOOD, "Wood", "A piece of wood."}, - // {ITEM_STONE, "Stone", "A piece of stone."}, {EFD_END}, }, @@ -354,38 +396,37 @@ efd_app_desc efd_main() { { .producer = ENTITY_FURNACE, .ticks = 20, - .input = (efd_craft_item[]){ - {ITEM_IRON_ORE, 1}, + .input = (efd_item_list[]){ + {ENTITY_IRON_ORE, 1}, {EFD_END}, }, - .output = (efd_craft_item[]){ - {ITEM_IRON_PLATE, 4}, + .output = (efd_item_list[]){ + {ENTITY_IRON_PLATE, 4}, {EFD_END}, }, }, { .producer = ENTITY_CRAFTBENCH, .ticks = 40, - .input = (efd_craft_item[]){ - {ITEM_IRON_PLATE, 1}, + .input = (efd_item_list[]){ + {ENTITY_IRON_PLATE, 1}, {EFD_END}, }, - .output = (efd_craft_item[]){ - {ITEM_SCREW, 8}, + .output = (efd_item_list[]){ + {ENTITY_SCREW, 8}, {EFD_END}, }, }, { .producer = ENTITY_ASSEMBLER, .ticks = 120, - .input = (efd_craft_item[]){ - {BLOCK_FENCE, 1}, - {ITEM_SCREW, 4}, - {ITEM_IRON_PLATE, 2}, + .input = (efd_item_list[]){ + {ENTITY_SCREW, 4}, + {ENTITY_IRON_PLATE, 2}, {EFD_END}, }, - .output = (efd_craft_item[]){ - {ITEM_BELT, 1}, + .output = (efd_item_list[]){ + {ENTITY_BELT, 1}, {EFD_END}, }, }, @@ -412,8 +453,8 @@ int main(int argc, char **argv) { printf("value: %f\n", desc.rules.item_pickup_radius); printf("TILE_DIRT: %d\n", TILE_DIRT); printf("TILE_GRASS: %d\n", TILE_GRASS); - printf("ENTITY_PLAYER: %d\n", ENTITY_PLAYER); - printf("ENTITY_CHEST: %d\n", ENTITY_CHEST); + printf("ENTITY_PLAYER: %d, is_valid type: %d\n", ENTITY_PLAYER, EFD_TYPE(ENTITY_PLAYER) == EFD_TYPE_PLAYER); + printf("ENTITY_CHEST: %d, is_valid type: %d\n", ENTITY_CHEST, EFD_TYPE(ENTITY_CHEST) == EFD_TYPE_DEVICE); desc.init_cb(); diff --git a/foundation.md b/foundation.md index fd1dbab..270031b 100644 --- a/foundation.md +++ b/foundation.md @@ -45,8 +45,14 @@ * tile - basic thing that makes up the chunks * block - 2nd level of things that make up the chunk * entity - an grid-independant static or dynamic entity that can exist in the world and has some systems controlling it -* item - an entity in the world, that can have a different state when its picked up -* crafting - a recipe that can be used to craft an item + primary archetypes: + * item - an entity in the world, that can have a different state when its picked up + * object - an item that can be placed in the world + * device - an object that can be interacted with + * mob - an entity that can be controlled by ai + * player - an entity that can be controlled by a player + * vehicle - an entity that can be used to transport other entities +* craft - a recipe that can be used to craft an item ## Naming @@ -57,16 +63,27 @@ * survival * prefix: efd_ -## Objects +## Concepts * tile * block * entity - * npc + * item + * object + * device + * mob * player * vehicle - * item * craft +## Transitions +* item -> tile (item destroyed, tile replaced) +* item -> block (item destroyed, block created) +* item -> entity (item hidden and untracked, entity component added) // item becomes entity, just changes state +* item -> item (crafting) (item destroyed, item created) +* tile -> item (tile replaced, item created) +* block -> item (block destroyed, item created) +* block -> block (crafting) (block destroyed, block created) +* entity -> item (entity component removed, item shown and tracked) // entity becomes item, just changes state ## Features * In-memory lists @@ -76,3 +93,21 @@ * prafabs for entities (pipeline for entities) * built in server->client RPC * + + + +// // register game specific input bindings +// // pre-defined bindings and controlsets +// efd_controlset_apply(EFD_ACTION_MOVE, EFD_CONTROLSET_WASD | EFD_CONTROLSET_ARROWS | EFD_CONTROLSET_GAMEPAD_LEFT); +// efd_controlset_apply(EFD_ACTION_POINT, EFD_CONTROLSET_MOUSE | EFD_CONTROLSET_GAMEPAD_RIGHT); + +// // custom bindings and controlsets +// efd_controlset_keyboard(CONTROLSET_ACCELERATE, EFD_KEY_DOWN, EFD_KEY_SHIFT_LEFT | EFD_KEY_SHIFT_RIGHT); +// efd_controlset_gamepad(CONTROLSET_ACCELERATE, EFD_GAMEPAD_LEFT_TRIGGER, 0.5f); +// efd_controlset_apply(EFD_ACTION_SPRINT, CONTROLSET_ACCERLATE); + +// // custom input bindings for custom actions +// efd_controlset_register(ACTION_USE); +// efd_controlset_keyboard(CONTROLSET_USE, EFD_KEY_DOWN, EFD_KEY_E); +// efd_controlset_gamepad(CONTROLSET_USE, EFD_GAMEPAD_BUTTON_A, 0.5f); +// efd_controlset_apply(ACTION_USE, CONTROLSET_USE);