Broken verlet work, committing before chipmunk

main
Cameron Murphy Reikes 2 years ago
parent 7bab2e9900
commit 35fbdf2635

@ -29,6 +29,8 @@
"sokol_time.h": "c", "sokol_time.h": "c",
"enet.h": "c", "enet.h": "c",
"types.h": "c", "types.h": "c",
"cmath": "c" "cmath": "c",
"math.h": "c",
"corecrt_math.h": "c"
} }
} }

@ -0,0 +1,46 @@
<?xml version="1.0"?>
<N10X>
<Workspace>
<IncludeFilter>*.c,*.cc,*.cpp,*.c++,*.cp,*.cxx,*.h,*.hh,*.hpp,*.h++,*.hp,*.hxx,*.inl,*.cs,*.rs,*.java,*.jav,*.js,*.jsc,*.jsx,*.json,*.cls,*.py,*.rpy,*.php,*.php3,*.phl,*.phtml,*.rhtml,*.tpl,*.phps,*.lua,*.html,*.html5,*.htm,*.xml,*.xaml,*.css,*.ssi,*.haml,*.yaml,*.bat,*.wbf,*.wbt,*.txt,*.cmake,*.make,*.makefile,*.mak,*.mk,*.sh,*.bash,*.csv,*.asp,*.pl,*.mac,*.ws,*.vbs,*.perl,*.src,*.rss,*.inc,*.f,*.go,*.prl,*.plx,*.rb,*.lsp,*.lpx,*.ps1,*.command,*.cbl,*.cob,*.qs,*.wxs,*.ph,*.msc,*.glsl,*.hlsl,*.fx,*.vert,*.tesc,*.tese,*.geom,*.frag,*.comp,*.pssl,*.scons,</IncludeFilter>
<ExcludeFilter></ExcludeFilter>
<SyncFiles>true</SyncFiles>
<Recursive>true</Recursive>
<IsVirtual>false</IsVirtual>
<IsFolder>false</IsFolder>
<BuildCommand>build_debug.bat</BuildCommand>
<RebuildCommand></RebuildCommand>
<BuildFileCommand></BuildFileCommand>
<CleanCommand></CleanCommand>
<BuildWorkingDirectory></BuildWorkingDirectory>
<RunCommand>flight.exe</RunCommand>
<DebugCommand>devenv.exe \Run $(Workspacefilename)</DebugCommand>
<ExePathCommand></ExePathCommand>
<DebugSln></DebugSln>
<Configurations>
<Configuration>Debug</Configuration>
<Configuration>Release</Configuration>
</Configurations>
<Platforms>
<Platform>x64</Platform>
<Platform>Win32</Platform>
</Platforms>
<AdditionalIncludePaths></AdditionalIncludePaths>
<Defines></Defines>
<ConfigProperties>
<ConfigAndPlatform>
<Name>Debug:x64</Name>
<Defines></Defines>
<ForceIncludes></ForceIncludes>
</ConfigAndPlatform>
<Config>
<Name>Debug</Name>
<Defines></Defines>
</Config>
<Platform>
<Name>x64</Name>
<Defines></Defines>
</Platform>
</ConfigProperties>
<Children></Children>
</Workspace>
</N10X>

