move ASSET_MOB to survival game

master
Dominik Madarász 2024-05-29 11:18:48 +02:00
parent 29d9b9306d
commit 23645ed32a
10 changed files with 285 additions and 305 deletions

View File

@ -20,7 +20,6 @@
X(ASSET_BLUEPRINT)\ X(ASSET_BLUEPRINT)\
X(ASSET_BLUEPRINT_DEMO_HOUSE)\ X(ASSET_BLUEPRINT_DEMO_HOUSE)\
X(ASSET_BLUEPRINT_END)\ X(ASSET_BLUEPRINT_END)\
X(ASSET_MOB)\
X(ASSET_FENCE)\ X(ASSET_FENCE)\
X(ASSET_DEV)\ X(ASSET_DEV)\
X(ASSET_GROUND)\ X(ASSET_GROUND)\

View File

@ -163,7 +163,6 @@ static debug_item items[] = {
.is_collapsed = false .is_collapsed = false
} }
}, },
{ .kind = DITEM_BUTTON, .name = "spawn mobs", .on_click = ActSpawnMobs },
{ .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar }, { .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar },
{ .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink }, { .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink },
{ .kind = DITEM_BUTTON, .name = "erase world changes", .on_click = ActEraseWorldChanges }, { .kind = DITEM_BUTTON, .name = "erase world changes", .on_click = ActEraseWorldChanges },

View File

