summaryrefslogtreecommitdiff
path: root/testsat.cpp
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2025-02-07 00:34:44 +1100
committerquou <quou@disroot.org>2025-02-07 00:34:44 +1100
commit73d7f8325aeb00cbaec89a1c15602b9bd85ff04e (patch)
treefbef9f89fad53a86882aab0b17a2ff2d7290ad41 /testsat.cpp
parent5d09e4f0880b182a2f4c89508744c27823ed554e (diff)
collision yes/no
Diffstat (limited to 'testsat.cpp')
-rw-r--r--testsat.cpp155
1 files changed, 155 insertions, 0 deletions
diff --git a/testsat.cpp b/testsat.cpp
new file mode 100644
index 0000000..45f3891
--- /dev/null
+++ b/testsat.cpp
@@ -0,0 +1,155 @@
+#include <SDL2/SDL.h>
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "maths.cpp"
+
+struct Shape {
+ v2f* points;
+ int count;
+
+ Shape(std::initializer_list<v2f> in) {
+ int i;
+ points = (v2f*)malloc(in.size() * sizeof *points);
+ count = in.size();
+ for (i = 0; i < count; i++)
+ points[i] = *(in.begin() + i);
+ }
+
+ Shape(const Shape& other) {
+ int s = other.count * sizeof *points;
+ count = other.count;
+ points = (v2f*)malloc(s);
+ memcpy(points, other.points, s);
+ }
+
+ ~Shape() {
+ free(points);
+ }
+
+ void render(SDL_Renderer* ren) {
+ int i, c = count;
+ for (i = 0; i < c; i++) {
+ v2f a = points[i];
+ v2f b = points[(i + 1) % c];
+ SDL_RenderDrawLine(
+ ren,
+ (int)a.x,
+ (int)a.y,
+ (int)b.x,
+ (int)b.y
+ );
+ }
+ }
+
+ std::pair<v2f*, int> normals() const {
+ int c = (count >> 1) + 1, i;
+ v2f* normals = (v2f*)malloc(c * sizeof *normals);
+ for (i = 0; i < count; i++) {
+ v2f a = points[i];
+ v2f b = points[(i + 1) % count];
+ v2f e = a - b;
+ v2f n = v2f::normalised(v2f(e.y, -e.x));
+ normals[i] = n;
+ }
+ return { normals, i };
+ }
+};
+
+bool intersect(Shape& a, Shape& b) {
+ bool r = true;
+ int i;
+ auto[fn, fnc] = a.normals();
+ auto[sn, snc] = b.normals();
+ auto project = [](const Shape& shape, v2f axis) {
+ int i;
+ float mini = INFINITY;
+ float maxi = -INFINITY;
+ for (i = 0; i < shape.count; i++) {
+ v2f p = shape.points[i];
+ float d = v2f::dot(p, axis);
+ if (d < mini) mini = d;
+ if (d > maxi) maxi = d;
+ }
+ return std::pair<float, float>{ mini, maxi };
+ };
+ for (i = 0; i < fnc; i++) {
+ v2f axis = fn[i];
+ auto [fp1, fp2] = project(a, axis);
+ auto [sp1, sp2] = project(b, axis);
+ if (fp2 > sp1 && fp1 > sp2) {
+ r = false;
+ goto end;
+ }
+ }
+ for (i = 0; i < snc; i++) {
+ v2f axis = sn[i];
+ auto [fp1, fp2] = project(a, axis);
+ auto [sp1, sp2] = project(b, axis);
+ if (fp2 > sp1 && fp1 > sp2) {
+ r = false;
+ goto end;
+ }
+ }
+end:
+ free(fn);
+ free(sn);
+ return r;
+}
+
+int main(int argc, const char** argv) {
+ int r = 1;
+ SDL_Window* window;
+ SDL_Renderer* ren;
+ SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
+ SDL_CreateWindowAndRenderer(
+ 800,
+ 800,
+ 0,
+ &window,
+ &ren
+ );
+ Shape a({
+ v2f(300.0f, 300.0f),
+ v2f(400.0f, 400.0f),
+ v2f(250.0f, 500.0f),
+ });
+ Shape tri({
+ v2f(0.0f, 0.0f),
+ v2f(50.0f, 200.0f),
+ v2f(200.0f, 100.0f),
+ });
+ while (r) {
+ int i;
+ SDL_Event e;
+ while (SDL_PollEvent(&e)) {
+ switch (e.type) {
+ case SDL_QUIT:
+ r = 0;
+ break;
+ }
+ }
+ int mx, my;
+ SDL_GetMouseState(&mx, &my);
+ Shape b(tri);
+ for (i = 0; i < b.count; i++) {
+ v2f& p = b.points[i];
+ p.x += mx;
+ p.y += my;
+ }
+ SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0x00);
+ SDL_RenderClear(ren);
+ SDL_SetRenderDrawColor(ren, 0xff, 0x00, 0xff, 0xff);
+ a.render(ren);
+ if (intersect(a, b)) {
+ SDL_SetRenderDrawColor(ren, 0xff, 0x00, 0x00, 0xff);
+ }
+ b.render(ren);
+ SDL_RenderPresent(ren);
+ }
+ SDL_DestroyRenderer(ren);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+ return 0;
+}