@ -3,9 +3,9 @@
#include <stdlib.h> // malloc #include <stdlib.h> // malloc
#include <stdio.h> #include <stdio.h>
void __assert(bool cond, const char * file, int line, const char * cond_string) void __assert(bool cond, const char *file, int line, const char *cond_string)
{ {
if(!cond) if (!cond)
{ {
fprintf(stderr, "%s:%d | Assertion %s failed\n", file, line, cond_string); fprintf(stderr, "%s:%d | Assertion %s failed\n", file, line, cond_string);
} }
@ -38,32 +38,68 @@ static void integrate_acceleration(struct Body *body, float dt)
} }
} }
static void modify_interval(struct Body *from, float *from_interval, V2 center, V2 axis) struct ProcessBody
{ {
float halfbox = BOX_SIZE/2.0f; V2 vertices[4];
V2 points[4] = { struct Body *body;
V2add(from->position, V2rotate((V2){.x = halfbox, .y = -halfbox}, from->rotation)), // upper right };
V2add(from->position, V2rotate((V2){.x = halfbox, .y = halfbox}, from->rotation)), // bottom right
V2add(from->position, V2rotate((V2){.x = -halfbox, .y = halfbox}, from->rotation)), // lower left struct ProcessBody make_process_body(struct Body *from)
V2add(from->position, V2rotate((V2){.x = -halfbox, .y = -halfbox}, from->rotation)), // upper left {
}; float halfbox = BOX_SIZE / 2.0f;
for (int point_i = 0; point_i < 4; point_i++) struct ProcessBody to_return =
{
float value = V2projectvalue(V2sub(points[point_i], center), axis);
if (value > from_interval[1])
{
from_interval[1] = value;
}
if (value < from_interval[0])
{ {
from_interval[0] = value; .vertices = {
} // important that the first one is the upper right, used to deduce rotation from vertex position
// @Robust instead of array of vertices have type? like struct with upper_right upper_left etc
V2add(from->position, V2rotate((V2){.x = halfbox, .y = -halfbox}, from->rotation)), // upper right
V2add(from->position, V2rotate((V2){.x = halfbox, .y = halfbox}, from->rotation)), // bottom right
V2add(from->position, V2rotate((V2){.x = -halfbox, .y = halfbox}, from->rotation)), // lower left
V2add(from->position, V2rotate((V2){.x = -halfbox, .y = -halfbox}, from->rotation)), // upper left
},
.body = from,
};
return to_return;
}
static void project(struct ProcessBody *from, V2 axis, float *min, float *max)
{
float DotP = V2dot(axis, from->vertices[0]);
// Set the minimum and maximum values to the projection of the first vertex
*min = DotP;
*max = DotP;
for (int I = 1; I < 4; I++)
{
// Project the rest of the vertices onto the axis and extend
// the interval to the left/right if necessary
DotP = V2dot(axis, from->vertices[I]);
*min = fmin(DotP, *min);
*max = fmax(DotP, *max);
} }
} }
static float interval_distance(float min_a, float max_a, float min_b, float max_b)
{
if (min_a < min_b)
return min_b - max_a;
else
return min_a - max_b;
}
static void move_vertices(V2 *vertices, int num, V2 shift)
{
for (int i = 0; i < num; i++)
{
vertices[i] = V2add(vertices[i], shift);
}
}
void process(struct GameState *gs, float dt) void process(struct GameState *gs, float dt)
{ {
// process input
int num_bodies = gs->num_boxes; int num_bodies = gs->num_boxes;
for (int i = 0; i < MAX_PLAYERS; i++) for (int i = 0; i < MAX_PLAYERS; i++)
{ {
@ -76,7 +112,8 @@ void process(struct GameState *gs, float dt)
} }
// @Robust do this without malloc // @Robust do this without malloc
struct Body **bodies = malloc(sizeof *bodies * num_bodies);
struct ProcessBody *bodies = malloc(sizeof *bodies * num_bodies);
int cur_body_index = 0; int cur_body_index = 0;
for (int i = 0; i < MAX_PLAYERS; i++) for (int i = 0; i < MAX_PLAYERS; i++)
@ -84,24 +121,21 @@ void process(struct GameState *gs, float dt)
struct Player *p = &gs->players[i]; struct Player *p = &gs->players[i];
if (!p->connected) if (!p->connected)
continue; continue;
bodies[cur_body_index] = &p->body; integrate_acceleration(&p->body, dt);
bodies[cur_body_index] = make_process_body(&p->body);
cur_body_index++; cur_body_index++;
} }
for (int i = 0; i < gs->num_boxes; i++) for (int i = 0; i < gs->num_boxes; i++)
{ {
bodies[cur_body_index] = &gs->boxes[i].body; integrate_acceleration(&gs->boxes[i].body, dt);
bodies[cur_body_index] = make_process_body(&gs->boxes[i].body);
cur_body_index++; cur_body_index++;
} }
assert(cur_body_index == num_bodies); assert(cur_body_index == num_bodies);
for (int i = 0; i < num_bodies; i++) // Collision
{
struct Body *body = bodies[i];
integrate_acceleration(body, dt);
}
// @Robust handle when bodies are overlapping (even perfectly) // @Robust handle when bodies are overlapping (even perfectly)
for (int i = 0; i < num_bodies; i++) for (int i = 0; i < num_bodies; i++)
{ {
@ -109,35 +143,125 @@ void process(struct GameState *gs, float dt)
{ {
if (ii == i) if (ii == i)
continue; continue;
struct Body *from = bodies[i]; struct ProcessBody *from = &bodies[i];
struct Body *to = bodies[ii]; struct ProcessBody *to = &bodies[ii];
dbg_line(from->body->position, to->body->position);
float MinDistance = 10000.0f;
V2 axis = V2normalize(V2sub(to->position, from->position)); struct Edge
V2 center = V2scale(V2add(to->position, from->position), 0.5f); {
struct ProcessBody *parent;
V2 *from;
V2 *to;
};
dbg_line(from->position, to->position); struct ProcessBody *bodies[2] = {from, to};
bool was_collision = false;
V2 normal = {0};
struct Edge edge = {0};
for (int body_i = 0; body_i < 2; body_i++)
{
struct ProcessBody *body = bodies[body_i];
for (int edge_from_i = 0; edge_from_i < 3; edge_from_i++)
{
int edge_to_i = edge_from_i + 1;
V2 *edge_from = &body->vertices[edge_from_i];
V2 *edge_to = &body->vertices[edge_to_i];
dbg_rect(center); // normal vector of edge
V2 axis = (V2){
.x = edge_from->y - edge_to->y,
.y = edge_to->x - edge_from->x,
};
axis = V2normalize(axis);
float from_interval[2] = {1000.0f, -1000.0f}; float min_from, min_to, max_from, max_to = 0.0f;
float to_interval[2] = {1000.0f, -1000.0f}; project(from, axis, &min_from, &max_from);
modify_interval(from, from_interval, center, axis); project(to, axis, &min_to, &max_to);
modify_interval(to, to_interval, center, axis);
assert(from_interval[0] < from_interval[1]);
assert(to_interval[0] < to_interval[1]);
// @BeforeShip debug compile time flag in preprocessor float distance = interval_distance(min_from, min_to, max_from, max_to);
if (from_interval[1] > to_interval[0]) // intersecting if (distance > 0.0f)
break;
else if (fabsf(distance) < MinDistance)
{
MinDistance = fabsf(distance);
was_collision = true;
normal = axis;
edge = (struct Edge){
.parent = &body,
.from = edge_from,
.to = edge_to,
};
}
}
}
float depth = MinDistance;
if (was_collision)
{ {
float intersection_depth = from_interval[1] - to_interval[0]; float intersection_depth = from_interval[1] - to_interval[0];
move_vertices(from->vertices, 4, V2scale(axis, intersection_depth * -0.5f));
move_vertices(to->vertices, 4, V2scale(axis, intersection_depth * 0.5f));
}
}
}
// Wall
if (true)
{
for (int i = 0; i < num_bodies; i++)
{
for (int v_i = 0; v_i < 4; v_i++)
{
V2 *vert = &bodies[i].vertices[v_i];
if (vert->x > 2.0f)
{
vert->x = 2.0f;
}
}
}
}
// Correct for differences in vertex position
const int edge_update_iters = 3;
for (int iter = 0; iter < edge_update_iters; iter++)
{
for (int i = 0; i < num_bodies; i++)
{
for (int v_i = 0; v_i < 3; v_i++)
{
int other_v_i = v_i + 1;
V2 *from = &bodies[i].vertices[v_i];
V2 *to = &bodies[i].vertices[other_v_i];
from->position = V2add(from->position, V2scale(axis, intersection_depth*-0.5f)); V2 line = V2sub(*to, *from);
to->position = V2add(to->position, V2scale(axis, intersection_depth*0.5f)); float len = V2length(line);
float diff = len - BOX_SIZE;
line = V2normalize(line);
*from = V2add(*from, V2scale(line, diff * 0.5f));
*to = V2sub(*to, V2scale(line, diff * 0.5f));
} }
} }
} }
// Reupdate the positions of the bodies based on how the vertices changed
for (int i = 0; i < num_bodies; i++)
{
float upper_right_angle = V2angle(V2sub(bodies[i].vertices[0], bodies[i].body->position));
bodies[i].body->rotation = upper_right_angle - (PI / 4.0f);
V2 avg = {0};
for (int v_i = 0; v_i < 4; v_i++)
{
avg = V2add(avg, bodies[i].vertices[v_i]);
}
avg = V2scale(avg, 1.0f / 4.0f);
bodies[i].body->position = avg;
}
free(bodies); free(bodies);
} }

@ -158,6 +158,7 @@ static void frame(void)
ENetPacket *packet = enet_packet_create((void *)&curmsg, sizeof(curmsg), ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT); ENetPacket *packet = enet_packet_create((void *)&curmsg, sizeof(curmsg), ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT);
enet_peer_send(peer, 0, packet); enet_peer_send(peer, 0, packet);
// @BeforeShip client side prediction and rollback to previous server authoritative state, then replay inputs
process(&gs, (float)sapp_frame_duration()); process(&gs, (float)sapp_frame_duration());
} }

@ -89,6 +89,8 @@ void dbg_rect(V2 center);
// all the math is static so that it can be defined in each compilation unit its included in // all the math is static so that it can be defined in each compilation unit its included in
#define PI 3.14159f
static V2 V2add(V2 a, V2 b) static V2 V2add(V2 a, V2 b)
{ {
return (V2){ return (V2){
@ -139,6 +141,12 @@ static V2 V2rotate(V2 vec, float theta)
}; };
} }
// also known as atan2
static float V2angle(V2 vec)
{
return atan2f(vec.y, vec.x);
}
static V2 V2sub(V2 a, V2 b) static V2 V2sub(V2 a, V2 b)
{ {
return (V2){ return (V2){

Loading…
Cancel
Save