improve prediction code + layer updates
parent
074a3c601f
commit
7c39e51a07
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
#include "entity_view.h"
|
||||
|
||||
float smooth_val(float cur, float tgt, float dt);
|
||||
float smooth_val(float cur, float tgt, uint64_t dt);
|
||||
void predict_receive_update(entity_view *d, entity_view *data);
|
|
@ -14,6 +14,11 @@ typedef struct {
|
|||
uint16_t block_size;
|
||||
uint16_t chunk_size;
|
||||
uint16_t chunk_amount;
|
||||
|
||||
// NOTE(zaklaus): metrics
|
||||
uint64_t last_update[WORLD_TRACKER_LAYERS];
|
||||
uint64_t delta_time[WORLD_TRACKER_LAYERS];
|
||||
uint8_t active_layer_id;
|
||||
} world_view;
|
||||
|
||||
world_view world_view_create(uint16_t view_id);
|
||||
|
|
|
@ -114,7 +114,6 @@ void platform_input() {
|
|||
y = mouse_pos.y;
|
||||
}
|
||||
|
||||
|
||||
game_action_send_keystate(x, y, use, sprint);
|
||||
}
|
||||
|
||||
|
@ -236,7 +235,12 @@ void lerp_entity_positions(uint64_t key, entity_view data) {
|
|||
if (data.flag == EFLAG_INTERP) {
|
||||
entity_view *e = entity_view_get(&view->entities, key);
|
||||
|
||||
e->x = smooth_val(e->x, e->tx, 0);
|
||||
e->y = smooth_val(e->y, e->ty, 0);
|
||||
#if 1
|
||||
e->x = smooth_val(e->x, e->tx, view->delta_time[e->layer_id]);
|
||||
e->y = smooth_val(e->y, e->ty, view->delta_time[e->layer_id]);
|
||||
#else
|
||||
e->x = e->tx;
|
||||
e->y = e->ty;
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,12 +1,27 @@
|
|||
#include "zpl.h"
|
||||
#include "prediction.h"
|
||||
#include "world/world.h"
|
||||
#include "game.h"
|
||||
|
||||
#define PREDICT_SMOOTH_FACTOR_LO 0.8
|
||||
#define PREDICT_SMOOTH_FACTOR_HI 0.12
|
||||
#define PREDICT_SMOOTH_FACTOR_LO 0.80
|
||||
#define PREDICT_SMOOTH_FACTOR_HI 0.007
|
||||
|
||||
float smooth_val(float cur, float tgt, float dt) {
|
||||
return zpl_lerp(cur, tgt, zpl_lerp(PREDICT_SMOOTH_FACTOR_HI, PREDICT_SMOOTH_FACTOR_LO, zpl_unlerp(dt, WORLD_TRACKER_UPDATE_FAST_MS, WORLD_TRACKER_UPDATE_SLOW_MS)));
|
||||
static inline float map_factor(float x) {
|
||||
x = 1.0f - zpl_clamp01(x);
|
||||
return 1.0f - x*x*x*x*x*x*x*x;
|
||||
}
|
||||
|
||||
float smooth_val(float cur, float tgt, uint64_t dt) {
|
||||
float factor = zpl_clamp01(map_factor(zpl_unlerp(dt, WORLD_TRACKER_UPDATE_FAST_MS, WORLD_TRACKER_UPDATE_SLOW_MS)));
|
||||
|
||||
#if 0
|
||||
dt = 200;
|
||||
factor = map_factor(zpl_unlerp(dt, WORLD_TRACKER_UPDATE_FAST_MS, WORLD_TRACKER_UPDATE_SLOW_MS));
|
||||
zpl_printf("lerp factor: %f\n", factor);
|
||||
zpl_exit(0);
|
||||
#endif
|
||||
|
||||
return zpl_lerp(cur, tgt, zpl_lerp(PREDICT_SMOOTH_FACTOR_LO, PREDICT_SMOOTH_FACTOR_HI, factor));
|
||||
}
|
||||
|
||||
void predict_receive_update(entity_view *d, entity_view *data) {
|
||||
|
|
|
@ -9,6 +9,11 @@ int32_t tracker_read_remove(librg_world *w, librg_event *e) {
|
|||
int64_t entity_id = librg_event_entity_get(w, e);
|
||||
zpl_printf("[INFO] An entity %d was removed for owner: %d\n", (int)entity_id, (int)owner_id);
|
||||
world_view *view = (world_view*)librg_world_userdata_get(w);
|
||||
entity_view *d = entity_view_get(&view->entities, entity_id);
|
||||
if (d && d->layer_id < view->active_layer_id) {
|
||||
// NOTE(zaklaus): reject updates from slower layers
|
||||
return 0;
|
||||
}
|
||||
|
||||
entity_view_destroy(&view->entities, entity_id);
|
||||
return 0;
|
||||
|
@ -22,6 +27,11 @@ int32_t tracker_read_update(librg_world *w, librg_event *e) {
|
|||
|
||||
entity_view data = entity_view_unpack_struct(buffer, actual_length);
|
||||
entity_view *d = entity_view_get(&view->entities, entity_id);
|
||||
data.layer_id = view->active_layer_id;
|
||||
if (d && d->layer_id < data.layer_id) {
|
||||
// NOTE(zaklaus): reject updates from slower layers
|
||||
return 0;
|
||||
}
|
||||
predict_receive_update(d, &data);
|
||||
entity_view_update_or_create(&view->entities, entity_id, data);
|
||||
return 0;
|
||||
|
@ -36,6 +46,7 @@ int32_t tracker_read_create(librg_world *w, librg_event *e) {
|
|||
world_view *view = (world_view*)librg_world_userdata_get(w);
|
||||
|
||||
entity_view data = entity_view_unpack_struct(buffer, actual_length);
|
||||
data.layer_id = view->active_layer_id;
|
||||
if (data.flag & EFLAG_INTERP) {
|
||||
data.tx = data.x;
|
||||
data.ty = data.y;
|
||||
|
@ -57,7 +68,6 @@ void world_view_init(world_view *view, uint64_t ent_id, uint16_t block_size, uin
|
|||
view->block_size = block_size;
|
||||
view->chunk_size = chunk_size;
|
||||
view->chunk_amount = chunk_amount;
|
||||
|
||||
view->dim = block_size * chunk_size * chunk_amount;
|
||||
view->size = view->dim * view->dim;
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ typedef struct entity_view {
|
|||
float vy;
|
||||
float tx;
|
||||
float ty;
|
||||
|
||||
// NOTE(zaklaus): internals
|
||||
uint8_t layer_id;
|
||||
} entity_view;
|
||||
|
||||
ZPL_TABLE_DECLARE(, entity_view_tbl, entity_view_tbl_, entity_view);
|
||||
|
|
|
@ -1,27 +1,41 @@
|
|||
#include "zpl.h"
|
||||
#include "packet_utils.h"
|
||||
#include "packets/pkt_send_librg_update.h"
|
||||
#include "world/world.h"
|
||||
#include "game.h"
|
||||
|
||||
size_t pkt_send_librg_update_encode(void *data, int32_t data_length) {
|
||||
size_t pkt_send_librg_update_encode(void *data, int32_t data_length, uint8_t layer_id) {
|
||||
cw_pack_context pc = {0};
|
||||
pkt_pack_msg(&pc, 1);
|
||||
pkt_pack_msg(&pc, 2);
|
||||
cw_pack_unsigned(&pc, layer_id);
|
||||
cw_pack_bin(&pc, data, data_length);
|
||||
return pkt_pack_msg_size(&pc);
|
||||
}
|
||||
|
||||
int32_t pkt_send_librg_update_handler(pkt_header *header) {
|
||||
cw_unpack_context uc = {0};
|
||||
pkt_unpack_msg(&uc, header, 1);
|
||||
pkt_unpack_msg(&uc, header, 2);
|
||||
cw_unpack_next(&uc);
|
||||
|
||||
if (uc.item.type != CWP_ITEM_POSITIVE_INTEGER)
|
||||
return -1;
|
||||
|
||||
uint8_t layer_id = (uint8_t)uc.item.as.u64;
|
||||
|
||||
cw_unpack_next(&uc);
|
||||
|
||||
if (uc.item.type != CWP_ITEM_BIN)
|
||||
return -1;
|
||||
|
||||
world_view *view = game_world_view_get(header->view_id);
|
||||
view->active_layer_id = layer_id;
|
||||
|
||||
int32_t state = librg_world_read(view->tracker, header->view_id, uc.item.as.bin.start, uc.item.as.bin.length, NULL);
|
||||
if (state < 0) zpl_printf("[ERROR] world read error: %d\n", state);
|
||||
|
||||
uint64_t now = zpl_time_rel_ms();
|
||||
view->delta_time[layer_id] = now - view->last_update[layer_id];
|
||||
view->last_update[layer_id] = now;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ int32_t world_destroy(void) {
|
|||
|
||||
#define WORLD_LIBRG_BUFSIZ 2000000
|
||||
|
||||
static void world_tracker_update(uint8_t ticker, uint8_t freq, uint8_t radius) {
|
||||
static void world_tracker_update(uint8_t ticker, uint32_t freq, uint8_t radius) {
|
||||
if (world.tracker_update[ticker] > zpl_time_rel_ms()) return;
|
||||
world.tracker_update[ticker] = zpl_time_rel_ms() + freq;
|
||||
|
||||
|
@ -178,7 +178,7 @@ static void world_tracker_update(uint8_t ticker, uint8_t freq, uint8_t radius) {
|
|||
zpl_printf("[error] an error happened writing the world %d\n", result);
|
||||
}
|
||||
|
||||
pkt_world_write(MSG_ID_LIBRG_UPDATE, pkt_send_librg_update_encode(buffer, datalen), 1, p[i].view_id, p[i].peer);
|
||||
pkt_world_write(MSG_ID_LIBRG_UPDATE, pkt_send_librg_update_encode(buffer, datalen, ticker), 1, p[i].view_id, p[i].peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,10 @@
|
|||
#define WORLD_ERROR_INVALID_BUFFER -0x0004
|
||||
#define WORLD_ERROR_TRACKER_FAILED -0x0005
|
||||
|
||||
#define WORLD_TRACKER_LAYERS 3
|
||||
#define WORLD_TRACKER_UPDATE_FAST_MS 10
|
||||
#define WORLD_TRACKER_UPDATE_NORMAL_MS 100
|
||||
#define WORLD_TRACKER_UPDATE_SLOW_MS 800
|
||||
#define WORLD_TRACKER_UPDATE_SLOW_MS 400
|
||||
|
||||
#define WORLD_PKT_READER(name) int32_t name(void* data, uint32_t datalen, void *udata)
|
||||
typedef WORLD_PKT_READER(world_pkt_reader_proc);
|
||||
|
|
Loading…
Reference in New Issue