z ordering for outer blocks + improve entity aabb collisions
parent
a7622ceeec
commit
50967aa046
|
@ -269,29 +269,46 @@ void game_request_close() {
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint64_t key;
|
||||
entity_view *data;
|
||||
zpl_f32 y;
|
||||
} game_world_render_entry;
|
||||
|
||||
static game_world_render_entry* render_queue = NULL;
|
||||
|
||||
static void game__world_view_render_push_entry(uint64_t key, entity_view * data) {
|
||||
if (data->kind == EKIND_CHUNK) return;
|
||||
if (!data) return;
|
||||
|
||||
if (data->kind == EKIND_CHUNK) {
|
||||
world_view *view = game_world_view_get_active();
|
||||
float size = (float)(view->chunk_size * WORLD_BLOCK_SIZE);
|
||||
float offset = 0.0;
|
||||
for (size_t ty = 0; ty < view->chunk_size; ty++) {
|
||||
for (size_t tx = 0; tx < view->chunk_size; tx++) {
|
||||
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
|
||||
if (blk_id != 0) {
|
||||
game_world_render_entry entry = {
|
||||
.key = key,
|
||||
.data = data,
|
||||
.blk_id = blk_id,
|
||||
.x = (data->x*size + offset) + (float)tx*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
|
||||
.y = (data->y*size + offset) + (float)ty*WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2,
|
||||
};
|
||||
zpl_array_append(render_queue, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
game_world_render_entry entry = {
|
||||
.key = key,
|
||||
.data = data,
|
||||
.x = data->x,
|
||||
.y = data->y,
|
||||
.blk_id = 0,
|
||||
};
|
||||
zpl_array_append(render_queue, entry);
|
||||
}
|
||||
|
||||
static void game__world_view_render_ground(uint64_t key, entity_view * data) {
|
||||
if (data->kind != EKIND_CHUNK) return;
|
||||
renderer_draw_entry(key, data);
|
||||
renderer_draw_entry(key, data, 0);
|
||||
}
|
||||
|
||||
void game_world_view_render_world(void) {
|
||||
|
@ -300,12 +317,15 @@ void game_world_view_render_world(void) {
|
|||
}
|
||||
|
||||
zpl_array_clear(render_queue);
|
||||
game_world_view_active_entity_map(game__world_view_render_push_entry);
|
||||
zpl_sort_array(render_queue, zpl_array_count(render_queue), zpl_f32_cmp(zpl_offset_of(game_world_render_entry, y)));
|
||||
|
||||
profile(PROF_RENDER_PUSH_AND_SORT_ENTRIES) {
|
||||
game_world_view_active_entity_map(game__world_view_render_push_entry);
|
||||
zpl_sort_array(render_queue, zpl_array_count(render_queue), zpl_f32_cmp(zpl_offset_of(game_world_render_entry, y)));
|
||||
}
|
||||
|
||||
game_world_view_active_entity_map(game__world_view_render_ground);
|
||||
|
||||
for (zpl_isize i = 0; i < zpl_array_count(render_queue); i++) {
|
||||
renderer_draw_entry(render_queue[i].key, render_queue[i].data);
|
||||
renderer_draw_entry(render_queue[i].key, render_queue[i].data, &render_queue[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -232,6 +232,7 @@ static debug_item items[] = {
|
|||
{ .kind = DITEM_RAW, .val = PROF_UPDATE_SYSTEMS, .proc = DrawProfilerDelta },
|
||||
{ .kind = DITEM_RAW, .val = PROF_ENTITY_LERP, .proc = DrawProfilerDelta },
|
||||
{ .kind = DITEM_RAW, .val = PROF_INTEGRATE_POS, .proc = DrawProfilerDelta },
|
||||
{ .kind = DITEM_RAW, .val = PROF_RENDER_PUSH_AND_SORT_ENTRIES, .proc = DrawProfilerDelta },
|
||||
{ .kind = DITEM_END },
|
||||
},
|
||||
.is_collapsed = 1
|
||||
|
|
|
@ -15,6 +15,7 @@ static profiler profilers[] = {
|
|||
{ .id = PROF_UPDATE_SYSTEMS, .name = "update systems" },
|
||||
{ .id = PROF_ENTITY_LERP, .name = "entity lerp" },
|
||||
{ .id = PROF_INTEGRATE_POS, .name = "entity movement" },
|
||||
{ .id = PROF_RENDER_PUSH_AND_SORT_ENTRIES, .name = "push&sort entries" },
|
||||
};
|
||||
|
||||
static_assert((sizeof(profilers)/sizeof(profilers[0])) == MAX_PROF, "mismatched profilers");
|
||||
|
|
|
@ -10,6 +10,7 @@ typedef enum {
|
|||
PROF_UPDATE_SYSTEMS,
|
||||
PROF_ENTITY_LERP,
|
||||
PROF_INTEGRATE_POS,
|
||||
PROF_RENDER_PUSH_AND_SORT_ENTRIES,
|
||||
|
||||
MAX_PROF,
|
||||
PROF_FORCE_UINT8 = UINT8_MAX
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
#pragma once
|
||||
#include "platform/system.h"
|
||||
#include "world/entity_view.h"
|
||||
#include "world/blocks.h"
|
||||
#include "raylib.h"
|
||||
|
||||
typedef struct {
|
||||
uint64_t key;
|
||||
entity_view *data;
|
||||
float x;
|
||||
float y;
|
||||
block_id blk_id;
|
||||
} game_world_render_entry;
|
||||
|
||||
void renderer_draw(void);
|
||||
void renderer_init(void);
|
||||
void renderer_shutdown(void);
|
||||
void renderer_debug_draw(void);
|
||||
float renderer_zoom_get(void);
|
||||
void renderer_draw_single(float x, float y, asset_id id, Color color);
|
||||
void renderer_draw_entry(uint64_t key, entity_view * data);
|
||||
void renderer_draw_entry(uint64_t key, entity_view * data, game_world_render_entry* entry);
|
||||
void renderer_bake_chunk(uint64_t key, entity_view * data);
|
||||
void renderer_switch(int kind);
|
||||
|
|
|
@ -19,11 +19,15 @@
|
|||
#include "modules/system_producer.c"
|
||||
#include "modules/system_blueprint.c"
|
||||
|
||||
static inline float physics_correction(float x, float vx, float bounce) {
|
||||
float r = (((zpl_max(0.0f, (WORLD_BLOCK_SIZE/2.0f) - zpl_abs(x))*zpl_sign(x)))*(WORLD_BLOCK_SIZE/2.0f));
|
||||
static inline float physics_correction(float x, float vx, float bounce, float dim) {
|
||||
float r = (((zpl_max(0.0f, dim - zpl_abs(x))*zpl_sign(x)))*dim);
|
||||
return r + (-vx*bounce);
|
||||
}
|
||||
|
||||
static inline bool physics_check_aabb(float a1x, float a2x, float a1y, float a2y, float b1x, float b2x, float b1y, float b2y) {
|
||||
return (a1x < b2x && a2x > b1x && a1y < b2y && a2y > b1y);
|
||||
}
|
||||
|
||||
void IntegratePositions(ecs_iter_t *it) {
|
||||
profile(PROF_INTEGRATE_POS) {
|
||||
Position *p = ecs_field(it, Position, 1);
|
||||
|
@ -47,8 +51,15 @@ void IntegratePositions(ecs_iter_t *it) {
|
|||
world_block_lookup lookup = world_block_from_realpos(p[i].x+PHY_LOOKAHEAD(v[i].x), p[i].y);
|
||||
uint32_t flags = blocks_get_flags(lookup.bid);
|
||||
float bounce = blocks_get_bounce(lookup.bid);
|
||||
if (flags & BLOCK_FLAG_COLLISION) {
|
||||
v[i].x = physics_correction(lookup.ox, v[i].x, bounce);
|
||||
if (flags & BLOCK_FLAG_COLLISION && physics_check_aabb(p[i].x-WORLD_BLOCK_SIZE/4, p[i].x+WORLD_BLOCK_SIZE/4, p[i].y-0.5f, p[i].y+0.5f, lookup.aox-WORLD_BLOCK_SIZE/2, lookup.aox+WORLD_BLOCK_SIZE/2, lookup.aoy-WORLD_BLOCK_SIZE/2, lookup.aoy+WORLD_BLOCK_SIZE/2)) {
|
||||
#if 1
|
||||
{
|
||||
debug_v2 a = {p[i].x-WORLD_BLOCK_SIZE/4 + PHY_LOOKAHEAD(v[i].x), p[i].y-0.5f};
|
||||
debug_v2 b = {p[i].x+WORLD_BLOCK_SIZE/4 + PHY_LOOKAHEAD(v[i].x), p[i].y+0.5f};
|
||||
debug_push_rect(a, b, 0xFF0000FF);
|
||||
}
|
||||
#endif
|
||||
v[i].x = physics_correction(lookup.ox, v[i].x, bounce, WORLD_BLOCK_SIZE/2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,8 +68,22 @@ void IntegratePositions(ecs_iter_t *it) {
|
|||
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y+PHY_LOOKAHEAD(v[i].y));
|
||||
uint32_t flags = blocks_get_flags(lookup.bid);
|
||||
float bounce = blocks_get_bounce(lookup.bid);
|
||||
if (flags & BLOCK_FLAG_COLLISION) {
|
||||
v[i].y = physics_correction(lookup.oy, v[i].y, bounce);
|
||||
#if 0
|
||||
{
|
||||
debug_v2 a = {lookup.aox-WORLD_BLOCK_SIZE/2, lookup.aoy-WORLD_BLOCK_SIZE/2};
|
||||
debug_v2 b = {lookup.aox+WORLD_BLOCK_SIZE/2, lookup.aoy+WORLD_BLOCK_SIZE/2};
|
||||
debug_push_rect(a, b, 0xFFFFFFFF);
|
||||
}
|
||||
#endif
|
||||
if (flags & BLOCK_FLAG_COLLISION && physics_check_aabb(p[i].x-WORLD_BLOCK_SIZE/4, p[i].x+WORLD_BLOCK_SIZE/4, p[i].y-0.5f, p[i].y+0.5f, lookup.aox-WORLD_BLOCK_SIZE/2, lookup.aox+WORLD_BLOCK_SIZE/2, lookup.aoy-WORLD_BLOCK_SIZE/2, lookup.aoy+WORLD_BLOCK_SIZE/2)) {
|
||||
#if 1
|
||||
{
|
||||
debug_v2 a = {p[i].x-WORLD_BLOCK_SIZE/4, p[i].y-0.5f + PHY_LOOKAHEAD(v[i].y)};
|
||||
debug_v2 b = {p[i].x+WORLD_BLOCK_SIZE/4, p[i].y+0.5f + PHY_LOOKAHEAD(v[i].y)};
|
||||
debug_push_rect(a, b, 0xFF0000FF);
|
||||
}
|
||||
#endif
|
||||
v[i].y = physics_correction(lookup.oy, v[i].y, bounce, WORLD_BLOCK_SIZE/4);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -71,6 +96,12 @@ void IntegratePositions(ecs_iter_t *it) {
|
|||
debug_v2 b = {p[i].x+v[i].x, p[i].y+v[i].y};
|
||||
debug_push_line(a, b, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
{
|
||||
debug_v2 a = {p[i].x-WORLD_BLOCK_SIZE/4, p[i].y-0.5f};
|
||||
debug_v2 b = {p[i].x+WORLD_BLOCK_SIZE/4, p[i].y+0.5f};
|
||||
debug_push_rect(a, b, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -488,6 +488,10 @@ world_block_lookup world_block_from_realpos(float x, float y) {
|
|||
float box = chx - bx * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f;
|
||||
float boy = chy - by * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f;
|
||||
|
||||
// NOTE(zaklaus): absolute pos in world.
|
||||
float abox = (uint16_t)(x / WORLD_BLOCK_SIZE) * (float)WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2.0f;
|
||||
float aboy = (uint16_t)(y / WORLD_BLOCK_SIZE) * (float)WORLD_BLOCK_SIZE + WORLD_BLOCK_SIZE/2.0f;
|
||||
|
||||
world_block_lookup lookup = {
|
||||
.id = block_idx,
|
||||
.bid = bid,
|
||||
|
@ -495,6 +499,8 @@ world_block_lookup world_block_from_realpos(float x, float y) {
|
|||
.chunk_e = e,
|
||||
.ox = box,
|
||||
.oy = boy,
|
||||
.aox = abox,
|
||||
.aoy = aboy,
|
||||
.is_outer = is_outer,
|
||||
};
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ typedef struct {
|
|||
ecs_entity_t chunk_e;
|
||||
int64_t chunk_id;
|
||||
float ox, oy;
|
||||
float aox, aoy;
|
||||
bool is_outer;
|
||||
} world_block_lookup;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ void DEBUG_draw_overlay(uint64_t key, entity_view * data) {
|
|||
}
|
||||
}
|
||||
|
||||
void renderer_draw_entry(uint64_t key, entity_view *data) {
|
||||
void renderer_draw_entry(uint64_t key, entity_view *data, game_world_render_entry* entry) {
|
||||
float size = 16.f;
|
||||
|
||||
switch (data->kind) {
|
||||
|
@ -51,19 +51,14 @@ void renderer_draw_entry(uint64_t key, entity_view *data) {
|
|||
float x = data->x * size + offset;
|
||||
float y = data->y * size + offset;
|
||||
|
||||
RenderTexture2D tex = GetChunkTexture(key);
|
||||
float scale = (size)/(float)(tex.texture.width);
|
||||
tex.texture.width *= (int32_t)scale;
|
||||
tex.texture.height *= (int32_t)scale;
|
||||
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
|
||||
|
||||
for (size_t ty = 0; ty < view->chunk_size; ty++) {
|
||||
for (size_t tx = 0; tx < view->chunk_size; tx++) {
|
||||
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
|
||||
if (blk_id != 0) {
|
||||
DrawTextureRec(GetBlockImage(blk_id), ASSET_SRC_RECT(), (Vector2){x+tx*WORLD_BLOCK_SIZE, y+ty*WORLD_BLOCK_SIZE}, ColorAlpha(WHITE, data->tran_time));
|
||||
}
|
||||
}
|
||||
if (entry == NULL) {
|
||||
RenderTexture2D tex = GetChunkTexture(key);
|
||||
float scale = (size)/(float)(tex.texture.width);
|
||||
tex.texture.width *= (int32_t)scale;
|
||||
tex.texture.height *= (int32_t)scale;
|
||||
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
|
||||
} else {
|
||||
DrawTextureRec(GetBlockImage(entry->blk_id), ASSET_SRC_RECT(), (Vector2){entry->x-(WORLD_BLOCK_SIZE/2), entry->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
|
||||
}
|
||||
}break;
|
||||
case EKIND_VEHICLE: {
|
||||
|
|
|
@ -41,7 +41,7 @@ void DEBUG_draw_overlay(uint64_t key, entity_view * data) {
|
|||
|
||||
extern bool inv_is_open;
|
||||
|
||||
void renderer_draw_entry(uint64_t key, entity_view *data) {
|
||||
void renderer_draw_entry(uint64_t key, entity_view *data, game_world_render_entry* entry) {
|
||||
float size = 16.f;
|
||||
|
||||
switch (data->kind) {
|
||||
|
@ -53,19 +53,14 @@ void renderer_draw_entry(uint64_t key, entity_view *data) {
|
|||
float x = data->x * size + offset;
|
||||
float y = data->y * size + offset;
|
||||
|
||||
RenderTexture2D tex = GetChunkTexture(key);
|
||||
float scale = (size)/(float)(tex.texture.width);
|
||||
tex.texture.width *= (int32_t)scale;
|
||||
tex.texture.height *= (int32_t)scale;
|
||||
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
|
||||
|
||||
for (size_t ty = 0; ty < view->chunk_size; ty++) {
|
||||
for (size_t tx = 0; tx < view->chunk_size; tx++) {
|
||||
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
|
||||
if (blk_id != 0) {
|
||||
DrawTextureRec(GetBlockImage(blk_id), ASSET_SRC_RECT(), (Vector2){x+tx*WORLD_BLOCK_SIZE, y+ty*WORLD_BLOCK_SIZE}, ColorAlpha(WHITE, data->tran_time));
|
||||
}
|
||||
}
|
||||
if (entry == NULL) {
|
||||
RenderTexture2D tex = GetChunkTexture(key);
|
||||
float scale = (size)/(float)(tex.texture.width);
|
||||
tex.texture.width *= (int32_t)scale;
|
||||
tex.texture.height *= (int32_t)scale;
|
||||
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
|
||||
} else {
|
||||
DrawTextureRec(GetBlockImage(entry->blk_id), ASSET_SRC_RECT(), (Vector2){entry->x-(WORLD_BLOCK_SIZE/2), entry->y-(WORLD_BLOCK_SIZE/2)}, ColorAlpha(WHITE, data->tran_time));
|
||||
}
|
||||
}break;
|
||||
case EKIND_VEHICLE: {
|
||||
|
@ -94,15 +89,25 @@ void renderer_draw_entry(uint64_t key, entity_view *data) {
|
|||
case EKIND_DEMO_NPC: {
|
||||
float x = data->x;
|
||||
float y = data->y;
|
||||
if (!data->inside_vehicle) {
|
||||
DrawCircleEco(x, y, size, ColorAlpha(BLUE, data->tran_time));
|
||||
} else {
|
||||
y -= 32.f;
|
||||
}
|
||||
DrawNametag("Demo", key, data, x, y);
|
||||
DrawCircleEco(x, y, size, ColorAlpha(BLUE, data->tran_time));
|
||||
}break;
|
||||
case EKIND_PLAYER: {
|
||||
float x = data->x;
|
||||
float y = data->y;
|
||||
float health = (data->hp / data->max_hp);
|
||||
|
||||
if (!data->inside_vehicle) {
|
||||
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
||||
} else {
|
||||
y -= 32.f;
|
||||
}
|
||||
|
||||
DrawNametag("Player", key, data, x, y);
|
||||
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
||||
|
||||
if (data->has_items && !data->inside_vehicle) {
|
||||
float ix = data->x;
|
||||
|
@ -120,6 +125,11 @@ void renderer_draw_entry(uint64_t key, entity_view *data) {
|
|||
case EKIND_MACRO_BOT: {
|
||||
float x = data->x;
|
||||
float y = data->y;
|
||||
if (!data->inside_vehicle) {
|
||||
DrawCircleEco(x, y, size, ColorAlpha(GREEN, data->tran_time));
|
||||
} else {
|
||||
y -= 32.f;
|
||||
}
|
||||
DrawNametag("Bot", key, data, x, y);
|
||||
}break;
|
||||
case EKIND_ITEM: {
|
||||
|
|
Loading…
Reference in New Issue