@ -54,32 +54,6 @@ ActSpawnSelItem(void) {
entity_set_position(e, origin->x, origin->y); entity_set_position(e, origin->x, origin->y);
} }
void
ActSpawnMobs(void) {
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
const uint32_t w = 12*WORLD_BLOCK_SIZE;
const uint32_t h = 12*WORLD_BLOCK_SIZE;
uint32_t x = (uint32_t)origin->x - w/2;
uint32_t y = (uint32_t)origin->y - h/2;
for (uint32_t cy=y; cy<y+h; cy+=WORLD_BLOCK_SIZE) {
for (uint32_t cx=x; cx<x+w; cx+=WORLD_BLOCK_SIZE) {
if (cx >= world_dim()) continue;
if (cy >= world_dim()) continue;
if ((cy == y || cy == (y + h-WORLD_BLOCK_SIZE)) ||
(cx == x || cx == (x + w-WORLD_BLOCK_SIZE))) {
ecs_entity_t e = entity_spawn_id(ASSET_MOB);
entity_set_position(e, (float)cx, (float)cy);
ecs_add(world_ecs(), e, MobMelee);
}
}
}
}
void void
ActSpawnCirclingDriver(void) { ActSpawnCirclingDriver(void) {
ecs_entity_t plr = camera_get().ent_id; ecs_entity_t plr = camera_get().ent_id;

View File

@ -56,9 +56,6 @@ Texture2D texgen_build_sprite_fallback(asset_id id) {
case ASSET_CRAFTBENCH: return LoadTexEco("craftbench"); case ASSET_CRAFTBENCH: return LoadTexEco("craftbench");
case ASSET_SPLITTER: return LoadTexEco("item_splitter"); case ASSET_SPLITTER: return LoadTexEco("item_splitter");
case ASSET_ASSEMBLER: return LoadTexEco("assembler"); case ASSET_ASSEMBLER: return LoadTexEco("assembler");
// Mobs
case ASSET_MOB: return LoadTexEco("enemy1");
default: break; default: break;
} }

View File

@ -1,255 +1,254 @@
// Tooltip system with multilevel modal support // Tooltip system with multilevel modal support
typedef struct _tooltip { typedef struct _tooltip {
const char *name; const char *name;
const char *content; const char *content;
const char **links; const char **links;
} tooltip; } tooltip;
static tooltip *tooltips = 0; static tooltip *tooltips = 0;
//~ registration //~ registration
void tooltip_register(tooltip desc) { void tooltip_register(tooltip desc) {
if (!tooltips) { if (!tooltips) {
zpl_array_init(tooltips, zpl_heap()); zpl_array_init(tooltips, zpl_heap());
} }
desc.links = 0; desc.links = 0;
zpl_array_append(tooltips, desc); zpl_array_append(tooltips, desc);
} }
void tooltip_destroy_all(void) { void tooltip_destroy_all(void) {
if (!tooltips) return; if (!tooltips) return;
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) { for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i); tooltip *tp = (tooltips + i);
if (tp->links) { if (tp->links) {
zpl_array_free(tp->links); zpl_array_free(tp->links);
} }
} }
zpl_array_free(tooltips); zpl_array_free(tooltips);
} }
void tooltip_build_links(void) { void tooltip_build_links(void) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) { for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
tooltip *tp = (tooltips + i); tooltip *tp = (tooltips + i);
for (zpl_isize j = 0; j < zpl_array_count(tooltips); ++j) { for (zpl_isize j = 0; j < zpl_array_count(tooltips); ++j) {
tooltip *linked_tp = (tooltips + j); tooltip *linked_tp = (tooltips + j);
if (tp == linked_tp) if (tp == linked_tp)
continue; continue;
if (strstr(tp->content, linked_tp->name)) { if (strstr(tp->content, linked_tp->name)) {
if (!tp->links) { if (!tp->links) {
zpl_array_init(tp->links, zpl_heap()); zpl_array_init(tp->links, zpl_heap());
} }
zpl_array_append(tp->links, linked_tp->name); zpl_array_append(tp->links, linked_tp->name);
} }
} }
} }
} }
void tooltip_register_defaults(void) { void tooltip_register_defaults(void) {
// test // test
tooltip_register( (tooltip) { .name = "ASSET_WOOD", .content = "Used as a building material or fuel for the ASSET_FURNACE." } ); tooltip_register( (tooltip) { .name = "ASSET_WOOD", .content = "Used as a building material or fuel for the ASSET_FURNACE." } );
tooltip_register( (tooltip) { .name = "ASSET_FURNACE", .content = "Producer used to smelt ASSET_IRON_ORE into ASSET_IRON_INGOT." } ); tooltip_register( (tooltip) { .name = "ASSET_FURNACE", .content = "Producer used to smelt ASSET_IRON_ORE into ASSET_IRON_INGOT." } );
tooltip_register( (tooltip) { .name = "ASSET_IRON_ORE", .content = "Natural resource that can be smelted in ASSET_FURNACE." } ); tooltip_register( (tooltip) { .name = "ASSET_IRON_ORE", .content = "Natural resource that can be smelted in ASSET_FURNACE." } );
tooltip_register( (tooltip) { .name = "ASSET_IRON_INGOT", .content = "Used as a building material. It is smelted from ASSET_IRON_ORE." } ); tooltip_register( (tooltip) { .name = "ASSET_IRON_INGOT", .content = "Used as a building material. It is smelted from ASSET_IRON_ORE." } );
tooltip_register( (tooltip) { .name = "ASSET_SCREWS", .content = "Used as a building material. It is crafted from ASSET_IRON_PLATES." } ); tooltip_register( (tooltip) { .name = "ASSET_SCREWS", .content = "Used as a building material. It is crafted from ASSET_IRON_PLATES." } );
tooltip_register( (tooltip) { .name = "ASSET_MOB", .content = "Enemy hunting player down." } ); tooltip_register( (tooltip) { .name = "craft", .content = "Crafting is the process of constructing tools, items, and blocks." } );
tooltip_register( (tooltip) { .name = "craft", .content = "Crafting is the process of constructing tools, items, and blocks." } ); tooltip_register( (tooltip) { .name = "smelt", .content = "Smelting is a process of applying heat to ore, to extract a base metal. It is a form of extractive metallurgy. It is used to extract many metals from their ores, including silver, iron, copper, and other base metals." } );
tooltip_register( (tooltip) { .name = "smelt", .content = "Smelting is a process of applying heat to ore, to extract a base metal. It is a form of extractive metallurgy. It is used to extract many metals from their ores, including silver, iron, copper, and other base metals." } ); }
}
//~ rendering
//~ rendering
#define TOOLTIP_MOUSE_DIST 400.0f
#define TOOLTIP_MOUSE_DIST 400.0f
typedef struct _tooltip_node {
typedef struct _tooltip_node { float xpos, ypos;
float xpos, ypos; tooltip *desc;
tooltip *desc; struct _tooltip_node *next;
struct _tooltip_node *next; } tooltip_node;
} tooltip_node;
static tooltip_node main_tooltip = { 0 };
static tooltip_node main_tooltip = { 0 }; static bool tooltip__should_stay_open = false;
static bool tooltip__should_stay_open = false;
tooltip *tooltip_find_desc(const char *name) {
tooltip *tooltip_find_desc(const char *name) { for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) { tooltip *tp = (tooltips + i);
tooltip *tp = (tooltips + i);
if (!strcmp(tp->name, name))
if (!strcmp(tp->name, name)) return tp;
return tp; }
}
return 0;
return 0; }
}
const char *tooltip_find_desc_contents(const char *name) {
const char *tooltip_find_desc_contents(const char *name) { if (!tooltips) return 0;
if (!tooltips) return 0;
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) { tooltip *tp = (tooltips + i);
tooltip *tp = (tooltips + i);
if (!strcmp(tp->name, name))
if (!strcmp(tp->name, name)) return tp->content;
return tp->content; }
}
return 0;
return 0; }
}
void tooltip_clear(void);
void tooltip_clear(void);
void tooltip_show(const char* name, float xpos, float ypos) {
void tooltip_show(const char* name, float xpos, float ypos) { if (!tooltips) return;
if (!tooltips) return;
tooltip *desc = tooltip_find_desc(name);
tooltip *desc = tooltip_find_desc(name); if (!name) return;
if (!name) return;
tooltip_clear();
tooltip_clear();
main_tooltip = (tooltip_node) {
main_tooltip = (tooltip_node) { .xpos = xpos,
.xpos = xpos, .ypos = ypos,
.ypos = ypos, .desc = desc,
.desc = desc, .next = 0
.next = 0 };
}; }
}
void tooltip_show_cursor(const char* name) {
void tooltip_show_cursor(const char* name) { Vector2 mpos = GetMousePosition();
Vector2 mpos = GetMousePosition(); tooltip_show(name, mpos.x + 15, mpos.y + 15);
tooltip_show(name, mpos.x + 15, mpos.y + 15); }
}
void tooltip__clear_node(tooltip_node *node) {
void tooltip__clear_node(tooltip_node *node) { if (node->next) {
if (node->next) { tooltip__clear_node(node->next);
tooltip__clear_node(node->next); zpl_mfree(node->next);
zpl_mfree(node->next); }
} }
}
void tooltip_clear(void) {
void tooltip_clear(void) { tooltip__clear_node(&main_tooltip);
tooltip__clear_node(&main_tooltip); main_tooltip = (tooltip_node) {0};
main_tooltip = (tooltip_node) {0}; }
}
void tooltip_draw_contents(tooltip *desc) {
void tooltip_draw_contents(tooltip *desc) { if (!desc) return;
if (!desc) return; nk_layout_row_dynamic(game_ui, 0, 1);
nk_layout_row_dynamic(game_ui, 0, 1); nk_label_wrap(game_ui, desc->content);
nk_label_wrap(game_ui, desc->content); }
}
void tooltip__draw_node(tooltip_node *node) {
void tooltip__draw_node(tooltip_node *node) { if (!node) return;
if (!node) return; if (!node->desc) return;
if (!node->desc) return;
tooltip *desc = node->desc;
tooltip *desc = node->desc; Vector2 mpos = GetMousePosition();
Vector2 mpos = GetMousePosition();
if (nk_begin_titled(game_ui, zpl_bprintf("%d%s", (int)node->xpos, desc->name), desc->name, nk_rect(node->xpos, node->ypos, 500, 3200),
if (nk_begin_titled(game_ui, zpl_bprintf("%d%s", (int)node->xpos, desc->name), desc->name, nk_rect(node->xpos, node->ypos, 500, 3200), NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_DYNAMIC | NK_WINDOW_TITLE | NK_WINDOW_MOVABLE)) {
NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR | NK_WINDOW_DYNAMIC | NK_WINDOW_TITLE | NK_WINDOW_MOVABLE)) { tooltip_draw_contents(desc);
tooltip_draw_contents(desc);
if (desc->links) {
if (desc->links) { nk_label(game_ui, "See Also:", NK_TEXT_LEFT);
nk_label(game_ui, "See Also:", NK_TEXT_LEFT); nk_layout_row_dynamic(game_ui, 20, 2);
nk_layout_row_dynamic(game_ui, 20, 2);
for (zpl_isize i = 0; i < zpl_array_count(desc->links); ++i) {
for (zpl_isize i = 0; i < zpl_array_count(desc->links); ++i) { if (nk_button_label(game_ui, desc->links[i])) {
if (nk_button_label(game_ui, desc->links[i])) { if (node->next) tooltip__clear_node(node->next);
if (node->next) tooltip__clear_node(node->next); if (!node->next) node->next = zpl_malloc(sizeof(tooltip_node));
if (!node->next) node->next = zpl_malloc(sizeof(tooltip_node)); *node->next = (tooltip_node) {
*node->next = (tooltip_node) { .xpos = mpos.x+15,
.xpos = mpos.x+15, .ypos = mpos.y+15,
.ypos = mpos.y+15, .desc = tooltip_find_desc(desc->links[i]),
.desc = tooltip_find_desc(desc->links[i]), .next = 0
.next = 0 };
}; }
} }
} }
}
// suggest closing tooltip
// suggest closing tooltip struct nk_vec2 wpos = nk_window_get_position(game_ui);
struct nk_vec2 wpos = nk_window_get_position(game_ui); struct nk_vec2 wsize = nk_window_get_content_region_size(game_ui);
struct nk_vec2 wsize = nk_window_get_content_region_size(game_ui); struct nk_panel *wpanel = nk_window_get_panel(game_ui);
struct nk_panel *wpanel = nk_window_get_panel(game_ui); Vector2 tp_pos = (Vector2) { .x = wpos.x + wsize.x/2.0f, .y = wpos.y + wpanel->row.height / 2.0f };
Vector2 tp_pos = (Vector2) { .x = wpos.x + wsize.x/2.0f, .y = wpos.y + wpanel->row.height / 2.0f }; if (Vector2Distance(mpos, tp_pos) <= TOOLTIP_MOUSE_DIST) {
if (Vector2Distance(mpos, tp_pos) <= TOOLTIP_MOUSE_DIST) { tooltip__should_stay_open = true;
tooltip__should_stay_open = true; }
}
#if 0
#if 0 {
{ DrawCircleV(tp_pos, TOOLTIP_MOUSE_DIST, BLUE);
DrawCircleV(tp_pos, TOOLTIP_MOUSE_DIST, BLUE); }
} #endif
#endif
nk_end(game_ui);
nk_end(game_ui);
// draw nested tooltip
// draw nested tooltip if (node->next) {
if (node->next) { tooltip__draw_node(node->next);
tooltip__draw_node(node->next); }
} }
} }
}
void tooltip_draw(void) {
void tooltip_draw(void) { // draw tooltip
// draw tooltip tooltip__draw_node(&main_tooltip);
tooltip__draw_node(&main_tooltip);
if (!tooltip__should_stay_open) {
if (!tooltip__should_stay_open) { tooltip_clear();
tooltip_clear(); }
}
tooltip__should_stay_open = false;
tooltip__should_stay_open = false;
// draw search bar
// draw search bar float width = (float)GetScreenWidth();
float width = (float)GetScreenWidth(); float height = (float)GetScreenHeight();
float height = (float)GetScreenHeight();
if (nk_begin(game_ui, "#searchbar", nk_rect(width / 2.0f - 200, 15.f, 400, 600), NK_WINDOW_DYNAMIC | NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR)) {
if (nk_begin(game_ui, "#searchbar", nk_rect(width / 2.0f - 200, 15.f, 400, 600), NK_WINDOW_DYNAMIC | NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR)) { {
{ static int len=0; static char buffer[256] = { 0 };
static int len=0; static char buffer[256] = { 0 };
static bool show_all = false;
static bool show_all = false;
if (len > 0) {
if (len > 0) { nk_layout_row_dynamic(game_ui, 15, 1);
nk_layout_row_dynamic(game_ui, 15, 1); if (nk_button_label(game_ui, "clear all")) {
if (nk_button_label(game_ui, "clear all")) { len = 0;
len = 0; }
} }
}
nk_layout_row_dynamic(game_ui, 35, 1);
nk_layout_row_dynamic(game_ui, 35, 1);
if (!(nk_edit_string(game_ui, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_ascii) & NK_WIDGET_STATE_ACTIVE) && len == 0 ) {
if (!(nk_edit_string(game_ui, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_ascii) & NK_WIDGET_STATE_ACTIVE) && len == 0 ) { show_all = true;
show_all = true; }
} buffer[len] = 0;
buffer[len] = 0;
if (len > 0 || show_all) {
if (len > 0 || show_all) { if (nk_tree_push(game_ui, NK_TREE_TAB, "results", NK_MAXIMIZED)) {
if (nk_tree_push(game_ui, NK_TREE_TAB, "results", NK_MAXIMIZED)) { for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) {
for (zpl_isize i = 0; i < zpl_array_count(tooltips); ++i) { tooltip *tp = (tooltips + i);
tooltip *tp = (tooltips + i);
if (strstr(tp->name, buffer) || show_all) {
if (strstr(tp->name, buffer) || show_all) { if (nk_button_label(game_ui, tp->name)) {
if (nk_button_label(game_ui, tp->name)) { tooltip_show_cursor(tp->name);
tooltip_show_cursor(tp->name); }
} }
} }
} nk_tree_pop(game_ui);
nk_tree_pop(game_ui); }
} }
}
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) || len > 0) {
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) || len > 0) { show_all = false;
show_all = false; }
} }
} nk_end(game_ui);
nk_end(game_ui); }
} }
}

