code: add basic vehicle logic
parent
626457e1b9
commit
d1016f68a0
|
@ -1,8 +1,12 @@
|
||||||
#include "debug_ui.h"
|
#include "debug_ui.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "vehicle.h"
|
#include "vehicle.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "world/world.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
|
#include "modules/components.h"
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
ActExitGame(void) {
|
ActExitGame(void) {
|
||||||
game_request_close();
|
game_request_close();
|
||||||
|
@ -10,5 +14,10 @@ ActExitGame(void) {
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
ActSpawnCar(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;
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
ZPL_TABLE_DEFINE(entity_view_tbl, entity_view_tbl_, entity_view);
|
ZPL_TABLE_DEFINE(entity_view_tbl, entity_view_tbl_, entity_view);
|
||||||
|
|
||||||
pkt_desc pkt_entity_view_desc[] = {
|
pkt_desc pkt_entity_view_desc[] = {
|
||||||
|
|
||||||
{ PKT_UINT(entity_view, kind) },
|
{ PKT_UINT(entity_view, kind) },
|
||||||
{ PKT_UINT(entity_view, flag) },
|
{ PKT_UINT(entity_view, flag) },
|
||||||
{ PKT_HALF(entity_view, x) },
|
{ PKT_HALF(entity_view, x) },
|
||||||
|
|
|
@ -217,6 +217,13 @@ void DEBUG_draw_entities(uint64_t key, entity_view * data) {
|
||||||
#endif
|
#endif
|
||||||
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
||||||
}break;
|
}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;
|
default:break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
uint64_t vehicle_spawn(void) {
|
uint64_t vehicle_spawn(void) {
|
||||||
ecs_entity_t e = entity_spawn(EKIND_VEHICLE);
|
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;
|
return (uint64_t)e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -382,3 +382,24 @@ uint8_t world_chunk_is_dirty(ecs_entity_t e) {
|
||||||
if (chunk) return chunk->is_dirty;
|
if (chunk) return chunk->is_dirty;
|
||||||
return false;
|
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;
|
||||||
|
}
|
|
@ -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);
|
uint8_t *world_chunk_get_blocks(int64_t id);
|
||||||
void world_chunk_mark_dirty(ecs_entity_t e);
|
void world_chunk_mark_dirty(ecs_entity_t e);
|
||||||
uint8_t world_chunk_is_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);
|
|
@ -12,6 +12,7 @@ ECS_COMPONENT_DECLARE(Classify);
|
||||||
ECS_COMPONENT_DECLARE(Vehicle);
|
ECS_COMPONENT_DECLARE(Vehicle);
|
||||||
ECS_TAG_DECLARE(EcsActor);
|
ECS_TAG_DECLARE(EcsActor);
|
||||||
ECS_TAG_DECLARE(EcsDemoNPC);
|
ECS_TAG_DECLARE(EcsDemoNPC);
|
||||||
|
ECS_TAG_DECLARE(EcsInVehicle);
|
||||||
ECS_TYPE_DECLARE(Player);
|
ECS_TYPE_DECLARE(Player);
|
||||||
ECS_TYPE_DECLARE(Movement);
|
ECS_TYPE_DECLARE(Movement);
|
||||||
ECS_TYPE_DECLARE(Walking);
|
ECS_TYPE_DECLARE(Walking);
|
||||||
|
@ -47,6 +48,7 @@ void ComponentsImport(ecs_world_t *ecs) {
|
||||||
|
|
||||||
ECS_TAG_DEFINE(ecs, EcsActor);
|
ECS_TAG_DEFINE(ecs, EcsActor);
|
||||||
ECS_TAG_DEFINE(ecs, EcsDemoNPC);
|
ECS_TAG_DEFINE(ecs, EcsDemoNPC);
|
||||||
|
ECS_TAG_DEFINE(ecs, EcsInVehicle);
|
||||||
|
|
||||||
ECS_PREFAB(ecs, Base, Position, Velocity, Input, EcsActor);
|
ECS_PREFAB(ecs, Base, Position, Velocity, Input, EcsActor);
|
||||||
ECS_TYPE_DEFINE(ecs, Movement, Walking, Flying);
|
ECS_TYPE_DEFINE(ecs, Movement, Walking, Flying);
|
||||||
|
@ -66,5 +68,6 @@ void ComponentsImport(ecs_world_t *ecs) {
|
||||||
ECS_SET_ENTITY(Flying);
|
ECS_SET_ENTITY(Flying);
|
||||||
ECS_SET_ENTITY(EcsActor);
|
ECS_SET_ENTITY(EcsActor);
|
||||||
ECS_SET_ENTITY(EcsDemoNPC);
|
ECS_SET_ENTITY(EcsDemoNPC);
|
||||||
|
ECS_SET_ENTITY(EcsInVehicle);
|
||||||
ECS_SET_TYPE(Movement);
|
ECS_SET_TYPE(Movement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@ ECS_STRUCT(Input, {
|
||||||
uint8_t use;
|
uint8_t use;
|
||||||
uint8_t sprint;
|
uint8_t sprint;
|
||||||
uint8_t is_blocked;
|
uint8_t is_blocked;
|
||||||
|
|
||||||
|
ecs_entity_t parent;
|
||||||
});
|
});
|
||||||
|
|
||||||
ECS_STRUCT(ClientInfo, {
|
ECS_STRUCT(ClientInfo, {
|
||||||
|
@ -63,6 +65,7 @@ ECS_COMPONENT_EXTERN(Classify);
|
||||||
ECS_COMPONENT_EXTERN(Vehicle);
|
ECS_COMPONENT_EXTERN(Vehicle);
|
||||||
ECS_TAG_EXTERN(EcsActor);
|
ECS_TAG_EXTERN(EcsActor);
|
||||||
ECS_TAG_EXTERN(EcsDemoNPC);
|
ECS_TAG_EXTERN(EcsDemoNPC);
|
||||||
|
ECS_TAG_EXTERN(EcsInVehicle);
|
||||||
ECS_TYPE_EXTERN(Player);
|
ECS_TYPE_EXTERN(Player);
|
||||||
ECS_TYPE_EXTERN(Movement);
|
ECS_TYPE_EXTERN(Movement);
|
||||||
ECS_TYPE_EXTERN(Walking);
|
ECS_TYPE_EXTERN(Walking);
|
||||||
|
@ -82,6 +85,7 @@ typedef struct {
|
||||||
ECS_DECLARE_COMPONENT(Vehicle);
|
ECS_DECLARE_COMPONENT(Vehicle);
|
||||||
ECS_DECLARE_ENTITY(EcsActor);
|
ECS_DECLARE_ENTITY(EcsActor);
|
||||||
ECS_DECLARE_ENTITY(EcsDemoNPC);
|
ECS_DECLARE_ENTITY(EcsDemoNPC);
|
||||||
|
ECS_DECLARE_ENTITY(EcsInVehicle);
|
||||||
ECS_DECLARE_TYPE(Player);
|
ECS_DECLARE_TYPE(Player);
|
||||||
ECS_DECLARE_TYPE(Builder);
|
ECS_DECLARE_TYPE(Builder);
|
||||||
ECS_DECLARE_TYPE(Movement);
|
ECS_DECLARE_TYPE(Movement);
|
||||||
|
@ -109,5 +113,6 @@ ECS_IMPORT_ENTITY(handles, EcsDemoNPC);\
|
||||||
ECS_IMPORT_ENTITY(handles, Walking);\
|
ECS_IMPORT_ENTITY(handles, Walking);\
|
||||||
ECS_IMPORT_ENTITY(handles, Flying);\
|
ECS_IMPORT_ENTITY(handles, Flying);\
|
||||||
ECS_IMPORT_ENTITY(handles, EcsClient);\
|
ECS_IMPORT_ENTITY(handles, EcsClient);\
|
||||||
|
ECS_IMPORT_ENTITY(handles, EcsInVehicle);\
|
||||||
|
|
||||||
void ComponentsImport(ecs_world_t *ecs);
|
void ComponentsImport(ecs_world_t *ecs);
|
||||||
|
|
|
@ -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) {
|
void UpdateTrackerPos(ecs_iter_t *it) {
|
||||||
Position *p = ecs_column(it, Position, 1);
|
Position *p = ecs_column(it, Position, 1);
|
||||||
|
|
||||||
|
@ -136,6 +78,7 @@ void MovementImpulse(ecs_iter_t *it) {
|
||||||
Velocity *v = ecs_column(it, Velocity, 2);
|
Velocity *v = ecs_column(it, Velocity, 2);
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++) {
|
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);
|
double speed = PLR_MOVE_SPEED * (in[i].sprint ? PLR_MOVE_SPEED_MULT : 1.0);
|
||||||
if (zpl_abs(v[i].x) < speed && in[i].x)
|
if (zpl_abs(v[i].x) < speed && in[i].x)
|
||||||
v[i].x = in[i].x*speed;
|
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) {
|
void SystemsImport(ecs_world_t *ecs) {
|
||||||
ECS_MODULE(ecs, Systems);
|
ECS_MODULE(ecs, Systems);
|
||||||
ECS_IMPORT(ecs, Components);
|
ECS_IMPORT(ecs, Components);
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, components.Input, components.Velocity);
|
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, 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, MoveWalk, EcsOnUpdate, components.Position, components.Velocity);
|
||||||
ECS_SYSTEM(ecs, HurtOnHazardBlock, EcsOnUpdate, components.Position, components.Health);
|
ECS_SYSTEM(ecs, HurtOnHazardBlock, EcsOnUpdate, components.Position, components.Health);
|
||||||
ECS_SYSTEM(ecs, RegenerateHP, EcsOnUpdate, 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, IntegratePositions, EcsOnValidate, components.Position, components.Velocity);
|
||||||
//ECS_SYSTEM(ecs, PushOutOverlappingEntities, EcsOnValidate, components.Position, Velocity);
|
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, components.Position);
|
ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, components.Position);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue