code: add basic vehicle logic

isolation_bkp/dynres
Dominik Madarász 2021-08-09 19:30:39 +02:00
parent 626457e1b9
commit d1016f68a0
9 changed files with 143 additions and 63 deletions

View File

@ -1,8 +1,12 @@
#include "debug_ui.h"
#include "raylib.h"
#include "vehicle.h"
#include "camera.h"
#include "world/world.h"
#include "game.h"
#include "modules/components.h"
static inline void
ActExitGame(void) {
game_request_close();
@ -10,5 +14,10 @@ ActExitGame(void) {
static inline void
ActSpawnCar(void) {
vehicle_spawn();
}
ecs_entity_t e = vehicle_spawn();
ecs_entity_t plr = camera_get().ent_id;
Position const* origin = ecs_get(world_ecs(), plr, Position);
Position * dest = ecs_get_mut(world_ecs(), e, Position, NULL);
*dest = *origin;
}

View File

@ -5,6 +5,7 @@
ZPL_TABLE_DEFINE(entity_view_tbl, entity_view_tbl_, entity_view);
pkt_desc pkt_entity_view_desc[] = {
{ PKT_UINT(entity_view, kind) },
{ PKT_UINT(entity_view, flag) },
{ PKT_HALF(entity_view, x) },

View File

@ -217,6 +217,13 @@ void DEBUG_draw_entities(uint64_t key, entity_view * data) {
#endif
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
}break;
case EKIND_VEHICLE: {
float x = data->x;
float y = data->y;
float const w = 50;
float const h = 80;
DrawRectanglePro((Rectangle){x,y,w,h}, (Vector2){w/2.0f,h/2.0f}, 0.0f, ColorAlpha(RED, data->tran_time));
}break;
default:break;
}
}

View File

@ -8,7 +8,7 @@
uint64_t vehicle_spawn(void) {
ecs_entity_t e = entity_spawn(EKIND_VEHICLE);
ecs_add(world_ecs(), e, Vehicle);
ecs_set(world_ecs(), e, Vehicle, {0});
return (uint64_t)e;
}

View File

@ -382,3 +382,24 @@ uint8_t world_chunk_is_dirty(ecs_entity_t e) {
if (chunk) return chunk->is_dirty;
return false;
}
int64_t *world_chunk_fetch_entities(librg_chunk chunk_id, size_t *ents_len) {
ZPL_ASSERT_NOT_NULL(ents_len);
static int64_t ents[UINT16_MAX];
*ents_len = UINT16_MAX;
librg_world_fetch_chunk(world.tracker, chunk_id, ents, ents_len);
return ents;
}
int64_t *world_chunk_fetch_entities_realpos(float x, float y, size_t *ents_len) {
return world_chunk_fetch_entities(librg_chunk_from_realpos(world.tracker, x, y, 0), ents_len);
}
int64_t *world_chunk_query_entities(int64_t e, size_t *ents_len, int8_t radius) {
ZPL_ASSERT_NOT_NULL(ents_len);
static int64_t ents[UINT16_MAX];
*ents_len = UINT16_MAX;
librg_entity_radius_set(world.tracker, e, radius);
librg_world_query(world.tracker, e, ents, ents_len);
return ents;
}

View File

@ -77,3 +77,8 @@ void world_chunk_replace_block(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_entity_t e);
uint8_t world_chunk_is_dirty(ecs_entity_t e);
// NOTE(zaklaus): Uses locally persistent buffer !!
int64_t *world_chunk_fetch_entities(librg_chunk chunk_id, size_t *ents_len);
int64_t *world_chunk_fetch_entities_realpos(float x, float y, size_t *ents_len);
int64_t *world_chunk_query_entities(int64_t e, size_t *ents_len, int8_t radius);

View File

