chunk streaming alpha transition

isolation_bkp/dynres
Dominik Madarász 2021-05-10 00:40:25 +02:00
parent db0517eb3f
commit 68f274580a
9 changed files with 123 additions and 40 deletions

View File

@ -86,7 +86,7 @@ void game_world_view_set_active_by_idx(uint16_t idx) {
game_world_view_set_active(&world_viewers[idx]);
}
void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_view value)) {
void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_view * value)) {
entity_view_map(&active_viewer->entities, map_proc);
}
@ -154,6 +154,8 @@ void game_update() {
network_client_tick();
}
else world_update();
game_world_cleanup_entities();
}
void game_render() {
@ -162,4 +164,20 @@ void game_render() {
void game_action_send_keystate(float x, float y, uint8_t use, uint8_t sprint) {
pkt_send_keystate_send(active_viewer->view_id, x, y, use, sprint);
}
void game_world_cleanup_entities(void) {
for (int i = 0; i < zpl_buffer_count(world_viewers); i += 1){
entity_view_tbl *view = &world_viewers[i].entities;
for (int j = 0; j < zpl_array_count(view->entries); j += 1){
entity_view *e = &view->entries[j];
if (e->tran_effect == ETRAN_REMOVE) {
entity_view_tbl_remove(view, e->ent_id);
j--;
}
}
}
}

View File

@ -16,7 +16,7 @@
#define DEFAULT_WORLD_SEED 302097
#define DEFAULT_BLOCK_SIZE 16 /* amount of units within a block (single axis) */
#define DEFAULT_CHUNK_SIZE 16 /* amount of blocks within a chunk (single axis) */
#define DEFAULT_WORLD_SIZE 8 /* amount of chunks within a world (single axis) */
#define DEFAULT_WORLD_SIZE 32 /* amount of chunks within a world (single axis) */
int main(int argc, char** argv)
{
@ -50,7 +50,7 @@ int main(int argc, char** argv)
uint16_t block_size = zpl_opts_integer(&opts, "block-size", DEFAULT_BLOCK_SIZE);
uint16_t chunk_size = zpl_opts_integer(&opts, "chunk-size", DEFAULT_CHUNK_SIZE);
uint16_t world_size = zpl_opts_integer(&opts, "world-size", DEFAULT_WORLD_SIZE);
uint32_t npc_count = zpl_opts_integer(&opts, "npc-count", 100);
uint32_t npc_count = zpl_opts_integer(&opts, "npc-count", 1000);
if (zpl_opts_has_arg(&opts, "random-seed")) {
zpl_random rnd={0};

View File

@ -129,15 +129,17 @@ void platform_input() {
void display_conn_status();
void DEBUG_draw_entities(uint64_t key, entity_view data);
void DEBUG_draw_ground(uint64_t key, entity_view data);
void DEBUG_draw_entities(uint64_t key, entity_view * data);
void DEBUG_draw_ground(uint64_t key, entity_view * data);
void lerp_entity_positions(uint64_t key, entity_view data);
void lerp_entity_positions(uint64_t key, entity_view * data);
void do_entity_fadeinout(uint64_t key, entity_view * data);
float zpl_lerp(float,float,float);
void platform_render() {
game_world_view_active_entity_map(lerp_entity_positions);
game_world_view_active_entity_map(do_entity_fadeinout);
render_camera.zoom = zpl_lerp(render_camera.zoom, target_zoom, 0.18);
camera_update();
@ -163,14 +165,13 @@ void display_conn_status() {
}
} else {
DrawText("Connection: single-player", 5, 5, 12, BLUE);
//DrawText("Connection: ", 5, 5, 52, BLUE);
}
DrawFPS(0, 20);
}
void DEBUG_draw_ground(uint64_t key, entity_view data) {
switch (data.kind) {
void DEBUG_draw_ground(uint64_t key, entity_view * data) {
switch (data->kind) {
case EKIND_CHUNK: {
world_view *view = game_world_view_get_active();
int32_t size = view->chunk_size * view->block_size;
@ -180,10 +181,10 @@ void DEBUG_draw_ground(uint64_t key, entity_view data) {
float block_spacing = (float)block_size * (size/(float)(chunk_size*block_size));
float block_offset = size - block_spacing*chunk_size;
double x = data.x * size + offset;
double y = data.y * size + offset;
DrawRectangleEco((int)x-offset, (int)y-offset, size+offset, size+offset, BLACK);
DrawRectangleEco((int)x, (int)y, size-offset, size-offset, LIME);
float x = data->x * size + offset;
float y = data->y * size + offset;
DrawRectangleEco(x-offset, y-offset, size+offset, size+offset, ColorAlpha(BLACK, data->tran_time));
DrawRectangleEco(x, y, size-offset, size-offset, ColorAlpha(LIME, data->tran_time));
#if 0
for (uint16_t i = 0; i < chunk_size*chunk_size; i++) {
@ -193,7 +194,7 @@ void DEBUG_draw_ground(uint64_t key, entity_view data) {
}
#endif
DrawTextEco(TextFormat("%.01f %.01f", data.x, data.y), (int16_t)x+15, (int16_t)y+15, 65 , BLACK, 0.0);
DrawTextEco(TextFormat("%d %d", (int)data->x, (int)data->y), (int16_t)x+15, (int16_t)y+15, 65 , ColorAlpha(BLACK, data->tran_time), 0.0);
}break;
default:break;
@ -202,32 +203,31 @@ void DEBUG_draw_ground(uint64_t key, entity_view data) {
static inline float lerp(float a, float b, float t) { return a * (1.0f - t) + b * t; }
void DEBUG_draw_entities(uint64_t key, entity_view data) {
world_view *view = game_world_view_get_active();
void DEBUG_draw_entities(uint64_t key, entity_view * data) {
uint16_t size = 4;
uint16_t font_size = (uint16_t)lerp(4.0f, 32.0f, 0.5f/(float)render_camera.zoom);
float font_spacing = 1.1f;
float title_bg_offset = 4;
float fixed_title_offset = 2;
switch (data.kind) {
switch (data->kind) {
case EKIND_THING: {
double x = data.x;
double y = data.y;
float x = data->x;
float y = data->y;
const char *title = TextFormat("Thing %d", key);
int title_w = MeasureTextEco(title, font_size, font_spacing);
DrawRectangleEco(x-title_w/2-title_bg_offset/2, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, BLACK);
DrawTextEco(title, x-title_w/2, y-size-font_size-fixed_title_offset, font_size, RAYWHITE, font_spacing);
DrawCircleEco(x, y, size, BLUE);
DrawRectangleEco(x-title_w/2-title_bg_offset/2, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, ColorAlpha(BLACK, data->tran_time));
DrawTextEco(title, x-title_w/2, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(RAYWHITE, data->tran_time), font_spacing);
DrawCircleEco(x, y, size, ColorAlpha(BLUE, data->tran_time));
}break;
case EKIND_PLAYER: {
double x = data.x;
double y = data.y;
float x = data->x;
float y = data->y;
const char *title = TextFormat("Player %d", key);
int title_w = MeasureTextEco(title, font_size, font_spacing);
DrawRectangleEco(x-title_w/2-title_bg_offset/2, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, BLACK);
DrawTextEco(title, x-title_w/2, y-size-font_size-fixed_title_offset, font_size, RAYWHITE, font_spacing);
DrawCircleEco(x, y, size, RED);
DrawRectangleEco(x-title_w/2-title_bg_offset/2, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, ColorAlpha(BLACK, data->tran_time));
DrawTextEco(title, x-title_w/2, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(RAYWHITE, data->tran_time), font_spacing);
DrawCircleEco(x, y, size, ColorAlpha(RED, data->tran_time));
}break;
default:break;
}
@ -247,4 +247,28 @@ void lerp_entity_positions(uint64_t key, entity_view data) {
e->y = e->ty;
#endif
}
}
void do_entity_fadeinout(uint64_t key, entity_view * data) {
switch (data->tran_effect) {
case ETRAN_FADEIN: {
data->tran_time += GetFrameTime();
if (data->tran_time > 1.0f) {
data->tran_effect = ETRAN_NONE;
data->tran_time = 1.0f;
}
}break;
case ETRAN_FADEOUT: {
data->tran_time -= GetFrameTime();
if (data->tran_time < 0.0f) {
data->tran_effect = ETRAN_REMOVE;
data->tran_time = 0.0f;
}
}break;
default: break;
}
}

View File

@ -34,4 +34,8 @@ void predict_receive_update(entity_view *d, entity_view *data) {
data->tx = tx;
data->ty = ty;
}
data->tran_effect = d->tran_effect;
data->tran_time = d->tran_time;
zpl_printf("? %f\n", d->tran_time);
}

View File

@ -8,7 +8,7 @@
int32_t tracker_read_remove(librg_world *w, librg_event *e) {
int64_t entity_id = librg_event_entity_get(w, e);
world_view *view = (world_view*)librg_world_userdata_get(w);
entity_view_destroy(&view->entities, entity_id);
entity_view_mark_for_removal(&view->entities, entity_id);
return 0;
}
@ -42,19 +42,17 @@ int32_t tracker_read_create(librg_world *w, librg_event *e) {
size_t actual_length = librg_event_size_get(w, e);
char *buffer = librg_event_buffer_get(w, e);
world_view *view = (world_view*)librg_world_userdata_get(w);
#ifdef WORLD_LAYERING
if (view->active_layer_id != WORLD_TRACKER_LAYERS-1) {
// NOTE(zaklaus): reject updates from smaller layers
return 0;
}
#endif
entity_view data = entity_view_unpack_struct(buffer, actual_length);
data.ent_id = entity_id;
data.layer_id = view->active_layer_id;
data.tran_time = 0.0f;
if (data.flag & EFLAG_INTERP) {
data.tx = data.x;
data.ty = data.y;
}
entity_view_update_or_create(&view->entities, entity_id, data);
entity_view_mark_for_fadein(&view->entities, entity_id);
return 0;
}

View File

@ -50,6 +50,18 @@ entity_view *entity_view_get(entity_view_tbl *map, uint64_t ent_id) {
return entity_view_tbl_get(map, ent_id);
}
void entity_view_map(entity_view_tbl *map, void (*map_proc)(uint64_t key, entity_view value)) {
entity_view_tbl_map(map, map_proc);
void entity_view_map(entity_view_tbl *map, void (*map_proc)(uint64_t key, entity_view * value)) {
entity_view_tbl_map_mut(map, map_proc);
}
void entity_view_mark_for_removal(entity_view_tbl *map, uint64_t ent_id) {
entity_view *view = entity_view_tbl_get(map, ent_id);
view->tran_effect = ETRAN_FADEOUT;
view->tran_time = 1.0f;
}
void entity_view_mark_for_fadein(entity_view_tbl *map, uint64_t ent_id) {
entity_view *view = entity_view_tbl_get(map, ent_id);
view->tran_effect = ETRAN_FADEIN;
view->tran_time = 0.0f;
}

View File

@ -18,7 +18,16 @@ typedef enum {
FORCE_EFLAG_UINT16 = UINT16_MAX
} entity_flag;
typedef enum {
ETRAN_NONE,
ETRAN_FADEOUT,
ETRAN_FADEIN,
ETRAN_REMOVE,
FORCE_ETRAN_UINT8 = UINT8_MAX
} entity_transition_effect;
typedef struct entity_view {
int64_t ent_id;
entity_kind kind;
entity_flag flag;
float x;
@ -31,6 +40,10 @@ typedef struct entity_view {
// NOTE(zaklaus): internals
uint8_t layer_id;
uint64_t last_update;
// NOTE(zaklaus): fade in-out effect
entity_transition_effect tran_effect;
float tran_time;
} entity_view;
ZPL_TABLE_DECLARE(, entity_view_tbl, entity_view_tbl_, entity_view);
@ -44,7 +57,10 @@ void entity_view_update_or_create(entity_view_tbl *map, uint64_t ent_id, entity_
void entity_view_destroy(entity_view_tbl *map, uint64_t ent_id);
entity_view *entity_view_get(entity_view_tbl *map, uint64_t ent_id);
void entity_view_map(entity_view_tbl *map, void (*map_proc)(uint64_t key, entity_view value));
void entity_view_map(entity_view_tbl *map, void (*map_proc)(uint64_t key, entity_view * value));
size_t entity_view_pack_struct(void *data, size_t len, entity_view view);
entity_view entity_view_unpack_struct(void *data, size_t len);
void entity_view_mark_for_removal(entity_view_tbl *map, uint64_t ent_id);
void entity_view_mark_for_fadein(entity_view_tbl *map, uint64_t ent_id);

View File

@ -18,7 +18,8 @@ world_view *game_world_view_get(uint16_t idx);
void game_world_view_set_active_by_idx(uint16_t idx);
void game_world_view_set_active(world_view *view);
void game_world_view_cycle_active(uint8_t dir);
void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_view value));
void game_world_view_active_entity_map(void (*map_proc)(uint64_t key, entity_view * value));
void game_world_cleanup_entities(void);
//~ NOTE(zaklaus): viewer -> host actions
void game_action_send_keystate(float x, float y, uint8_t use, uint8_t sprint);

14
code/vendors/zpl.h vendored
View File

@ -31,6 +31,8 @@ GitHub:
https://github.com/zpl-c/zpl
Version History:
14.1.0 - add hashtable map_mut method
14.0.1 - fix zpl_array_remove_at boundary bug
14.0.0 - heap memory allocator analysis
13.4.1 - adt optimizations
@ -358,8 +360,8 @@ License:
#define ZPL_H
#define ZPL_VERSION_MAJOR 14
#define ZPL_VERSION_MINOR 0
#define ZPL_VERSION_PATCH 2
#define ZPL_VERSION_MINOR 1
#define ZPL_VERSION_PATCH 0
#define ZPL_VERSION_PRE ""
// file: zpl_hedley.h
@ -4299,6 +4301,7 @@ License:
PREFIX void ZPL_JOIN2(FUNC, grow)(NAME * h); \
PREFIX void ZPL_JOIN2(FUNC, rehash)(NAME * h, zpl_isize new_count); \
PREFIX void ZPL_JOIN2(FUNC, map)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE value)); \
PREFIX void ZPL_JOIN2(FUNC, map_mut)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE * value)); \
PREFIX void ZPL_JOIN2(FUNC, remove)(NAME * h, zpl_u64 key);
#define ZPL_TABLE_DEFINE(NAME, FUNC, VALUE) \
@ -4397,6 +4400,13 @@ License:
map_proc(h->entries[i].key, h->entries[i].value); \
} \
} \
void ZPL_JOIN2(FUNC, map_mut)(NAME * h, void (*map_proc)(zpl_u64 key, VALUE * value)) { \
ZPL_ASSERT_NOT_NULL(h); \
ZPL_ASSERT_NOT_NULL(map_proc); \
for (zpl_isize i = 0; i < zpl_array_count(h->entries); ++i) { \
map_proc(h->entries[i].key, &h->entries[i].value); \
} \
} \
\
void ZPL_JOIN2(FUNC, set)(NAME * h, zpl_u64 key, VALUE value) { \
zpl_isize index; \