-
Notifications
You must be signed in to change notification settings - Fork 0
/
GameMath.m
140 lines (128 loc) · 4.7 KB
/
GameMath.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
* GameMath.c
* JazzBall
*
* Created by Julian on 4/1/09.
* Copyright 2009 __MyCompanyName__. All rights reserved.
*
*/
#include "GameMath.h"
#import <Foundation/NSObjCRuntime.h>
CGFloat distanceBetweenPoints (CGPoint first, CGPoint second) {
CGFloat deltaX = second.x - first.x;
CGFloat deltaY = second.y - first.y;
#if defined(__LP64__) && __LP64__
return sqrt(deltaX*deltaX + deltaY*deltaY );
#else
return sqrtf(deltaX*deltaX + deltaY*deltaY);
#endif
};
CGFloat squaredDistanceBetweenPoints (CGPoint first, CGPoint second) {
CGFloat deltaX = second.x - first.x;
CGFloat deltaY = second.y - first.y;
return (deltaX*deltaX + deltaY*deltaY);
};
/*
BOOL CGRectAlmostEqualToRect(CGRect r1, CGRect r2) {
return ABS(r1.origin.x - r2.origin.x) < ALMOST_EQUAL_THRESHOLD && ABS(r1.origin.y - r2.origin.y) < ALMOST_EQUAL_THRESHOLD && ABS(r1.size.width - r2.size.width) < ALMOST_EQUAL_THRESHOLD && ABS(r1.size.height - r2.size.height) < ALMOST_EQUAL_THRESHOLD;
}
*/
Vector OrthogonalVector(Vector a) {
CGFloat denom;
#if defined(__LP64__) && __LP64__
denom = sqrt(a.x*a.x + a.y*a.y);
#else
denom = sqrtf(a.x*a.x + a.y*a.y);
#endif
return MakeVector(-a.y*signum(a.x)/denom, ABS(a.x)/denom);
}
Vector ProjectVector(Vector v, Vector proj) {
Vector projHat = UnitDirectionVector(proj);
CGFloat dotProduct = v.x*proj.x + v.y*proj.y;
return MakeVector(projHat.x*dotProduct, projHat.y*dotProduct);
}
CGFloat solveQuadraticForGreaterSolution(CGFloat a, CGFloat b, CGFloat c) {
CGFloat D;
// dlog(@"quadratic: a=%f, b=%f, c=%f", a, b, c);
#if defined(__LP64__) && __LP64__
D = sqrt(b*b - 4*a*c);
#else
D = sqrtf(b*b - 4*a*c);
#endif
CGFloat t = -0.5*(b + signum(b)*D);
CGFloat r1 = t/a;
CGFloat r2 = c/t;
return MAX(r1, r2);
}
CGFloat solveQuadraticForLesserSolution(CGFloat a, CGFloat b, CGFloat c) {
CGFloat D;
// dlog(@"quadratic: a=%f, b=%f, c=%f", a, b, c);
#if defined(__LP64__) && __LP64__
D = sqrt(b*b - 4*a*c);
#else
D = sqrtf(b*b - 4*a*c);
#endif
CGFloat t = -0.5*(b + signum(b)*D);
CGFloat r1 = t/a;
CGFloat r2 = c/t;
// dlog(@"SolveQuadraticForLesserSolultion: %f, %f", r1, r2);
return MIN(r1, r2);
}
Vector RandomVectorWithMagnitude(CGFloat magnitude) {
CGFloat theta = (float)myrandom()/RAND_MAX*2*M_PI;
// convert polar coords to euclidean
return MakeVector(magnitude*cos(theta), magnitude*sin(theta));
}
// in RandomVelocity. we make sure that the velocity isn't too x- or y-oriented,
// which would make the level start boring.
Vector RandomVelocityWithMagnitude(CGFloat magnitude) {
CGFloat theta = 0;
while (1) {
theta = (float)myrandom()/RAND_MAX*2*M_PI;
CGFloat thetaP = theta;
while (thetaP > .5*M_PI) {
thetaP -= .5*M_PI;
}
if (thetaP >= .5*.25*M_PI && thetaP <= .5*.75*M_PI) {
break;
}
dlog(@"repeat for theta=%f, thetaP=%f", theta*180.0/M_PI, thetaP*180.0/M_PI);
}
// convert polar coords to euclidean
return MakeVector(magnitude*cos(theta), magnitude*sin(theta));
}
CGRect JBRectSubtractRect(CGRect container, CGRect other) {
CGFloat w, h;
BOOL hsplit = other.size.width == container.size.width;
w = hsplit ? container.size.width : container.size.width - other.size.width;
h = !hsplit ? container.size.height : container.size.height - other.size.height;
if (CGPointEqualToPoint(container.origin, other.origin)) {
return CGRectMake(hsplit ? other.origin.x : other.origin.x + other.size.width, hsplit ? other.origin.y + other.size.height : other.origin.y, w, h);
}
return CGRectMake(container.origin.x, container.origin.y, w, h);
}
BOOL CGRectAdjacentToRect(CGRect r1, CGRect r2) {
JBRange r1Range, r2Range;
// first test: adjacent in x
if (r2.origin.x == r1.origin.x + r1.size.width) {
r1Range = JBMakeRange(r1.origin.y, r1.size.height);
r2Range = JBMakeRange(r2.origin.y, r2.size.height);
return RangeIntersectsRange(r1Range, r2Range);
}
else if (r2.origin.y == r1.origin.y + r1.size.height) {
r1Range = JBMakeRange(r1.origin.x, r1.size.width);
r2Range = JBMakeRange(r2.origin.x, r2.size.width);
return RangeIntersectsRange(r1Range, r2Range);
}
else if (r1.origin.x == r2.origin.x + r2.size.width) {
r1Range = JBMakeRange(r1.origin.y, r1.size.height);
r2Range = JBMakeRange(r2.origin.y, r2.size.height);
return RangeIntersectsRange(r1Range, r2Range);
}
else if (r1.origin.y == r2.origin.y + r2.size.height) {
r1Range = JBMakeRange(r1.origin.x, r1.size.width);
r2Range = JBMakeRange(r2.origin.x, r2.size.width);
return RangeIntersectsRange(r1Range, r2Range);
}
return NO;
}