@ -12,6 +12,7 @@ ECS_COMPONENT_DECLARE(Classify);
ECS_COMPONENT_DECLARE(Vehicle);
ECS_TAG_DECLARE(EcsActor);
ECS_TAG_DECLARE(EcsDemoNPC);
ECS_TAG_DECLARE(EcsInVehicle);
ECS_TYPE_DECLARE(Player);
ECS_TYPE_DECLARE(Movement);
ECS_TYPE_DECLARE(Walking);
@ -47,6 +48,7 @@ void ComponentsImport(ecs_world_t *ecs) {
ECS_TAG_DEFINE(ecs, EcsActor);
ECS_TAG_DEFINE(ecs, EcsDemoNPC);
ECS_TAG_DEFINE(ecs, EcsInVehicle);
ECS_PREFAB(ecs, Base, Position, Velocity, Input, EcsActor);
ECS_TYPE_DEFINE(ecs, Movement, Walking, Flying);
@ -66,5 +68,6 @@ void ComponentsImport(ecs_world_t *ecs) {
ECS_SET_ENTITY(Flying);
ECS_SET_ENTITY(EcsActor);
ECS_SET_ENTITY(EcsDemoNPC);
ECS_SET_ENTITY(EcsInVehicle);
ECS_SET_TYPE(Movement);
}

View File

@ -27,6 +27,8 @@ ECS_STRUCT(Input, {
uint8_t use;
uint8_t sprint;
uint8_t is_blocked;
ecs_entity_t parent;
});
ECS_STRUCT(ClientInfo, {
@ -63,6 +65,7 @@ ECS_COMPONENT_EXTERN(Classify);
ECS_COMPONENT_EXTERN(Vehicle);
ECS_TAG_EXTERN(EcsActor);
ECS_TAG_EXTERN(EcsDemoNPC);
ECS_TAG_EXTERN(EcsInVehicle);
ECS_TYPE_EXTERN(Player);
ECS_TYPE_EXTERN(Movement);
ECS_TYPE_EXTERN(Walking);
@ -82,6 +85,7 @@ typedef struct {
ECS_DECLARE_COMPONENT(Vehicle);
ECS_DECLARE_ENTITY(EcsActor);
ECS_DECLARE_ENTITY(EcsDemoNPC);
ECS_DECLARE_ENTITY(EcsInVehicle);
ECS_DECLARE_TYPE(Player);
ECS_DECLARE_TYPE(Builder);
ECS_DECLARE_TYPE(Movement);
@ -109,5 +113,6 @@ ECS_IMPORT_ENTITY(handles, EcsDemoNPC);\
ECS_IMPORT_ENTITY(handles, Walking);\
ECS_IMPORT_ENTITY(handles, Flying);\
ECS_IMPORT_ENTITY(handles, EcsClient);\
ECS_IMPORT_ENTITY(handles, EcsInVehicle);\
void ComponentsImport(ecs_world_t *ecs);

View File

@ -62,64 +62,6 @@ void IntegratePositions(ecs_iter_t *it) {
}
}
#define PHY_PUSHOUT_DIST ((64.0f*WORLD_BLOCK_SIZE))
void PushOutOverlappingEntities(ecs_iter_t *it) {
Position *p = ecs_column(it, Position, 1);
for (int i = 0; i <= it->count; i++) {
#if 1
// NOTE(zaklaus): slow path. iterate over all the entities in the table.
for (int k = 0; k <= it->count; k++) {
if (i == k) continue;
#else
// TODO(zaklaus): use a shared internal buffer instead !!!
static int64_t ents[UINT32_MAX];
size_t ents_count = UINT32_MAX;
librg_world_fetch_chunk(world_tracker(), librg_chunk_from_realpos(world_tracker(), p[i].x, p[i].y, 0), ents, &ents_count);
// NOTE(zaklaus): iterate over all entities inside this chunk
for (size_t j = 0; j < ents_count; j++) {
ecs_entity_t e = ents[j];
if (e == it->entities[i])
continue;
// NOTE(zaklaus): reverse lookup
int k = 0;
for (; k <= it->count; k++) {
if (k == it->count) {
k = -1;
break;
}
if (it->entities[k] == e) {
break;
}
}
if (k == -1)
continue;
#endif
float dx = p[i].x - p[k].x;
float dy = p[i].y - p[k].y;
float dist = zpl_sqrt(dx*dx + dy*dy);
if (dist < PHY_PUSHOUT_DIST) {
p[i].x = zpl_sign(dx);
p[i].y = zpl_sign(dy);
#if 0
p[k].x += zpl_sign(dx);
p[k].y += zpl_sign(dy);
#endif
}
}
}
}
#if 0
}
#endif
void UpdateTrackerPos(ecs_iter_t *it) {
Position *p = ecs_column(it, Position, 1);
@ -136,6 +78,7 @@ void MovementImpulse(ecs_iter_t *it) {
Velocity *v = ecs_column(it, Velocity, 2);
for (int i = 0; i < it->count; i++) {
if (ecs_is_alive(world_ecs(), in[i].parent)) continue;
double speed = PLR_MOVE_SPEED * (in[i].sprint ? PLR_MOVE_SPEED_MULT : 1.0);
if (zpl_abs(v[i].x) < speed && in[i].x)
v[i].x = in[i].x*speed;
@ -205,20 +148,106 @@ void RegenerateHP(ecs_iter_t *it) {
}
}
#define VEH_ENTER_RADIUS 45.0f
void EnterOrLeaveVehicle(ecs_iter_t *it) {
Input *in = ecs_column(it, Input, 1);
Position *p = ecs_column(it, Position, 2);
for (int i = 0; i < it->count; i++) {
if (!in[i].use) continue;
if (!ecs_is_alive(world_ecs(), in[i].parent)) {
size_t ents_count;
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
for (size_t j = 0; j < ents_count; j++) {
if (ecs_get(world_ecs(), ents[j], Vehicle)) {
Vehicle *veh = ecs_get_mut(world_ecs(), ents[j], Vehicle, NULL);
Position const* p2 = ecs_get(world_ecs(), ents[j], Position);
float dx = p2->x - p[i].x;
float dy = p2->y - p[i].y;
float range = zpl_sqrt(dx*dx + dy*dy);
if (range <= VEH_ENTER_RADIUS) {
for (int k = 0; k < 4; k++) {
if (veh->seats[k] != 0) continue;
// NOTE(zaklaus): We can enter the vehicle, yay!
veh->seats[k] = it->entities[i];
in[i].parent = ents[j];
p[i] = *p2;
break;
}
}
}
}
} else {
if (ecs_get(world_ecs(), in[i].parent, Vehicle)) {
Vehicle *veh = ecs_get_mut(world_ecs(), in[i].parent, Vehicle, NULL);
for (int k = 0; k < 4; k++) {
if (veh->seats[k] == it->entities[i]) {
veh->seats[k] = 0;
break;
}
}
in[i].parent = 0;
} else {
ZPL_PANIC("unreachable code");
}
}
}
}
void VehicleHandling(ecs_iter_t *it) {
Vehicle *veh = ecs_column(it, Vehicle, 1);
Position *p = ecs_column(it, Position, 2);
Velocity *v = ecs_column(it, Velocity, 3);
for (int i = 0; i < it->count; i++) {
for (int j = 0; j < 4; j++) {
// NOTE(zaklaus): Perform seat cleanup
if (!ecs_is_alive(world_ecs(), veh[i].seats[j])) {
veh[i].seats[j] = 0;
continue;
}
ecs_entity_t pe = veh[i].seats[j];
// NOTE(zaklaus): Update passenger position
{
Position *p2 = ecs_get_mut(world_ecs(), pe, Position, NULL);
*p2 = p[i];
}
// NOTE(zaklaus): Handle driver input
if (j == 0) {
// TODO(zaklaus): Be lazy about it for now, implement wheels later
Input const* in = ecs_get(world_ecs(), pe, Input);
v[i].x += in->x;
v[i].y += in->y;
}
}
}
}
void SystemsImport(ecs_world_t *ecs) {
ECS_MODULE(ecs, Systems);
ECS_IMPORT(ecs, Components);
ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, components.Input, components.Velocity);
ECS_SYSTEM(ecs, DemoPlaceIceBlock, EcsOnLoad, components.Input, components.Position);
//ECS_SYSTEM(ecs, DemoPlaceIceBlock, EcsOnLoad, components.Input, components.Position);
ECS_SYSTEM(ecs, DemoNPCMoveAround, EcsOnLoad, components.Velocity, components.EcsDemoNPC);
ECS_SYSTEM(ecs, EnterOrLeaveVehicle, EcsOnLoad, components.Input, components.Position);
ECS_SYSTEM(ecs, MoveWalk, EcsOnUpdate, components.Position, components.Velocity);
ECS_SYSTEM(ecs, HurtOnHazardBlock, EcsOnUpdate, components.Position, components.Health);
ECS_SYSTEM(ecs, RegenerateHP, EcsOnUpdate, components.Health);
ECS_SYSTEM(ecs, VehicleHandling, EcsOnUpdate, components.Vehicle, components.Position, components.Velocity);
ECS_SYSTEM(ecs, IntegratePositions, EcsOnValidate, components.Position, components.Velocity);
//ECS_SYSTEM(ecs, PushOutOverlappingEntities, EcsOnValidate, components.Position, Velocity);
ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, components.Position);
}