View File

@ -44,7 +44,6 @@ void entity_default_spawnlist(void) {
entity_add_spawndef(ASSET_SPLITTER, splitter_spawn); entity_add_spawndef(ASSET_SPLITTER, splitter_spawn);
entity_add_spawndef(ASSET_ASSEMBLER, assembler_spawn); entity_add_spawndef(ASSET_ASSEMBLER, assembler_spawn);
entity_add_spawndef(ASSET_CREATURE, creature_spawn); entity_add_spawndef(ASSET_CREATURE, creature_spawn);
entity_add_spawndef(ASSET_MOB, mob_spawn);
entity_add_spawndef_data(ASSET_BLUEPRINT, blueprint_spawn_udata); entity_add_spawndef_data(ASSET_BLUEPRINT, blueprint_spawn_udata);
} }

View File

@ -118,13 +118,3 @@ uint64_t storage_spawn(void) {
//------------------------------------------------------------------------ //------------------------------------------------------------------------
uint64_t mob_spawn(void) {
ecs_entity_t e = entity_spawn(EKIND_MONSTER);
ecs_add(world_ecs(), e, Mob);
ecs_set(world_ecs(), e, Health, { 60, 60, 0 });
ecs_set(world_ecs(), e, PhysicsBody, { .kind = PHYS_AABB, .mass = 1.0f });
ecs_set(world_ecs(), e, Sprite, { .frame = 101 + (rand()%3) });
return (uint64_t)e;
}

View File

@ -83,8 +83,23 @@ void mob_systems(ecs_world_t *ecs) {
ECS_OBSERVER(ecs, MobOnDead, EcsOnAdd, components.Mob, components.Sprite, components.Velocity, components.Dead); ECS_OBSERVER(ecs, MobOnDead, EcsOnAdd, components.Mob, components.Sprite, components.Velocity, components.Dead);
} }
void game_init(bool new_db) { uint64_t mob_spawn(void) {
ecs_entity_t e = entity_spawn(EKIND_MONSTER);
ecs_add(world_ecs(), e, Mob);
ecs_set(world_ecs(), e, Health, { 60, 60, 0 });
ecs_set(world_ecs(), e, PhysicsBody, { .kind = PHYS_AABB, .mass = 1.0f });
ecs_set(world_ecs(), e, Sprite, { .frame = 101 + (rand()%3) });
return (uint64_t)e;
}
void game_init(bool new_db) {
if (new_db) {
assets_new("MOB");
}
entity_add_spawndef(ASSET_MOB, mob_spawn);
} }
void game_input() { void game_input() {

View File

@ -1,7 +1,11 @@
#pragma once #pragma once
enum { enum {
SURV_CODE_SHOW_NOTIF, SURV_CODE_SHOW_NOTIF,
}; };
void game_setup_ecs(); enum {
ASSET_MOB = NEXT_FREE_ASSET,
};
void game_setup_ecs();

View File

@ -2,10 +2,14 @@
#include "world/world.h" #include "world/world.h"
#include "zpl.h" #include "zpl.h"
#include "utils/raylib_helpers.h" #include "utils/raylib_helpers.h"
#include "game.h"
Texture2D texgen_build_anim(asset_id id, int64_t counter) { Texture2D texgen_build_anim(asset_id id, int64_t counter) {
(void)counter; (void)counter;
switch (id) { switch (id) {
// Mobs
case ASSET_MOB: return LoadTexEco("enemy1");
default: return texgen_build_anim_fallback(id, counter); break; default: return texgen_build_anim_fallback(id, counter); break;
} }
} }