From 25e9b9e57ede7eb92a7a0fa0f0ea983116c454e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Mon, 30 Aug 2021 11:59:36 +0200 Subject: [PATCH] code: add 2nd world layer --- code/game/src/debug_replay.c | 5 +++++ code/game/src/debug_ui.c | 1 + code/game/src/debug_ui_actions.c | 18 +++++++++++++++- code/game/src/entity_view.c | 5 +++-- code/game/src/entity_view.h | 1 + code/game/src/renderer_bridge.c | 2 +- code/game/src/world/blocks.c | 8 +++++-- code/game/src/world/blocks.h | 2 +- code/game/src/world/blocks_info.h | 1 + code/game/src/world/blocks_list.c | 1 + code/game/src/world/world.c | 31 +++++++++++++++++++++++++--- code/game/src/world/world.h | 2 ++ code/modules/source/system_demo.c | 2 +- code/modules/source/system_vehicle.c | 20 +++++++++--------- 14 files changed, 78 insertions(+), 21 deletions(-) diff --git a/code/game/src/debug_replay.c b/code/game/src/debug_replay.c index d2a8390..581216c 100644 --- a/code/game/src/debug_replay.c +++ b/code/game/src/debug_replay.c @@ -10,6 +10,7 @@ typedef enum { // NOTE(zaklaus): Special actions RPKIND_SPAWN_CAR, RPKIND_PLACE_ICE_RINK, + RPKIND_PLACE_ERASE_CHANGES, RPKIND_SPAWN_CIRCLING_DRIVER, } replay_kind; @@ -152,6 +153,7 @@ void debug_replay_run(void) { void ActPlaceIceRink(); void ActSpawnCirclingDriver(void); +void ActEraseWorldChanges(void); void debug_replay_update(void) { if (!is_playing) return; @@ -183,6 +185,9 @@ void debug_replay_update(void) { case RPKIND_SPAWN_CIRCLING_DRIVER: { ActSpawnCirclingDriver(); }break; + case RPKIND_PLACE_ERASE_CHANGES:{ + ActEraseWorldChanges(); + }break; default: { ZPL_PANIC("unreachable"); }break; diff --git a/code/game/src/debug_ui.c b/code/game/src/debug_ui.c index abb49f3..6f6c135 100644 --- a/code/game/src/debug_ui.c +++ b/code/game/src/debug_ui.c @@ -113,6 +113,7 @@ static debug_item items[] = { .items = (debug_item[]) { { .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar }, { .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink }, + { .kind = DITEM_BUTTON, .name = "erase world changes", .on_click = ActEraseWorldChanges }, { .kind = DITEM_BUTTON, .name = "spawn circling driver", .on_click = ActSpawnCirclingDriver }, { .kind = DITEM_BUTTON, .name = "spawn icemaker item", .on_click = ActSpawnIcemaker }, { diff --git a/code/game/src/debug_ui_actions.c b/code/game/src/debug_ui_actions.c index 985933e..276b705 100644 --- a/code/game/src/debug_ui_actions.c +++ b/code/game/src/debug_ui_actions.c @@ -63,13 +63,29 @@ ActPlaceIceRink(void) { for (int y = 0; y < 100; y++) { for (int x = 0; x < 100; x++) { world_block_lookup l = world_block_from_realpos((p->x - (x*bs)/2.0f), p->y - (y*bs)/2.0f); - world_chunk_replace_block(world_ecs(), l.chunk_id, l.id, watr_id); + world_chunk_replace_outer_block(world_ecs(), l.chunk_id, l.id, watr_id); } } debug_replay_special_action(RPKIND_PLACE_ICE_RINK); } +void +ActEraseWorldChanges(void) { + ecs_entity_t plr = camera_get().ent_id; + Position const *p = ecs_get(world_ecs(), plr, Position); + float const bs = WORLD_BLOCK_SIZE; + + for (int y = 0; y < 100; y++) { + for (int x = 0; x < 100; x++) { + world_block_lookup l = world_block_from_realpos((p->x - (x*bs)/2.0f), p->y - (y*bs)/2.0f); + world_chunk_replace_outer_block(world_ecs(), l.chunk_id, l.id, 0); + } + } + + debug_replay_special_action(RPKIND_PLACE_ERASE_CHANGES); +} + // NOTE(zaklaus): Replay system uint8_t diff --git a/code/game/src/entity_view.c b/code/game/src/entity_view.c index fac1a3f..7b2b4a5 100644 --- a/code/game/src/entity_view.c +++ b/code/game/src/entity_view.c @@ -15,8 +15,9 @@ pkt_desc pkt_entity_view_desc[] = { { PKT_HALF(entity_view, vx) }, { PKT_HALF(entity_view, vy) }, - { PKT_SKIP_IF(entity_view, blocks_used, 0, 1) }, // NOTE(zaklaus): skip blocks for anything else + { PKT_SKIP_IF(entity_view, blocks_used, 0, 2) }, // NOTE(zaklaus): skip blocks for anything else { PKT_ARRAY(entity_view, blocks) }, + { PKT_ARRAY(entity_view, outer_blocks) }, { PKT_KEEP_IF(entity_view, blocks_used, 0, 2) }, // NOTE(zaklaus): skip hp for chunks { PKT_HALF(entity_view, hp) }, @@ -96,7 +97,7 @@ void entity_view_mark_for_fadein(entity_view_tbl *map, uint64_t ent_id) { void entity_view_update_chunk_texture(entity_view_tbl *map, uint64_t ent_id, void *world_view) { entity_view *view = entity_view_tbl_get(map, ent_id); if (view->kind != EKIND_CHUNK) return; - blocks_build_chunk_tex(ent_id, view->blocks, sizeof(view->blocks), world_view); + blocks_build_chunk_tex(ent_id, view->blocks, view->outer_blocks, world_view); } void entity_view_remove_chunk_texture(entity_view_tbl *map, uint64_t ent_id) { diff --git a/code/game/src/entity_view.h b/code/game/src/entity_view.h index 4af337a..2f98358 100644 --- a/code/game/src/entity_view.h +++ b/code/game/src/entity_view.h @@ -47,6 +47,7 @@ typedef struct entity_view { // TODO(zaklaus): Find a way to stream dynamic arrays uint8_t blocks_used; uint8_t blocks[256]; + uint8_t outer_blocks[256]; uint32_t color; uint8_t is_dirty; int64_t tex; diff --git a/code/game/src/renderer_bridge.c b/code/game/src/renderer_bridge.c index 64611cc..dfe169c 100644 --- a/code/game/src/renderer_bridge.c +++ b/code/game/src/renderer_bridge.c @@ -69,7 +69,7 @@ void renderer_debug_draw(void) { void renderer_bake_chunk(uint64_t key, entity_view * data) { if (data->kind != EKIND_CHUNK) return; world_view *view = game_world_view_get_active(); - blocks_build_chunk_tex(key, data->blocks, sizeof(data->blocks), view); + blocks_build_chunk_tex(key, data->blocks, data->outer_blocks, view); } void renderer_switch(int kind) { diff --git a/code/game/src/world/blocks.c b/code/game/src/world/blocks.c index 4364161..2a62acb 100644 --- a/code/game/src/world/blocks.c +++ b/code/game/src/world/blocks.c @@ -96,8 +96,7 @@ void *blocks_get_img(uint8_t id) { return (void*)&blocks[id].img; } -void blocks_build_chunk_tex(uint64_t id, uint8_t *chunk_blocks, size_t blocks_len, void *raw_view) { - (void)blocks_len; +void blocks_build_chunk_tex(uint64_t id, uint8_t *chunk_blocks, uint8_t *outer_chunk_blocks, void *raw_view) { world_view *view = (world_view*)raw_view; uint16_t dims = WORLD_BLOCK_SIZE * view->chunk_size; RenderTexture2D canvas = LoadRenderTexture(dims, dims); @@ -118,6 +117,11 @@ void blocks_build_chunk_tex(uint64_t id, uint8_t *chunk_blocks, size_t blocks_le Rectangle src = {0, 0, WORLD_BLOCK_SIZE, WORLD_BLOCK_SIZE}; Rectangle dst = {x*WORLD_BLOCK_SIZE + half_block, y*WORLD_BLOCK_SIZE + half_block, WORLD_BLOCK_SIZE, WORLD_BLOCK_SIZE}; DrawTexturePro(blk, src, dst, (Vector2){half_block, half_block}, rot, WHITE); + + if (outer_chunk_blocks[(y*view->chunk_size)+x] != 0) { + Texture2D blk2 = blocks[outer_chunk_blocks[(y*view->chunk_size)+x]].img; + DrawTexturePro(blk2, src, dst, (Vector2){half_block, half_block}, rot, WHITE); + } #endif } } diff --git a/code/game/src/world/blocks.h b/code/game/src/world/blocks.h index 9dd0bee..7453729 100644 --- a/code/game/src/world/blocks.h +++ b/code/game/src/world/blocks.h @@ -27,6 +27,6 @@ float blocks_get_bounce(uint8_t id); // NOTE(zaklaus): viewer-related functions void *blocks_get_img(uint8_t id); -void blocks_build_chunk_tex(uint64_t id, uint8_t *blocks, size_t blocks_len, void *view); +void blocks_build_chunk_tex(uint64_t id, uint8_t *blocks, uint8_t *outer_blocks, void *view); void *blocks_get_chunk_tex(uint64_t id); void blocks_remove_chunk_tex(uint64_t id); \ No newline at end of file diff --git a/code/game/src/world/blocks_info.h b/code/game/src/world/blocks_info.h index 2daa543..0e569a9 100644 --- a/code/game/src/world/blocks_info.h +++ b/code/game/src/world/blocks_info.h @@ -1,6 +1,7 @@ #pragma once typedef enum { + BLOCK_KIND_EMPTY, BLOCK_KIND_DEV, BLOCK_KIND_GROUND, BLOCK_KIND_DIRT, diff --git a/code/game/src/world/blocks_list.c b/code/game/src/world/blocks_list.c index aad7518..7ae8bc6 100644 --- a/code/game/src/world/blocks_list.c +++ b/code/game/src/world/blocks_list.c @@ -1,6 +1,7 @@ #include "world/blocks.h" static block blocks[] = { + {.name = "empty", .flags = 0, .kind = BLOCK_KIND_EMPTY, .biome = 0, .symbol = ' ', .drag = 1.0f, .friction = 1.0f }, {.name = "base-ground", .flags = 0, .kind = BLOCK_KIND_GROUND, .biome = 0, .symbol = '.', .drag = 1.0f, .friction = 1.0f }, {.name = "base-dirt", .flags = 0, .kind = BLOCK_KIND_DIRT, .biome = 0, .symbol = ',', .drag = 2.1f , .friction = 1.0f }, {.name = "base-wall", .flags = BLOCK_FLAG_COLLISION, .kind = BLOCK_KIND_WALL, .biome = 0, .symbol = '#', .drag = 1.0f , .friction = 1.0f, .bounce = 1.0f }, diff --git a/code/game/src/world/world.c b/code/game/src/world/world.c index 150bbda..09f5989 100644 --- a/code/game/src/world/world.c +++ b/code/game/src/world/world.c @@ -68,6 +68,10 @@ entity_view world_build_entity_view(int64_t e) { for (int i = 0; i < world.chunk_size*world.chunk_size; i += 1) { view.blocks[i] = world.block_mapping[chpos->id][i]; } + + for (int i = 0; i < world.chunk_size*world.chunk_size; i += 1) { + view.outer_blocks[i] = world.outer_block_mapping[chpos->id][i]; + } } world_snapshot_set(&streamer_snapshot, e, view); @@ -164,6 +168,7 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) { world.ecs_update = ecs_query_new(world.ecs, "components.ClientInfo, components.Position"); world.chunk_mapping = zpl_malloc(sizeof(ecs_entity_t)*zpl_square(chunk_amount)); world.block_mapping = zpl_malloc(sizeof(uint8_t*)*zpl_square(chunk_amount)); + world.outer_block_mapping = zpl_malloc(sizeof(uint8_t*)*zpl_square(chunk_amount)); world_snapshot_init(&streamer_snapshot, zpl_heap()); int32_t world_build_status = worldgen_test(&world); @@ -178,6 +183,7 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) { librg_chunk_to_chunkpos(world.tracker, i, &chunk->x, &chunk->y, NULL); world.chunk_mapping[i] = e; world.block_mapping[i] = zpl_malloc(sizeof(uint8_t)*zpl_square(chunk_size)); + world.outer_block_mapping[i] = zpl_malloc(sizeof(uint8_t)*zpl_square(chunk_size)); chunk->id = i; chunk->is_dirty = false; @@ -185,12 +191,19 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) { for (int x = 0; x < chunk_size; x += 1) { int chk_x = chunk->x * chunk_size; int chk_y = chunk->y * chunk_size; + uint8_t *c = &world.block_mapping[i][(y*chunk_size)+x]; *c = world.data[(chk_y+y)*world.dim + (chk_x+x)]; + + c = &world.outer_block_mapping[i][(y*chunk_size)+x]; + *c = 0; } } } + zpl_mfree(world.data); + world.data = NULL; + zpl_printf("[INFO] Created a new server world\n"); return world_build_status; @@ -199,12 +212,12 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) { int32_t world_destroy(void) { librg_world_destroy(world.tracker); ecs_fini(world.ecs); - zpl_mfree(world.data); zpl_mfree(world.chunk_mapping); for (int i = 0; i < zpl_square(world.chunk_amount); i+=1) { zpl_mfree(world.block_mapping[i]); } zpl_mfree(world.block_mapping); + zpl_mfree(world.outer_block_mapping); world_snapshot_destroy(&streamer_snapshot); zpl_memset(&world, 0, sizeof(world)); zpl_printf("[INFO] World was destroyed.\n"); @@ -331,7 +344,10 @@ world_block_lookup world_block_from_realpos(float x, float y) { uint32_t bx = (uint32_t)chx / WORLD_BLOCK_SIZE; uint32_t by = (uint32_t)chy / WORLD_BLOCK_SIZE; uint32_t block_idx = (by*world.chunk_size)+bx; - uint8_t block_id = world.block_mapping[chunk_id][block_idx]; + uint8_t block_id = world.outer_block_mapping[chunk_id][block_idx]; + if (block_id == 0) { + block_id = world.block_mapping[chunk_id][block_idx]; + } // NOTE(zaklaus): pos relative to block's center float box = chx - bx * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f; @@ -350,7 +366,10 @@ world_block_lookup world_block_from_realpos(float x, float y) { } world_block_lookup world_block_from_index(int64_t id, uint16_t block_idx) { - uint8_t block_id = world.block_mapping[id][block_idx]; + uint8_t block_id = world.outer_block_mapping[id][block_idx]; + if (block_id == 0) { + block_id = world.block_mapping[id][block_idx]; + } world_block_lookup lookup = { .id = block_idx, @@ -377,6 +396,12 @@ void world_chunk_replace_block(ecs_world_t *ecs, int64_t id, uint16_t block_idx, world_chunk_mark_dirty(ecs, world.chunk_mapping[id]); } +void world_chunk_replace_outer_block(ecs_world_t *ecs, int64_t id, uint16_t block_idx, uint8_t block_id) { + ZPL_ASSERT(block_idx >= 0 && block_idx < zpl_square(world.chunk_size)); + world.outer_block_mapping[id][block_idx] = block_id; + world_chunk_mark_dirty(ecs, world.chunk_mapping[id]); +} + uint8_t *world_chunk_get_blocks(int64_t id) { return world.block_mapping[id]; } diff --git a/code/game/src/world/world.h b/code/game/src/world/world.h index d379c01..e3990e3 100644 --- a/code/game/src/world/world.h +++ b/code/game/src/world/world.h @@ -33,6 +33,7 @@ typedef struct { uint16_t chunk_size; uint16_t chunk_amount; uint8_t **block_mapping; + uint8_t **outer_block_mapping; uint16_t dim; uint64_t tracker_update[3]; uint8_t active_layer_id; @@ -74,6 +75,7 @@ world_block_lookup world_block_from_index(int64_t id, uint16_t block_idx); int64_t world_chunk_from_realpos(float x, float y); int64_t world_chunk_from_entity(ecs_entity_t id); void world_chunk_replace_block(ecs_world_t *ecs, int64_t id, uint16_t block_idx, uint8_t block_id); +void world_chunk_replace_outer_block(ecs_world_t *ecs, int64_t id, uint16_t block_idx, uint8_t block_id); uint8_t *world_chunk_get_blocks(int64_t id); void world_chunk_mark_dirty(ecs_world_t *ecs, ecs_entity_t e); uint8_t world_chunk_is_dirty(ecs_world_t *ecs, ecs_entity_t e); diff --git a/code/modules/source/system_demo.c b/code/modules/source/system_demo.c index bb0eb38..19855be 100644 --- a/code/modules/source/system_demo.c +++ b/code/modules/source/system_demo.c @@ -20,7 +20,7 @@ void DemoPlaceIceBlock(ecs_iter_t *it) { if (in[i].use) { in[i].use = false; world_block_lookup l = world_block_from_realpos(p[i].x, p[i].y); - world_chunk_replace_block(it->world, l.chunk_id, l.id, watr_id); + world_chunk_replace_outer_block(it->world, l.chunk_id, l.id, watr_id); } } } diff --git a/code/modules/source/system_vehicle.c b/code/modules/source/system_vehicle.c index 78a194e..5199afe 100644 --- a/code/modules/source/system_vehicle.c +++ b/code/modules/source/system_vehicle.c @@ -24,10 +24,10 @@ void LeaveVehicle(ecs_iter_t *it) { // NOTE(zaklaus): push passenger out { - float px = zpl_sin(veh->heading)*400.0f; - float py = zpl_cos(veh->heading)*400.0f; - v->x += px; - v->y += py; + float px = zpl_cos(veh->heading)*400.0f; + float py = zpl_sin(veh->heading)*400.0f; + v->x += py; + v->y -= px; } } else { ZPL_PANIC("unreachable code"); @@ -73,10 +73,10 @@ void EnterVehicle(ecs_iter_t *it) { } #define VEHICLE_FORCE 34.8f -#define VEHICLE_ACCEL 0.02f +#define VEHICLE_ACCEL 0.42f #define VEHICLE_DECEL 0.28f -#define VEHICLE_STEER 0.09f -#define VEHICLE_BRAKE_FORCE 0.04f +#define VEHICLE_STEER 3.89f +#define VEHICLE_BRAKE_FORCE 0.84f void VehicleHandling(ecs_iter_t *it) { Vehicle *veh = ecs_column(it, Vehicle, 1); @@ -102,14 +102,14 @@ void VehicleHandling(ecs_iter_t *it) { if (j == 0) { Input const* in = ecs_get(it->world, pe, Input); - car->force += zpl_lerp(0.0f, in->y * VEHICLE_FORCE, VEHICLE_ACCEL); + car->force += zpl_lerp(0.0f, in->y * VEHICLE_FORCE, VEHICLE_ACCEL*it->delta_time); if (in->sprint) { - car->force = zpl_lerp(car->force, 0.0f, VEHICLE_BRAKE_FORCE); + car->force = zpl_lerp(car->force, 0.0f, VEHICLE_BRAKE_FORCE*it->delta_time); if (zpl_abs(car->force) < 5.5f) car->force = 0.0f; } - car->steer += in->x * VEHICLE_STEER; + car->steer += (in->x * VEHICLE_STEER)*it->delta_time; car->steer = zpl_clamp(car->steer, -40.0f, 40.0f); } }