diff --git a/Component_Physics.c b/Component_Physics.c
index 54d08b5..8bfb826 100644
--- a/Component_Physics.c
+++ b/Component_Physics.c
@@ -12,6 +12,18 @@
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 *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) {
- if (!e->position)
- return;
+// Defined in Physics_Move.c
+void _physics_MoveX(System_Physics *sys, Entity *e, Duration deltaTime);
+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
if (!e->hitbox || e->hitbox->fixed) {
@@ -59,6 +75,8 @@ inline void _physics_AdvanceEntity(Entity *e, Duration deltaTime) {
}
// 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 = tree_Node_Next(i)) {
Component_Position *pos = *((Component_Position **)i->data);
- _physics_AdvanceEntity(pos->super, deltaTime);
+ _physics_AdvanceEntity(sys, pos->super, deltaTime);
}
}
diff --git a/Component_Physics.h b/Component_Physics.h
index 8c6028c..f197ff1 100644
--- a/Component_Physics.h
+++ b/Component_Physics.h
@@ -33,6 +33,9 @@ typedef struct {
bool fixed;
} Component_Hitbox;
+// Returns the absolute version of the hitbox.
+Box2 physics_HitboxAbsolute(Component_Hitbox *hitbox);
+
// Physics manager
typedef struct {
diff --git a/JacksEscape.vcxproj b/JacksEscape.vcxproj
index b72ed88..d27a7cf 100644
--- a/JacksEscape.vcxproj
+++ b/JacksEscape.vcxproj
@@ -139,6 +139,7 @@
+
diff --git a/JacksEscape.vcxproj.filters b/JacksEscape.vcxproj.filters
index 4c430f8..34f0bc6 100644
--- a/JacksEscape.vcxproj.filters
+++ b/JacksEscape.vcxproj.filters
@@ -58,6 +58,9 @@
源文件
+
+
+ 源文件
diff --git a/Physics_Move.c b/Physics_Move.c
new file mode 100644
index 0000000..91aaf51
--- /dev/null
+++ b/Physics_Move.c
@@ -0,0 +1,79 @@
+
+#include "Component_Physics.h"
+#include "Entity.h"
+#include "Types.h"
+#include "util/tree.h"
+
+#include
+
+
+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;
+}
diff --git a/Types.c b/Types.c
index 75553b6..f6d19d8 100644
--- a/Types.c
+++ b/Types.c
@@ -55,3 +55,16 @@ bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection) {
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;
+}
diff --git a/Types.h b/Types.h
index a306d44..8c11316 100644
--- a/Types.h
+++ b/Types.h
@@ -28,6 +28,10 @@ typedef struct {
// Intersection test.
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 {
uint64_t microseconds;