physics: handle entity collisions
parent
37dc992c2e
commit
99a65431d8
|
@ -10,6 +10,7 @@ typedef enum {
|
||||||
PROF_UPDATE_SYSTEMS,
|
PROF_UPDATE_SYSTEMS,
|
||||||
PROF_ENTITY_LERP,
|
PROF_ENTITY_LERP,
|
||||||
PROF_ENTITY_REMOVAL,
|
PROF_ENTITY_REMOVAL,
|
||||||
|
PROF_INTEGRATE_POS,
|
||||||
|
|
||||||
MAX_PROF,
|
MAX_PROF,
|
||||||
PROF_FORCE_UINT8 = UINT8_MAX
|
PROF_FORCE_UINT8 = UINT8_MAX
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#define BLOCK_INVALID 0xF
|
#define BLOCK_INVALID 0xF
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BLOCK_FLAG_COLLISION = (1 << 0)
|
BLOCK_FLAG_COLLISION = (1 << 1)
|
||||||
} block_flags;
|
} block_flags;
|
||||||
|
|
||||||
#include "blocks_info.h"
|
#include "blocks_info.h"
|
||||||
|
|
|
@ -30,11 +30,13 @@ typedef struct {
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint16_t chunk_size;
|
uint16_t chunk_size;
|
||||||
uint16_t chunk_amount;
|
uint16_t chunk_amount;
|
||||||
|
uint8_t **block_mapping;
|
||||||
uint16_t dim;
|
uint16_t dim;
|
||||||
uint64_t tracker_update[3];
|
uint64_t tracker_update[3];
|
||||||
uint8_t active_layer_id;
|
uint8_t active_layer_id;
|
||||||
ecs_world_t *ecs;
|
ecs_world_t *ecs;
|
||||||
ecs_query_t *ecs_update;
|
ecs_query_t *ecs_update;
|
||||||
|
ecs_entity_t *chunk_mapping;
|
||||||
librg_world *tracker;
|
librg_world *tracker;
|
||||||
world_pkt_reader_proc *reader_proc;
|
world_pkt_reader_proc *reader_proc;
|
||||||
world_pkt_writer_proc *writer_proc;
|
world_pkt_writer_proc *writer_proc;
|
||||||
|
@ -55,3 +57,13 @@ librg_world * world_tracker(void);
|
||||||
uint16_t world_chunk_size(void);
|
uint16_t world_chunk_size(void);
|
||||||
uint16_t world_chunk_amount(void);
|
uint16_t world_chunk_amount(void);
|
||||||
uint16_t world_dim(void);
|
uint16_t world_dim(void);
|
||||||
|
ecs_entity_t world_chunk_mapping(librg_chunk id);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t id;
|
||||||
|
uint8_t block_id;
|
||||||
|
ecs_entity_t chunk_id;
|
||||||
|
float ox, oy;
|
||||||
|
} world_block_lookup;
|
||||||
|
|
||||||
|
world_block_lookup world_block_from_realpos(float x, float y);
|
|
@ -46,6 +46,11 @@ typedef struct debug_item {
|
||||||
uint8_t is_collapsed;
|
uint8_t is_collapsed;
|
||||||
} list;
|
} list;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float val, min, max;
|
||||||
|
void (*on_change)(float);
|
||||||
|
} slider;
|
||||||
|
|
||||||
void (*on_click)(void);
|
void (*on_click)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,6 +84,7 @@ static debug_item items[] = {
|
||||||
{ .kind = DITEM_TEXT, .name = "delta time", .proc = DrawDeltaTime },
|
{ .kind = DITEM_TEXT, .name = "delta time", .proc = DrawDeltaTime },
|
||||||
{ .kind = DITEM_TEXT, .name = "random literal", .text = "hello", .proc = DrawLiteral },
|
{ .kind = DITEM_TEXT, .name = "random literal", .text = "hello", .proc = DrawLiteral },
|
||||||
{ .kind = DITEM_TEXT, .name = "zoom", .proc = DrawZoom },
|
{ .kind = DITEM_TEXT, .name = "zoom", .proc = DrawZoom },
|
||||||
|
{ .kind = DITEM_SLIDER, .name = "slider", .slider = { .min = 0.0f, .max = 1.0f, .val = 0.5f } },
|
||||||
{ .kind = DITEM_END },
|
{ .kind = DITEM_END },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,6 +101,7 @@ static debug_item items[] = {
|
||||||
{ .kind = DITEM_RAW, .val = PROF_UPDATE_SYSTEMS, .proc = DrawProfilerDelta },
|
{ .kind = DITEM_RAW, .val = PROF_UPDATE_SYSTEMS, .proc = DrawProfilerDelta },
|
||||||
{ .kind = DITEM_RAW, .val = PROF_ENTITY_LERP, .proc = DrawProfilerDelta },
|
{ .kind = DITEM_RAW, .val = PROF_ENTITY_LERP, .proc = DrawProfilerDelta },
|
||||||
{ .kind = DITEM_RAW, .val = PROF_ENTITY_REMOVAL, .proc = DrawProfilerDelta },
|
{ .kind = DITEM_RAW, .val = PROF_ENTITY_REMOVAL, .proc = DrawProfilerDelta },
|
||||||
|
{ .kind = DITEM_RAW, .val = PROF_INTEGRATE_POS, .proc = DrawProfilerDelta },
|
||||||
{ .kind = DITEM_END },
|
{ .kind = DITEM_END },
|
||||||
},
|
},
|
||||||
.is_collapsed = 1
|
.is_collapsed = 1
|
||||||
|
@ -163,6 +170,25 @@ debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool
|
||||||
ypos = res.y;
|
ypos = res.y;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
|
case DITEM_SLIDER: {
|
||||||
|
assert(it->slider.min != it->slider.max);
|
||||||
|
char const *text = TextFormat("%s: ", it->name);
|
||||||
|
if (it->name_width == 0) {
|
||||||
|
it->name_width = UIMeasureText(text, DBG_FONT_SIZE);
|
||||||
|
}
|
||||||
|
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, RAYWHITE);
|
||||||
|
xpos += it->name_width;
|
||||||
|
|
||||||
|
DrawRectangleLines(xpos, ypos, 100.0f, DBG_FONT_SIZE, RAYWHITE);
|
||||||
|
|
||||||
|
float stick_x = xpos + ((it->slider.val / it->slider.max) * 100.0f) - 5.0f;
|
||||||
|
DrawRectangle(stick_x, ypos, 10.0f, DBG_FONT_SIZE, RED);
|
||||||
|
|
||||||
|
xpos += 100.0f + 5.0f;
|
||||||
|
DrawFloat(xpos, ypos, it->slider.val);
|
||||||
|
ypos += DBG_FONT_SPACING;
|
||||||
|
}break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
|
|
||||||
}break;
|
}break;
|
||||||
|
|
|
@ -22,11 +22,19 @@ uint64_t entity_spawn(char *name) {
|
||||||
|
|
||||||
ecs_set(world_ecs(), e, EcsName, {.alloc_value = name });
|
ecs_set(world_ecs(), e, EcsName, {.alloc_value = name });
|
||||||
ecs_set(world_ecs(), e, Velocity, {0});
|
ecs_set(world_ecs(), e, Velocity, {0});
|
||||||
ecs_set(world_ecs(), e, Position, {0});
|
|
||||||
ecs_add(world_ecs(), e, Walking);
|
ecs_add(world_ecs(), e, Walking);
|
||||||
|
Position *pos = ecs_get_mut(world_ecs(), e, Position, NULL);
|
||||||
|
#if 1
|
||||||
|
pos->x=rand() % world_dim();
|
||||||
|
pos->y=rand() % world_dim();
|
||||||
|
#else
|
||||||
|
pos->x=35;
|
||||||
|
pos->y=33;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
librg_entity_track(world_tracker(), e);
|
librg_entity_track(world_tracker(), e);
|
||||||
librg_entity_chunk_set(world_tracker(), e, librg_chunk_from_realpos(world_tracker(), 0, 0, 0));
|
librg_entity_chunk_set(world_tracker(), e, librg_chunk_from_realpos(world_tracker(), pos->x, pos->y, 0));
|
||||||
|
|
||||||
return (uint64_t)e;
|
return (uint64_t)e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,28 +21,18 @@ uint64_t player_spawn(char *name) {
|
||||||
ECS_IMPORT(world_ecs(), General);
|
ECS_IMPORT(world_ecs(), General);
|
||||||
ECS_IMPORT(world_ecs(), Controllers);
|
ECS_IMPORT(world_ecs(), Controllers);
|
||||||
ECS_IMPORT(world_ecs(), Net);
|
ECS_IMPORT(world_ecs(), Net);
|
||||||
|
|
||||||
ecs_set(world_ecs(), e, EcsName, {.alloc_value = name });
|
ecs_set(world_ecs(), e, EcsName, {.alloc_value = name });
|
||||||
ecs_add(world_ecs(), e, EcsClient);
|
ecs_add(world_ecs(), e, EcsClient);
|
||||||
ecs_set(world_ecs(), e, ClientInfo, {0});
|
ecs_set(world_ecs(), e, ClientInfo, {0});
|
||||||
ecs_set(world_ecs(), e, Input, {0});
|
ecs_set(world_ecs(), e, Input, {0});
|
||||||
ecs_add(world_ecs(), e, Player);
|
ecs_add(world_ecs(), e, Player);
|
||||||
Position *pos = ecs_get_mut(world_ecs(), e, Position, NULL);
|
|
||||||
#if 1
|
|
||||||
pos->x=rand() % world_dim();
|
|
||||||
pos->y=rand() % world_dim();
|
|
||||||
#else
|
|
||||||
pos->x=10;
|
|
||||||
pos->y=10;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
librg_entity_owner_set(world_tracker(), e, (int64_t)e);
|
librg_entity_owner_set(world_tracker(), e, (int64_t)e);
|
||||||
librg_entity_radius_set(world_tracker(), e, 3);
|
|
||||||
librg_entity_chunk_set(world_tracker(), e, librg_chunk_from_realpos(world_tracker(), pos->x, pos->y, 0));
|
|
||||||
|
|
||||||
return (uint64_t)e;
|
return (uint64_t)e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void player_despawn(uint64_t ent_id) {
|
void player_despawn(uint64_t ent_id) {
|
||||||
librg_entity_untrack(world_tracker(), ent_id);
|
entity_despawn(ent_id);
|
||||||
ecs_delete(world_ecs(), ent_id);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ static profiler profilers[] = {
|
||||||
{ .id = PROF_UPDATE_SYSTEMS, .name = "update systems" },
|
{ .id = PROF_UPDATE_SYSTEMS, .name = "update systems" },
|
||||||
{ .id = PROF_ENTITY_LERP, .name = "entity lerp" },
|
{ .id = PROF_ENTITY_LERP, .name = "entity lerp" },
|
||||||
{ .id = PROF_ENTITY_REMOVAL, .name = "entity removal" },
|
{ .id = PROF_ENTITY_REMOVAL, .name = "entity removal" },
|
||||||
|
{ .id = PROF_INTEGRATE_POS, .name = "entity movement" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert((sizeof(profilers)/sizeof(profilers[0])) == MAX_PROF, "mismatched profilers");
|
static_assert((sizeof(profilers)/sizeof(profilers[0])) == MAX_PROF, "mismatched profilers");
|
||||||
|
|
|
@ -42,7 +42,7 @@ entity_view world_build_entity_view(int64_t e) {
|
||||||
view.blocks_used = 1;
|
view.blocks_used = 1;
|
||||||
|
|
||||||
for (int i = 0; i < world.chunk_size*world.chunk_size; i += 1) {
|
for (int i = 0; i < world.chunk_size*world.chunk_size; i += 1) {
|
||||||
view.blocks[i] = *ecs_vector_get(chpos->blocks, uint8_t, i);
|
view.blocks[i] = world.block_mapping[chpos->id][i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +139,8 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) {
|
||||||
ECS_IMPORT(world.ecs, General);
|
ECS_IMPORT(world.ecs, General);
|
||||||
ECS_IMPORT(world.ecs, Net);
|
ECS_IMPORT(world.ecs, Net);
|
||||||
world.ecs_update = ecs_query_new(world.ecs, "net.ClientInfo, general.Position");
|
world.ecs_update = ecs_query_new(world.ecs, "net.ClientInfo, general.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));
|
||||||
|
|
||||||
int32_t world_build_status = worldgen_test(&world);
|
int32_t world_build_status = worldgen_test(&world);
|
||||||
ZPL_ASSERT(world_build_status >= 0);
|
ZPL_ASSERT(world_build_status >= 0);
|
||||||
|
@ -149,14 +151,16 @@ int32_t world_init(int32_t seed, uint16_t chunk_size, uint16_t chunk_amount) {
|
||||||
librg_entity_track(world.tracker, e);
|
librg_entity_track(world.tracker, e);
|
||||||
librg_entity_chunk_set(world.tracker, e, i);
|
librg_entity_chunk_set(world.tracker, e, i);
|
||||||
librg_chunk_to_chunkpos(world.tracker, i, &chunk->x, &chunk->y, NULL);
|
librg_chunk_to_chunkpos(world.tracker, i, &chunk->x, &chunk->y, NULL);
|
||||||
chunk->blocks = NULL;
|
world.chunk_mapping[i] = e;
|
||||||
|
world.block_mapping[i] = zpl_malloc(sizeof(uint8_t)*zpl_square(chunk_size));
|
||||||
|
chunk->id = i;
|
||||||
|
|
||||||
for (int y = 0; y < world.chunk_size; y += 1) {
|
for (int y = 0; y < world.chunk_size; y += 1) {
|
||||||
for (int x = 0; x < world.chunk_size; x += 1) {
|
for (int x = 0; x < world.chunk_size; x += 1) {
|
||||||
int chk = world.chunk_size * i;
|
int chk = world.chunk_size * i;
|
||||||
int chk_x = chk % world.dim;
|
int chk_x = chk % world.dim;
|
||||||
int chk_y = chk / world.dim;
|
int chk_y = chk / world.dim;
|
||||||
uint8_t *c = ecs_vector_add(&chunk->blocks, uint8_t);
|
uint8_t *c = &world.block_mapping[i][(y*chunk_size)+x];
|
||||||
*c = world.data[(chk_y+y)*world.dim + (chk_x+x)];
|
*c = world.data[(chk_y+y)*world.dim + (chk_x+x)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,6 +175,11 @@ int32_t world_destroy(void) {
|
||||||
librg_world_destroy(world.tracker);
|
librg_world_destroy(world.tracker);
|
||||||
ecs_fini(world.ecs);
|
ecs_fini(world.ecs);
|
||||||
zpl_mfree(world.data);
|
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_memset(&world, 0, sizeof(world));
|
zpl_memset(&world, 0, sizeof(world));
|
||||||
zpl_printf("[INFO] World was destroyed.\n");
|
zpl_printf("[INFO] World was destroyed.\n");
|
||||||
return WORLD_ERROR_NONE;
|
return WORLD_ERROR_NONE;
|
||||||
|
@ -269,3 +278,41 @@ uint16_t world_chunk_amount(void) {
|
||||||
uint16_t world_dim(void) {
|
uint16_t world_dim(void) {
|
||||||
return WORLD_BLOCK_SIZE * world.chunk_size * world.chunk_amount;
|
return WORLD_BLOCK_SIZE * world.chunk_size * world.chunk_amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ecs_entity_t world_chunk_mapping(librg_chunk id) {
|
||||||
|
assert(id >= 0 && id < zpl_square(world.chunk_amount));
|
||||||
|
return world.chunk_mapping[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
world_block_lookup world_block_from_realpos(float x, float y) {
|
||||||
|
x = zpl_clamp(x, 0, world_dim()-1);
|
||||||
|
y = zpl_clamp(y, 0, world_dim()-1);
|
||||||
|
librg_chunk chunk_id = librg_chunk_from_realpos(world.tracker, x, y, 0);
|
||||||
|
ecs_entity_t e = world.chunk_mapping[chunk_id];
|
||||||
|
int32_t size = world.chunk_size * WORLD_BLOCK_SIZE;
|
||||||
|
int16_t chunk_x, chunk_y;
|
||||||
|
librg_chunk_to_chunkpos(world.tracker, chunk_id, &chunk_x, &chunk_y, NULL);
|
||||||
|
|
||||||
|
// NOTE(zaklaus): pos relative to chunk
|
||||||
|
float chx = x - chunk_x * size;
|
||||||
|
float chy = y - chunk_y * size;
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
// NOTE(zaklaus): pos relative to block's center
|
||||||
|
float box = chx - bx * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f;
|
||||||
|
float boy = chy - by * WORLD_BLOCK_SIZE - WORLD_BLOCK_SIZE/2.0f;
|
||||||
|
|
||||||
|
world_block_lookup lookup = {
|
||||||
|
.id = block_idx,
|
||||||
|
.block_id = block_id,
|
||||||
|
.chunk_id = e,
|
||||||
|
.ox = box,
|
||||||
|
.oy = boy,
|
||||||
|
};
|
||||||
|
|
||||||
|
return lookup;
|
||||||
|
}
|
||||||
|
|
|
@ -9,14 +9,15 @@ ECS_STRUCT(Vector2D, {
|
||||||
});
|
});
|
||||||
|
|
||||||
ECS_STRUCT(Chunk, {
|
ECS_STRUCT(Chunk, {
|
||||||
|
uint32_t id;
|
||||||
int16_t x;
|
int16_t x;
|
||||||
int16_t y;
|
int16_t y;
|
||||||
ecs_vector(uint8_t) blocks;
|
//ecs_vector(uint8_t) blocks;
|
||||||
});
|
});
|
||||||
|
|
||||||
ECS_STRUCT(Drawable, {
|
ECS_STRUCT(Drawable, {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
});
|
});
|
||||||
|
|
||||||
ECS_ALIAS(Vector2D, Position);
|
ECS_ALIAS(Vector2D, Position);
|
||||||
|
|
||||||
|
@ -28,9 +29,9 @@ typedef struct {
|
||||||
} General;
|
} General;
|
||||||
|
|
||||||
#define GeneralImportHandles(handles)\
|
#define GeneralImportHandles(handles)\
|
||||||
ECS_IMPORT_COMPONENT(handles, Chunk);\
|
ECS_IMPORT_COMPONENT(handles, Chunk);\
|
||||||
ECS_IMPORT_COMPONENT(handles, Vector2D);\
|
ECS_IMPORT_COMPONENT(handles, Vector2D);\
|
||||||
ECS_IMPORT_COMPONENT(handles, Position);\
|
ECS_IMPORT_COMPONENT(handles, Position);\
|
||||||
ECS_IMPORT_COMPONENT(handles, Drawable);\
|
ECS_IMPORT_COMPONENT(handles, Drawable);\
|
||||||
|
|
||||||
void GeneralImport(ecs_world_t *ecs);
|
void GeneralImport(ecs_world_t *ecs);
|
||||||
|
|
|
@ -13,16 +13,16 @@ typedef struct {
|
||||||
ECS_DECLARE_COMPONENT(Velocity);
|
ECS_DECLARE_COMPONENT(Velocity);
|
||||||
ECS_DECLARE_ENTITY(MoveWalk);
|
ECS_DECLARE_ENTITY(MoveWalk);
|
||||||
ECS_DECLARE_ENTITY(UpdateTrackerPos);
|
ECS_DECLARE_ENTITY(UpdateTrackerPos);
|
||||||
ECS_DECLARE_ENTITY(HandleCollisions);
|
ECS_DECLARE_ENTITY(IntegratePositions);
|
||||||
} Physics;
|
} Physics;
|
||||||
|
|
||||||
#define PhysicsImportHandles(handles)\
|
#define PhysicsImportHandles(handles)\
|
||||||
ECS_IMPORT_TYPE(handles, Movement);\
|
ECS_IMPORT_TYPE(handles, Movement);\
|
||||||
ECS_IMPORT_ENTITY(handles, Walking);\
|
ECS_IMPORT_ENTITY(handles, Walking);\
|
||||||
ECS_IMPORT_ENTITY(handles, Flying);\
|
ECS_IMPORT_ENTITY(handles, Flying);\
|
||||||
ECS_IMPORT_COMPONENT(handles, Velocity);\
|
ECS_IMPORT_COMPONENT(handles, Velocity);\
|
||||||
ECS_IMPORT_ENTITY(handles, MoveWalk);\
|
ECS_IMPORT_ENTITY(handles, MoveWalk);\
|
||||||
ECS_IMPORT_ENTITY(handles, UpdateTrackerPos);\
|
ECS_IMPORT_ENTITY(handles, UpdateTrackerPos);\
|
||||||
ECS_IMPORT_ENTITY(handles, HandleCollisions);\
|
ECS_IMPORT_ENTITY(handles, IntegratePositions);\
|
||||||
|
|
||||||
void PhysicsImport(ecs_world_t *ecs);
|
void PhysicsImport(ecs_world_t *ecs);
|
||||||
|
|
|
@ -1,23 +1,28 @@
|
||||||
|
|
||||||
#include "zpl.h"
|
#include "zpl.h"
|
||||||
#include "modules/physics.h"
|
#include "modules/physics.h"
|
||||||
#include "world/world.h"
|
#include "world/world.h"
|
||||||
|
#include "world/blocks.h"
|
||||||
|
#include "profiler.h"
|
||||||
|
|
||||||
|
#define PHY_BLOCK_COLLISION 1
|
||||||
#define PHY_WALK_DRAG 0.12
|
#define PHY_WALK_DRAG 0.12
|
||||||
|
#define PHY_LOOKAHEAD(x) (zpl_sign(x)*16.0f)
|
||||||
|
#define PHY_CORRECTION(x) ((zpl_max(0.0f, (WORLD_BLOCK_SIZE/2.0f) - zpl_abs(x))*zpl_sign(x)))*(WORLD_BLOCK_SIZE/2.0f)
|
||||||
|
|
||||||
void MoveWalk(ecs_iter_t *it) {
|
void MoveWalk(ecs_iter_t *it) {
|
||||||
Position *p = ecs_column(it, Position, 1);
|
Velocity *v = ecs_column(it, Velocity, 1);
|
||||||
Velocity *v = ecs_column(it, Velocity, 2);
|
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++) {
|
for (int i = 0; i < it->count; i++) {
|
||||||
p[i].x += v[i].x * it->delta_time;
|
|
||||||
p[i].y += v[i].y * it->delta_time;
|
|
||||||
v[i].x = zpl_lerp(v[i].x, 0.0f, PHY_WALK_DRAG);
|
v[i].x = zpl_lerp(v[i].x, 0.0f, PHY_WALK_DRAG);
|
||||||
v[i].y = zpl_lerp(v[i].y, 0.0f, PHY_WALK_DRAG);
|
v[i].y = zpl_lerp(v[i].y, 0.0f, PHY_WALK_DRAG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleCollisions(ecs_iter_t *it) {
|
void IntegratePositions(ecs_iter_t *it) {
|
||||||
|
profile(PROF_INTEGRATE_POS) {
|
||||||
Position *p = ecs_column(it, Position, 1);
|
Position *p = ecs_column(it, Position, 1);
|
||||||
|
Velocity *v = ecs_column(it, Velocity, 2);
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++) {
|
for (int i = 0; i < it->count; i++) {
|
||||||
// NOTE(zaklaus): world bounds
|
// NOTE(zaklaus): world bounds
|
||||||
|
@ -26,6 +31,30 @@ void HandleCollisions(ecs_iter_t *it) {
|
||||||
p[i].x = zpl_clamp(p[i].x, 0, w-1);
|
p[i].x = zpl_clamp(p[i].x, 0, w-1);
|
||||||
p[i].y = zpl_clamp(p[i].y, 0, w-1);
|
p[i].y = zpl_clamp(p[i].y, 0, w-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PHY_BLOCK_COLLISION==1
|
||||||
|
// NOTE(zaklaus): X axis
|
||||||
|
{
|
||||||
|
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.block_id);
|
||||||
|
if (flags & BLOCK_FLAG_COLLISION) {
|
||||||
|
v[i].x = PHY_CORRECTION(lookup.ox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(zaklaus): Y axis
|
||||||
|
{
|
||||||
|
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.block_id);
|
||||||
|
if (flags & BLOCK_FLAG_COLLISION) {
|
||||||
|
v[i].y = PHY_CORRECTION(lookup.oy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p[i].x += v[i].x * it->delta_time;
|
||||||
|
p[i].y += v[i].y * it->delta_time;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +76,8 @@ void PhysicsImport(ecs_world_t *ecs) {
|
||||||
|
|
||||||
ECS_META(ecs, Velocity);
|
ECS_META(ecs, Velocity);
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, MoveWalk, EcsOnUpdate, general.Position, Velocity);
|
ECS_SYSTEM(ecs, MoveWalk, EcsOnUpdate, Velocity);
|
||||||
ECS_SYSTEM(ecs, HandleCollisions, EcsOnValidate, general.Position, Velocity);
|
ECS_SYSTEM(ecs, IntegratePositions, EcsOnValidate, general.Position, Velocity);
|
||||||
ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, general.Position);
|
ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, general.Position);
|
||||||
|
|
||||||
ECS_SET_TYPE(Movement);
|
ECS_SET_TYPE(Movement);
|
||||||
|
@ -57,5 +86,5 @@ void PhysicsImport(ecs_world_t *ecs) {
|
||||||
ECS_SET_COMPONENT(Velocity);
|
ECS_SET_COMPONENT(Velocity);
|
||||||
ECS_SET_ENTITY(MoveWalk);
|
ECS_SET_ENTITY(MoveWalk);
|
||||||
ECS_SET_ENTITY(UpdateTrackerPos);
|
ECS_SET_ENTITY(UpdateTrackerPos);
|
||||||
ECS_SET_ENTITY(HandleCollisions);
|
ECS_SET_ENTITY(IntegratePositions);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue