rework vehicle driving model

isolation_bkp/dynres
Dominik Madarász 2021-08-29 14:59:00 +02:00
parent 3cda4cc334
commit 936658056a
6 changed files with 55 additions and 26 deletions

View File

@ -66,8 +66,8 @@ void platform_input() {
uint8_t use, sprint; uint8_t use, sprint;
if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) x += 1.0f; if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) x += 1.0f;
if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) x -= 1.0f; if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) x -= 1.0f;
if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) y -= 1.0f; if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) y += 1.0f;
if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) y += 1.0f; if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) y -= 1.0f;
use = IsKeyPressed(KEY_SPACE); use = IsKeyPressed(KEY_SPACE);
sprint = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT); sprint = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT);

View File

@ -11,6 +11,9 @@ uint64_t vehicle_spawn(void) {
Vehicle *veh = ecs_get_mut(world_ecs(), e, Vehicle, NULL); Vehicle *veh = ecs_get_mut(world_ecs(), e, Vehicle, NULL);
zpl_zero_item(veh); zpl_zero_item(veh);
veh->wheel_base = 50.0f; veh->wheel_base = 50.0f;
veh->speed = 50.0f;
veh->reverse_speed = -20.0f;
veh->force = 0.0f;
return (uint64_t)e; return (uint64_t)e;
} }

View File

@ -68,6 +68,9 @@ ECS_STRUCT(Vehicle, {
float heading; float heading;
float steer; float steer;
float wheel_base; float wheel_base;
float speed;
float reverse_speed;
}); });
typedef struct { typedef struct {

View File

@ -136,9 +136,6 @@ void SystemsImport(ecs_world_t *ecs) {
ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, components.Input, components.Velocity, components.Position, !components.IsInVehicle); ECS_SYSTEM(ecs, MovementImpulse, EcsOnLoad, components.Input, components.Velocity, components.Position, !components.IsInVehicle);
ECS_SYSTEM(ecs, DemoNPCMoveAround, EcsOnLoad, components.Velocity, components.EcsDemoNPC); ECS_SYSTEM(ecs, DemoNPCMoveAround, EcsOnLoad, components.Velocity, components.EcsDemoNPC);
ECS_SYSTEM(ecs, EnterVehicle, EcsOnLoad, components.Input, components.Position, !components.IsInVehicle);
ECS_SYSTEM(ecs, LeaveVehicle, EcsOnLoad, components.Input, components.IsInVehicle);
ECS_SYSTEM(ecs, DemoPlaceIceBlock, EcsOnLoad, components.Input, components.Position, !components.IsInVehicle);
ECS_SYSTEM(ecs, ApplyWorldDragOnVelocity, EcsOnUpdate, components.Position, components.Velocity); ECS_SYSTEM(ecs, ApplyWorldDragOnVelocity, EcsOnUpdate, components.Position, components.Velocity);
ECS_SYSTEM(ecs, HurtOnHazardBlock, EcsOnUpdate, components.Position, components.Health); ECS_SYSTEM(ecs, HurtOnHazardBlock, EcsOnUpdate, components.Position, components.Health);
@ -147,6 +144,10 @@ void SystemsImport(ecs_world_t *ecs) {
ECS_SYSTEM(ecs, IntegratePositions, EcsOnValidate, components.Position, components.Velocity); ECS_SYSTEM(ecs, IntegratePositions, EcsOnValidate, components.Position, components.Velocity);
ECS_SYSTEM(ecs, EnterVehicle, EcsPostUpdate, components.Input, components.Position, !components.IsInVehicle);
ECS_SYSTEM(ecs, LeaveVehicle, EcsPostUpdate, components.Input, components.IsInVehicle, components.Velocity);
ECS_SYSTEM(ecs, DemoPlaceIceBlock, EcsPostUpdate, components.Input, components.Position, !components.IsInVehicle);
ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, components.Position, components.Velocity); ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, components.Position, components.Velocity);
ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle); ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle);

View File

@ -11,6 +11,6 @@ void MovementImpulse(ecs_iter_t *it) {
float drag = zpl_clamp(blocks_get_drag(lookup.block_id), 0.0f, 1.0f); float drag = zpl_clamp(blocks_get_drag(lookup.block_id), 0.0f, 1.0f);
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);
v[i].x += in[i].x*speed*drag; v[i].x += in[i].x*speed*drag;
v[i].y += in[i].y*speed*drag; v[i].y -= in[i].y*speed*drag;
} }
} }

View File

