File: Math.c

package info (click to toggle)
openclonk 8.1-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 169,656 kB
  • sloc: cpp: 180,484; ansic: 108,988; xml: 31,371; python: 1,223; php: 767; makefile: 148; sh: 101; javascript: 34
file content (200 lines) | stat: -rw-r--r-- 4,799 bytes parent folder | download | duplicates (5)
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/**
	Math.c
	Any kind of help with calculations.
	
	@author Maikel, flgr, Newton, Tyron, Zapper
*/

// Returns the offset to x.
// documented in /docs/sdk/script/fn
global func AbsX(int x)
{
	return x - GetX();
}

// Returns the offset to y.
// documented in /docs/sdk/script/fn
global func AbsY(int y)
{
	return y - GetY();
}

// Supports negative values, and can deliver random values between two bounds.
// documented in /docs/sdk/script/fn
global func RandomX(int start, int end)
{
	var swap;
	// Values swapped: reswap them.
	if (start > end)
	{
		swap = start;
		start = end;
		end = swap;
	}
	// Return random factor.
	return Random(end - start + 1) + start;
}

// Returns the sign of x.
global func Sign(int x)
{
	return (x>0)-(x<0);
}

// Tangens.
// documented in /docs/sdk/script/fn
global func Tan(int angle, int radius, int prec)
{
	return radius * Sin(angle, radius * 100, prec) / Cos(angle, radius * 100, prec);
}

global func Normalize(int angle, int start, int precision)
{
	if (!precision)
		precision = 1;
	var end = precision * 360 + start;
	
	while (angle < start)
		angle += precision * 360;
	while (angle >= end)
		angle -= precision * 360;

	return angle;
}

global func ComDirLike(int comdir1, int comdir2)
{
	if (comdir1 == comdir2)
		return true;
	if (comdir1 == COMD_Stop || comdir2 == COMD_Stop)
		return false;
	if (comdir1 == COMD_None || comdir2 == COMD_None)
		return false;
	if (comdir1 % 8 + 1 == comdir2)
		return true;
	if (comdir1 == comdir2 % 8 + 1)
		return true;
	return false;
}

// the shortest direction (left/right) to turn from one angle to another
// (for example for homing projectiles or aiming)
global func GetTurnDirection(
	int from /* the angle at which the turning starts */
	, int to /* the angle that should be turned towards */)
{
/*
	// code for a homing missile
	var dir = GetTurnDirection(my_angle, target_angle);
	SetR(GetR() + dir / 10);
	SetSpeed(Sin(GetR(), 10), -Cos(GetR(), 10));
*/
	 var dir;
	 /*if(to < from)*/dir=to-from;
	 //else dir=from-to;

	 var dif=360-from+to;
	 var dif2=360-to+from;
	 if(dif < 180)dir=+dif;
	 else
	 if(dif2 < 180)dir=-dif2;
	 
	 return dir;
}

// documented in /docs/sdk/script/fn
global func SetBit(int old_val, int bit_nr, bool bit)
{
	if (GetBit(old_val, bit_nr) != (bit != 0))
		return ToggleBit(old_val, bit_nr);
	return old_val;
}

// documented in /docs/sdk/script/fn
global func GetBit(int value, int bit_nr)
{
	return (value & (1 << bit_nr)) != 0;
}

// documented in /docs/sdk/script/fn
global func ToggleBit(int old_val, int bit_nr)
{
	return old_val ^ (1 << bit_nr);
}

// Returns -1 for DIR_Left and +1 for DIR_Right or 0 if no object context is present
global func GetCalcDir()
{
	if (!this) return 0;
	return GetDir() * 2 - 1;
}

// Moves param 'a' towards param 'b' by 'max' amount per frame.
global func MoveTowards(int a, int b, int max)
{
	if(b == nil) return false;
	if(max == nil) max = 1;
	if(a < b) return BoundBy(a + max,a,b);
	if(a > b) return BoundBy(a - max,b,a);
}

global func FindHeight(int x)
{
	var y = 0;
	while (!GBackSemiSolid(x, y) && y < LandscapeHeight())
		y += 10;
	while (GBackSemiSolid(x, y) && y)
		y--;
	return y;
}

/*
	Returns the normal vector of the (solid) landscape at a point relative to an object.
	Can f.e. be used to bounce projectiles.
*/
global func GetSurfaceVector(int x, int y)
{
	var normal = [0, 0];
	
	var fac = 1;
	for(var fac = 1; fac <= 4; fac *= 2)
	{
		if(GBackSolid(x + fac, y)) --normal[0];
		if(GBackSolid(x - fac, y)) ++normal[0];
			
		if(GBackSolid(x, y + fac)) --normal[1];
		if(GBackSolid(x, y - fac)) ++normal[1];
	}
	
	return normal;
}

// Mathematical modulo operation for calculations in ℤ/nℤ.
//
// Examples:
// (12 % 10) == Mod(12, 10) == 2
// (-1 % 10) == -1
// Mod(-1, 10) == 9
global func Mod(int dividend, int divisor)
{
	var a = dividend, b = divisor;
	return (a % b + b) % b;
}

// Returns whether the line from (x1, y1) to (x2, y2) overlaps with the line from (x3, y3) to (x4, y4).
// Whenever the two lines share a starting or ending point they are not considered to be overlapping.
global func IsLineOverlap(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
{
	// Same starting or ending point is not overlapping.
	if ((x1 == x3 && y1 == y3) || (x1 == x4 && y1 == y4) || (x2 == x3 && y2 == y3) || (x2 == x4 && y2 == y4))
		return false;	
	
	// Check if line from (x1, y1) to (x2, y2) crosses the line from (x3, y3) to (x4, y4).
	var d1x = x2 - x1, d1y = y2 - y1, d2x = x4 - x3, d2y = y4 - y3, d3x = x3 - x1, d3y = y3 - y1;
	var a = d1y * d3x - d1x * d3y;
	var b = d2y * d3x - d2x * d3y;
	var c = d2y * d1x - d2x * d1y;
	if (!c) 
		return !a && Inside(x3, x1, x2) && Inside(y3, y1, y2); // lines are parallel
	return a * c >= 0 && !(a * a / (c * c + 1)) && b * c >= 0 && !(b * b/(c * c + 1));
}