More physics code

This commit is contained in:
Edgaru089 2024-02-29 16:51:46 +08:00
parent e8f0b0c63a
commit 663a3401e6
7 changed files with 125 additions and 4 deletions

View File

@ -12,6 +12,18 @@
double physics_Gravity = 5.0; double physics_Gravity = 5.0;
Box2 physics_HitboxAbsolute(Component_Hitbox *hitbox) {
Entity *super = hitbox->super;
if (!super->position)
return hitbox->box;
else {
Box2 box = hitbox->box;
box.lefttop = vec2_Add(box.lefttop, super->position->position);
return box;
}
}
System_Physics *physics_NewSystem() { System_Physics *physics_NewSystem() {
System_Physics *sys = malloc(sizeof(System_Physics)); System_Physics *sys = malloc(sizeof(System_Physics));
@ -43,9 +55,13 @@ void physics_DeleteEntity(System_Physics *sys, uintptr_t id) {
} }
inline void _physics_AdvanceEntity(Entity *e, Duration deltaTime) { // Defined in Physics_Move.c
if (!e->position) void _physics_MoveX(System_Physics *sys, Entity *e, Duration deltaTime);
return; void _physics_MoveY(System_Physics *sys, Entity *e, Duration deltaTime);
inline void _physics_AdvanceEntity(System_Physics *sys, Entity *e, Duration deltaTime) {
ASSERT(e->position && "_physics_AdvanceEntity() called on entity with no position");
// Short path // Short path
if (!e->hitbox || e->hitbox->fixed) { if (!e->hitbox || e->hitbox->fixed) {
@ -59,6 +75,8 @@ inline void _physics_AdvanceEntity(Entity *e, Duration deltaTime) {
} }
// Long path // Long path
_physics_MoveX(sys, e, deltaTime);
_physics_MoveY(sys, e, deltaTime);
} }
@ -81,6 +99,6 @@ void physics_Advance(System_Physics *sys, Duration deltaTime) {
i != NULL; i != NULL;
i = tree_Node_Next(i)) { i = tree_Node_Next(i)) {
Component_Position *pos = *((Component_Position **)i->data); Component_Position *pos = *((Component_Position **)i->data);
_physics_AdvanceEntity(pos->super, deltaTime); _physics_AdvanceEntity(sys, pos->super, deltaTime);
} }
} }

View File

@ -33,6 +33,9 @@ typedef struct {
bool fixed; bool fixed;
} Component_Hitbox; } Component_Hitbox;
// Returns the absolute version of the hitbox.
Box2 physics_HitboxAbsolute(Component_Hitbox *hitbox);
// Physics manager // Physics manager
typedef struct { typedef struct {

View File

@ -139,6 +139,7 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="Types.c" /> <ClCompile Include="Types.c" />
<ClCompile Include="Component_Physics.c" /> <ClCompile Include="Component_Physics.c" />
<ClCompile Include="Physics_Move.c" />
<ClCompile Include="util\queue.c" /> <ClCompile Include="util\queue.c" />
<ClCompile Include="util\tree.c" /> <ClCompile Include="util\tree.c" />
<ClCompile Include="util\vector.c" /> <ClCompile Include="util\vector.c" />

View File

@ -58,6 +58,9 @@
</ClCompile> </ClCompile>
<ClCompile Include="Component_Physics.c"> <ClCompile Include="Component_Physics.c">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Physics_Move.c">
<Filter>源文件</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

79
Physics_Move.c Normal file
View File

@ -0,0 +1,79 @@
#include "Component_Physics.h"
#include "Entity.h"
#include "Types.h"
#include "util/tree.h"
#include <stdlib.h>
static const double EPS = 1e-6;
static inline double dabs(double x) {
return x < 0 ? -x : x;
}
void _physics_MoveX(System_Physics *sys, Entity *e, Duration deltaTime) {
double delta = e->position->velocity.x * duration_Seconds(deltaTime);
if (dabs(delta) < EPS)
return;
for (tree_Node *i = tree_FirstNode(sys->hit);
i != NULL;
i = tree_Node_Next(i)) {
Component_Hitbox *tohit = *((Component_Hitbox **)i->data);
if (!tohit->fixed)
continue;
if (box2_Intersects(tohit->box, box2_OffsetX(e->hitbox->box, delta), NULL)) {
if (delta > 0) {
// Moves right, hits left edge
double maxdelta = tohit->box.lefttop.x - e->hitbox->box.lefttop.x - e->hitbox->box.size.x;
delta = maxdelta - EPS;
} else {
// Moves left, hits right edge
double maxdelta = tohit->box.lefttop.x - e->hitbox->box.lefttop.x + tohit->box.size.x;
delta = maxdelta + EPS;
}
}
if (dabs(delta) < EPS)
break;
}
if (dabs(delta) > EPS)
e->position->position.x += delta;
}
void _physics_MoveY(System_Physics *sys, Entity *e, Duration deltaTime) {
double delta = e->position->velocity.y * duration_Seconds(deltaTime);
if (dabs(delta) < EPS)
return;
for (tree_Node *i = tree_FirstNode(sys->hit);
i != NULL;
i = tree_Node_Next(i)) {
Component_Hitbox *tohit = *((Component_Hitbox **)i->data);
if (!tohit->fixed)
continue;
if (box2_Intersects(tohit->box, box2_OffsetY(e->hitbox->box, delta), NULL)) {
if (delta > 0) {
// Moves down, hits top edge
double maxdelta = tohit->box.lefttop.y - e->hitbox->box.lefttop.y - e->hitbox->box.size.y;
delta = maxdelta - EPS;
} else {
// Moves up, hits bottom edge
double maxdelta = tohit->box.lefttop.y - e->hitbox->box.lefttop.y + tohit->box.size.y;
delta = maxdelta + EPS;
}
}
if (dabs(delta) < EPS)
break;
}
if (dabs(delta) > EPS)
e->position->position.y += delta;
}

13
Types.c
View File

@ -55,3 +55,16 @@ bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection) {
return false; return false;
} }
} }
Box2 box2_Offset(Box2 box, Vec2 offset) {
box.lefttop = vec2_Add(box.lefttop, offset);
return box;
}
Box2 box2_OffsetX(Box2 box, double offsetX) {
box.lefttop.x += offsetX;
return box;
}
Box2 box2_OffsetY(Box2 box, double offsetY) {
box.lefttop.y += offsetY;
return box;
}

View File

@ -28,6 +28,10 @@ typedef struct {
// Intersection test. // Intersection test.
bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection); bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection);
Box2 box2_Offset(Box2 box, Vec2 offset);
Box2 box2_OffsetX(Box2 box, double offsetX);
Box2 box2_OffsetY(Box2 box, double offsetY);
typedef struct { typedef struct {
uint64_t microseconds; uint64_t microseconds;