diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj b/SpaceCadetPinball/SpaceCadetPinball.vcxproj
index 5bcbfb4..ccbfe7e 100644
--- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj
+++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj
@@ -172,9 +172,12 @@
+
+
+
@@ -185,6 +188,7 @@
+
@@ -228,9 +232,12 @@
+
+
+
@@ -241,6 +248,7 @@
+
diff --git a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters
index 514302a..08f0e7d 100644
--- a/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters
+++ b/SpaceCadetPinball/SpaceCadetPinball.vcxproj.filters
@@ -19,6 +19,18 @@
{33813da8-81ac-449c-b19a-9756272519b9}
+
+ {0aa40751-a44a-400e-8809-ee817161e8e0}
+
+
+ {d70e7fca-2294-41a4-9cf8-78052bdb9aa4}
+
+
+ {01aed326-d2ec-457a-b99f-08ef32ed97fa}
+
+
+ {7ed2796a-da4b-4edd-8783-53e45d8d1c88}
+
@@ -168,6 +180,18 @@
Header Files
+
+ Header Files\TEdgeSegment
+
+
+ Header Files\TCollisionComponent
+
+
+ Header Files\TEdgeSegment
+
+
+ Header Files\TEdgeSegment
+
@@ -314,6 +338,18 @@
Source Files
+
+ Source Files\TEdgeSegment
+
+
+ Source Files\TCollisionComponent
+
+
+ Source Files\TEdgeSegment
+
+
+ Source Files\TEdgeSegment
+
diff --git a/SpaceCadetPinball/TCircle.cpp b/SpaceCadetPinball/TCircle.cpp
new file mode 100644
index 0000000..2ae524b
--- /dev/null
+++ b/SpaceCadetPinball/TCircle.cpp
@@ -0,0 +1,16 @@
+#include "pch.h"
+#include "TCircle.h"
+
+TCircle::TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned visualFlag, float* floatArr,
+ float radius): TEdgeSegment(collComp, someFlagPtr, visualFlag)
+{
+ Circle.RadiusSq = radius * radius;
+ Circle.X = *floatArr;
+ Circle.Y = floatArr[1];
+ Circle.Unknown2 = floatArr[2];
+}
+
+double TCircle::FindCollisionDistance(ray_type* ray)
+{
+ return maths::ray_intersect_circle(ray, &Circle);
+}
\ No newline at end of file
diff --git a/SpaceCadetPinball/TCircle.h b/SpaceCadetPinball/TCircle.h
new file mode 100644
index 0000000..f675dc3
--- /dev/null
+++ b/SpaceCadetPinball/TCircle.h
@@ -0,0 +1,12 @@
+#pragma once
+#include "maths.h"
+#include "TEdgeSegment.h"
+
+class TCircle :
+ public TEdgeSegment
+{
+ circle_type Circle;
+
+ TCircle(TCollisionComponent* collComp, char* someFlagPtr, unsigned int visualFlag, float* floatArr, float radius);
+ double FindCollisionDistance(ray_type* ray) override;
+};
diff --git a/SpaceCadetPinball/TCollisionComponent.cpp b/SpaceCadetPinball/TCollisionComponent.cpp
new file mode 100644
index 0000000..dae0a13
--- /dev/null
+++ b/SpaceCadetPinball/TCollisionComponent.cpp
@@ -0,0 +1,2 @@
+#include "pch.h"
+#include "TCollisionComponent.h"
diff --git a/SpaceCadetPinball/TCollisionComponent.h b/SpaceCadetPinball/TCollisionComponent.h
new file mode 100644
index 0000000..7175d95
--- /dev/null
+++ b/SpaceCadetPinball/TCollisionComponent.h
@@ -0,0 +1,5 @@
+#pragma once
+class TCollisionComponent
+{
+};
+
diff --git a/SpaceCadetPinball/TEdgeSegment.cpp b/SpaceCadetPinball/TEdgeSegment.cpp
new file mode 100644
index 0000000..87234c2
--- /dev/null
+++ b/SpaceCadetPinball/TEdgeSegment.cpp
@@ -0,0 +1,10 @@
+#include "pch.h"
+#include "TEdgeSegment.h"
+
+TEdgeSegment::TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsigned visualFlag)
+{
+ this->CollisionComponent = collComp;
+ this->PinbCompFlag2Ptr = someFlag;
+ this->VisualFlag = visualFlag;
+ this->Unknown3_0 = 0;
+}
diff --git a/SpaceCadetPinball/TEdgeSegment.h b/SpaceCadetPinball/TEdgeSegment.h
new file mode 100644
index 0000000..369b5f3
--- /dev/null
+++ b/SpaceCadetPinball/TEdgeSegment.h
@@ -0,0 +1,23 @@
+#pragma once
+#include "TCollisionComponent.h"
+#include "maths.h"
+#include "TBall.h"
+
+class TEdgeSegment
+{
+public:
+ TCollisionComponent* CollisionComponent;
+ char* PinbCompFlag2Ptr;
+ char Unknown3_0;
+ char Unknown3_1;
+ char Unknown3_2;
+ char Unknown3_3;
+ char Unknown4;
+ int VisualFlag;
+
+ TEdgeSegment(TCollisionComponent* collComp, char* someFlag, unsigned int visualFlag);
+ //virtual ~TEdgeSegment() = 0;
+ virtual void place_in_grid() = 0;
+ virtual double FindCollisionDistance(ray_type* ray) = 0;
+ virtual void EdgeCollision(TBall* ball, float coef) = 0;
+};
diff --git a/SpaceCadetPinball/TLine.cpp b/SpaceCadetPinball/TLine.cpp
new file mode 100644
index 0000000..de2f452
--- /dev/null
+++ b/SpaceCadetPinball/TLine.cpp
@@ -0,0 +1,38 @@
+#include "pch.h"
+#include "TLine.h"
+
+
+TLine::TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, float x0, float y0, float x1,
+ float y1): TEdgeSegment(collCmp, flagPtr, visualFlag)
+{
+ Start.X = x0;
+ Start.Y = y0;
+ End.X = x1;
+ End.Y = y1;
+ maths::line_init(&Line, x0, y0, x1, y1);
+}
+
+TLine::TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, struct vector_type* start,
+ struct vector_type* end) : TEdgeSegment(collCmp, flagPtr, visualFlag)
+{
+ Start = *start;
+ End = *end;
+ maths::line_init(&Line, Start.X, Start.Y, End.X, End.Y);
+}
+
+void TLine::Offset(float offset)
+{
+ float offX = offset * Line.PerpendicularL.X;
+ float offY = offset * Line.PerpendicularL.Y;
+
+ Start.X += offX;
+ Start.Y += offY;
+ End.X += offX;
+ End.Y += offY;
+ maths::line_init(&Line, Start.X, Start.Y, End.X, End.Y);
+}
+
+double TLine::FindCollisionDistance(ray_type* ray)
+{
+ return maths::ray_intersect_line(ray, &Line);
+}
\ No newline at end of file
diff --git a/SpaceCadetPinball/TLine.h b/SpaceCadetPinball/TLine.h
new file mode 100644
index 0000000..ebfc0cf
--- /dev/null
+++ b/SpaceCadetPinball/TLine.h
@@ -0,0 +1,17 @@
+#pragma once
+#include "maths.h"
+#include "TEdgeSegment.h"
+
+class TLine :
+ public TEdgeSegment
+{
+public:
+ line_type Line;
+ vector_type Start;
+ vector_type End;
+ TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, float x0, float y0, float x1, float y1);
+ TLine(TCollisionComponent* collCmp, char* flagPtr, unsigned int visualFlag, struct vector_type* start,
+ struct vector_type* end);
+ void Offset(float offset);
+ double FindCollisionDistance(ray_type* ray) override;
+};
diff --git a/SpaceCadetPinball/maths.cpp b/SpaceCadetPinball/maths.cpp
index 8541f1b..47e5e57 100644
--- a/SpaceCadetPinball/maths.cpp
+++ b/SpaceCadetPinball/maths.cpp
@@ -83,7 +83,6 @@ int maths::overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectang
{
int v3; // esi
int v4; // edi
- int v5; // esi
int v6; // esi
int v7; // edi
@@ -100,7 +99,7 @@ int maths::overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectang
v4 = rect2->XPosition;
}
dstRect->Width = v3 + v4 + 1;
- v5 = rect1->YPosition;
+ int v5 = rect1->YPosition;
if (v5 >= rect2->YPosition)
{
dstRect->YPosition = rect2->YPosition;
@@ -116,3 +115,133 @@ int maths::overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectang
dstRect->Height = v6 + v7 + 1;
return dstRect->Width <= rect2->Width + rect1->Width && dstRect->Height <= rect2->Height + rect1->Height;
}
+
+float maths::ray_intersect_circle(ray_type* ray, circle_type* circle)
+{
+ // O - ray origin
+ // D - ray direction
+ // C - circle center
+ // R - circle radius
+ // L, C - O, vector between O and C
+ float Lx = circle->X - ray->Origin.X;
+ float Ly = circle->Y - ray->Origin.Y;
+
+ // Tca, L dot D, projection of L on D
+ float Tca = Ly * ray->Direction.Y + Lx * ray->Direction.X;
+ if (Tca < 0.0) // No intersection if Tca is negative
+ return 1000000000.0f;
+
+ // L dot L, distance from ray origin to circle center
+ float LMagSq = Ly * Ly + Lx * Lx;
+
+ // If ray origin is inside of the circle
+ // T0 = Tca - Sqrt(rad^2 - d^2). d = sqrt(L dot L - Tca dot Tca)
+ if (LMagSq < circle->RadiusSq)
+ return Tca - sqrt(circle->RadiusSq - LMagSq + Tca * Tca);
+
+ // Thc^2 = rad^2 - d = rad^2 - L dot L + Tca dot Tca
+ float ThcSq = circle->RadiusSq - LMagSq + Tca * Tca;
+ if (ThcSq < 0.0) // No intersection if Thc is negative
+ return 1000000000.0f;
+
+ // T0 = Tca - Thc, distance from origin to first intersection
+ float T0 = Tca - sqrt(ThcSq);
+ if (T0 < 0.0 || T0 > ray->MaxDistance)
+ return 1000000000.0f;
+ return T0;
+}
+
+
+float maths::normalize_2d(vector_type* vec)
+{
+ float mag = sqrt(vec->X * vec->X + vec->Y * vec->Y);
+ if (0.0 != mag)
+ {
+ vec->X = 1.0f / mag * vec->X;
+ vec->Y = 1.0f / mag * vec->Y;
+ }
+ return mag;
+}
+
+
+void maths::line_init(line_type* line, float x0, float y0, float x1, float y1)
+{
+ float v9; // st7
+ bool lineDirection; // pf
+ float v11; // eax
+
+ line->Direction.X = x1 - x0;
+ line->Direction.Y = y1 - y0;
+ normalize_2d(&line->Direction);
+ line->PerpendicularL.X = line->Direction.Y;
+ line->PerpendicularL.Y = -line->Direction.X;
+ line->PreComp1 = -(line->Direction.Y * x0) + (line->Direction.X * y0);
+ if (line->Direction.X >= 0.000000001 || line->Direction.X <= -0.000000001)
+ {
+ v9 = x1;
+ lineDirection = x0 >= x1;
+ v11 = x0;
+ }
+ else
+ {
+ line->Direction.X = 0.0;
+ v9 = y1;
+ lineDirection = y0 >= y1;
+ v11 = y0;
+ }
+ if (lineDirection)
+ {
+ line->Origin.X = v9;
+ line->Origin.Y = v11;
+ }
+ else
+ {
+ line->Origin.Y = v9;
+ line->Origin.X = v11;
+ }
+}
+
+float maths::ray_intersect_line(ray_type* ray, line_type* line)
+{
+ // Similar to https://rootllama.wordpress.com/2014/06/20/ray-line-segment-intersection-test-in-2d/
+ float perpDot; // st7
+ float result; // st7
+ float v4; // st6
+ bool v5; // c0
+ bool v6; // c3
+ float v7; // st6
+
+ perpDot = line->PerpendicularL.Y * ray->Direction.Y + ray->Direction.X * line->PerpendicularL.X;
+ if (perpDot < 0.0)
+ {
+ result = -((ray->Origin.X * line->PerpendicularL.X + ray->Origin.Y * line->PerpendicularL.Y + line->PreComp1)
+ / perpDot);
+ if (result >= -ray->Unknown7 && result <= ray->MaxDistance)
+ {
+ line->Unknown9 = result * ray->Direction.X + ray->Origin.X;
+ v4 = result * ray->Direction.Y + ray->Origin.Y;
+ line->Unknown10 = v4;
+ if (0.0 == line->Direction.X)
+ {
+ if (v4 >= line->Origin.X)
+ {
+ v5 = v4 < line->Origin.Y;
+ v6 = v4 == line->Origin.Y;
+ if (v5 || v6)
+ return result;
+ return 1000000000.0;
+ }
+ }
+ else if (line->Origin.X <= line->Unknown9)
+ {
+ v7 = line->Unknown9;
+ v5 = v7 < line->Origin.Y;
+ v6 = v7 == line->Origin.Y;
+ if (v5 || v6)
+ return result;
+ return 1000000000.0;
+ }
+ }
+ }
+ return 1000000000.0;
+}
diff --git a/SpaceCadetPinball/maths.h b/SpaceCadetPinball/maths.h
index c3433e9..bdd9b45 100644
--- a/SpaceCadetPinball/maths.h
+++ b/SpaceCadetPinball/maths.h
@@ -1,5 +1,11 @@
#pragma once
+struct vector_type
+{
+ float X;
+ float Y;
+};
+
struct __declspec(align(4)) rectangle_type
{
@@ -9,10 +15,46 @@ struct __declspec(align(4)) rectangle_type
int Height;
};
+struct circle_type
+{
+ float X;
+ float Y;
+ float Unknown2;
+ float RadiusSq;
+};
+
+struct __declspec(align(4)) ray_type
+{
+ vector_type Origin;
+ float Unknown2;
+ vector_type Direction;
+ float Unknown5;
+ float MaxDistance;
+ float Unknown7;
+};
+
+struct __declspec(align(4)) line_type
+{
+ vector_type PerpendicularL;
+ float Unknown2;
+ vector_type Direction;
+ float Unknown5;
+ float PreComp1;
+ vector_type Origin;
+ float Unknown9;
+ float Unknown10;
+ float Unknown11;
+};
+
+
class maths
{
public:
static void enclosing_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect);
static int rectangle_clip(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect);
static int overlapping_box(rectangle_type* rect1, rectangle_type* rect2, rectangle_type* dstRect);
+ static float ray_intersect_circle(ray_type* ray, circle_type* circle);
+ static float normalize_2d(vector_type* vec);
+ static void line_init(line_type* line, float x0, float y0, float x1, float y1);
+ static float ray_intersect_line(ray_type* ray, line_type* line);
};