@ -5,6 +5,7 @@
void LeaveVehicle(ecs_iter_t *it) { void LeaveVehicle(ecs_iter_t *it) {
Input *in = ecs_column(it, Input, 1); Input *in = ecs_column(it, Input, 1);
IsInVehicle *vehp = ecs_column(it, IsInVehicle, 2); IsInVehicle *vehp = ecs_column(it, IsInVehicle, 2);
Velocity *v = ecs_column(it, Velocity, 3);
for (int i = 0; i < it->count; i++) { for (int i = 0; i < it->count; i++) {
if (!in[i].use) continue; if (!in[i].use) continue;
@ -20,6 +21,14 @@ void LeaveVehicle(ecs_iter_t *it) {
in[i].use = false; in[i].use = false;
ecs_remove(it->world, it->entities[i], IsInVehicle); ecs_remove(it->world, it->entities[i], IsInVehicle);
// 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;
}
} else { } else {
ZPL_PANIC("unreachable code"); ZPL_PANIC("unreachable code");
} }
@ -64,10 +73,10 @@ void EnterVehicle(ecs_iter_t *it) {
} }
#define VEHICLE_FORCE 34.8f #define VEHICLE_FORCE 34.8f
#define VEHICLE_ACCEL 0.27f #define VEHICLE_ACCEL 0.02f
#define VEHICLE_DECEL 0.28f #define VEHICLE_DECEL 0.28f
#define VEHICLE_STEER 0.11f #define VEHICLE_STEER 0.09f
#define VEHICLE_STEER_MUL 0.087f #define VEHICLE_BRAKE_FORCE 0.04f
void VehicleHandling(ecs_iter_t *it) { void VehicleHandling(ecs_iter_t *it) {
Vehicle *veh = ecs_column(it, Vehicle, 1); Vehicle *veh = ecs_column(it, Vehicle, 1);
@ -78,7 +87,6 @@ void VehicleHandling(ecs_iter_t *it) {
Vehicle *car = &veh[i]; Vehicle *car = &veh[i];
// NOTE(zaklaus): Apply friction // NOTE(zaklaus): Apply friction
car->force = zpl_lerp(car->force, 0.0f, VEHICLE_DECEL);
car->steer *= 0.97f; car->steer *= 0.97f;
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
@ -90,26 +98,24 @@ void VehicleHandling(ecs_iter_t *it) {
ecs_entity_t pe = veh[i].seats[j]; ecs_entity_t pe = veh[i].seats[j];
// NOTE(zaklaus): Update passenger position
{
Position *p2 = ecs_get_mut(it->world, pe, Position, NULL);
Velocity *v2 = ecs_get_mut(it->world, pe, Velocity, NULL);
*p2 = p[i];
*v2 = v[i];
}
// NOTE(zaklaus): Handle driver input // NOTE(zaklaus): Handle driver input
if (j == 0) { if (j == 0) {
Input const* in = ecs_get(it->world, pe, Input); Input const* in = ecs_get(it->world, pe, Input);
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y);
float drag = zpl_clamp(blocks_get_drag(lookup.block_id), 0.0f, 1.0f);
car->force += zpl_lerp(0.0f, in->y * VEHICLE_FORCE, VEHICLE_ACCEL) * drag; car->force += zpl_lerp(0.0f, in->y * VEHICLE_FORCE, VEHICLE_ACCEL);
car->steer += in->x * -VEHICLE_STEER; if (in->sprint) {
car->force = zpl_lerp(car->force, 0.0f, VEHICLE_BRAKE_FORCE);
if (zpl_abs(car->force) < 5.5f)
car->force = 0.0f;
}
car->steer += in->x * VEHICLE_STEER;
car->steer = zpl_clamp(car->steer, -40.0f, 40.0f); car->steer = zpl_clamp(car->steer, -40.0f, 40.0f);
} }
} }
car->force = zpl_clamp(car->force, car->reverse_speed, car->speed);
// NOTE(zaklaus): Vehicle physics // NOTE(zaklaus): Vehicle physics
float fr_x = p[i].x + (car->wheel_base/2.0f) * zpl_cos(car->heading); float fr_x = p[i].x + (car->wheel_base/2.0f) * zpl_cos(car->heading);
float fr_y = p[i].y + (car->wheel_base/2.0f) * zpl_sin(car->heading); float fr_y = p[i].y + (car->wheel_base/2.0f) * zpl_sin(car->heading);
@ -117,15 +123,31 @@ void VehicleHandling(ecs_iter_t *it) {
float bk_x = p[i].x - (car->wheel_base/2.0f) * zpl_cos(car->heading); float bk_x = p[i].x - (car->wheel_base/2.0f) * zpl_cos(car->heading);
float bk_y = p[i].y - (car->wheel_base/2.0f) * zpl_sin(car->heading); float bk_y = p[i].y - (car->wheel_base/2.0f) * zpl_sin(car->heading);
bk_x += car->force * zpl_cos(car->heading); world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y);
bk_y += car->force * zpl_sin(car->heading); float drag = zpl_clamp(blocks_get_drag(lookup.block_id), 0.0f, 1.0f);
fr_x += car->force * zpl_cos(car->heading + zpl_to_radians(car->steer));
fr_y += car->force * zpl_sin(car->heading + zpl_to_radians(car->steer)); bk_x += car->force * drag * zpl_cos(car->heading);
bk_y += car->force * drag * zpl_sin(car->heading);
fr_x += car->force * drag * zpl_cos(car->heading + zpl_to_radians(car->steer));
fr_y += car->force * drag * zpl_sin(car->heading + zpl_to_radians(car->steer));
v[i].x += (fr_x + bk_x) / 2.0f - p[i].x; v[i].x += (fr_x + bk_x) / 2.0f - p[i].x;
v[i].y += (fr_y + bk_y) / 2.0f - p[i].y; v[i].y += (fr_y + bk_y) / 2.0f - p[i].y;
car->heading = zpl_arctan2(fr_y - bk_y, fr_x - bk_x); car->heading = zpl_arctan2(fr_y - bk_y, fr_x - bk_x);
for (int j = 0; j < 4; j++) {
if (!world_entity_valid(veh[i].seats[j])) continue;
ecs_entity_t pe = veh[i].seats[j];
// NOTE(zaklaus): Update passenger position
{
Position *p2 = ecs_get_mut(it->world, pe, Position, NULL);
Velocity *v2 = ecs_get_mut(it->world, pe, Velocity, NULL);
*p2 = p[i];
*v2 = v[i];
}
}
{ {
debug_v2 b2 = {p[i].x + zpl_cos(car->heading)*(car->wheel_base), p[i].y + zpl_sin(car->heading)*(car->wheel_base)}; debug_v2 b2 = {p[i].x + zpl_cos(car->heading)*(car->wheel_base), p[i].y + zpl_sin(car->heading)*(car->wheel_base)};
debug_push_line((debug_v2){p[i].x, p[i].y}, b2, 0x0000FFFF); debug_push_line((debug_v2){p[i].x, p[i].y}, b2, 0x0000FFFF);