1 /*
2 * This file is part of 'Garden of coloured lights'.
3 *
4 * 'Garden of coloured lights' is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * 'Garden of coloured lights' is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 'Garden of coloured lights'. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19
20 This file contains some maths and utility functions. The only ones used at present are:
21
22 xpart/ypart - call them with angle x and distance d; they'll give you the x component and y component
23 of a line in the angle x and the distance d
24
25 angle_to_radians - I use a 1024-degree circle in a format called 'angle'. It lets me use lookup tables
26 radians_to_angle without interpolation for simple trig, and minimises slow floating-point operations.
27 angle_to_radians takes 'angle' values and turns them into radians; radians_to_angle etc.
28
29 grand(n) - random number from 1 to n
30
31
32 */
33
34
35 #include "config.h"
36
37 #include "allegro.h"
38
39 #include <math.h>
40
41 int turn_towards_angle (int angle, int tangle, int turning);
42 int delta_turn_towards_angle (int angle, int tangle, int turning);
43
44 float lcos (int angle);
45 float lsin (int angle);
46 float angle_to_radians (int angle);
47
48 // I have no idea why, but the first few elements of cos_table always get corrupted
49 // unless I put a big fat decoy array just above. A similar thing happens to the
50 // palette arrays; allegro seems to have a problem with global arrays like these.
51 float decoy_table[ANGLE_1]; // not used
52 float cos_table[ANGLE_1];
53 float sin_table[ANGLE_1];
54
55 int xpart (int angle, int length);
56
init_trig(void)57 void init_trig (void)
58 {
59 int i;
60
61 for (i = 0; i < ANGLE_1; i++)
62 {
63 cos_table[i] = cos (angle_to_radians (i)); // * ANGLE_1;
64 sin_table[i] = sin (angle_to_radians (i)); // * ANGLE_1;
65 }
66
67
68 }
69
xpart(int angle,int length)70 int xpart (int angle, int length)
71 {
72 return (cos_table[angle & 1023] * length);
73 }
74
ypart(int angle,int length)75 int ypart (int angle, int length)
76 {
77 return (sin_table[angle & 1023] * length);
78 }
79
lcos(int angle)80 float lcos (int angle)
81 {
82 return cos_table[angle & 1023];
83
84 }
85
lsin(int angle)86 float lsin (int angle)
87 {
88 return sin_table[angle & 1023];
89
90 }
91
92
angle_to_radians(int angle)93 float angle_to_radians (int angle)
94 {
95 return ((float) angle * PI * 2) / ANGLE_1;
96 }
97
radians_to_angle(float angle)98 int radians_to_angle (float angle)
99 {
100 if (angle < 0)
101 angle += PI * 2;
102 return (int) ((angle * ANGLE_1) / (PI * 2));
103 }
104
angle_to_fixed(int angle)105 fixed angle_to_fixed (int angle)
106 {
107 return itofix (angle / ANGLE_TO_FIXED);
108 }
109
grand(int number)110 int grand (int number)
111 {
112 if (number == 0)
113 return 0;
114 return ((rand () + (rand () << 16)) & 0x7fffffff) % number;
115 }
116
117 // returns the new angle
turn_towards_angle(int angle,int tangle,int turning)118 int turn_towards_angle (int angle, int tangle, int turning)
119 {
120
121 if ((angle < tangle && tangle > angle + ANGLE_2)
122 || (angle > tangle && tangle > angle - ANGLE_2))
123 {
124 angle -= turning;
125 if (angle < 0)
126 angle += ANGLE_1;
127 }
128 else
129 {
130 angle += turning;
131 if (angle > ANGLE_1)
132 angle -= ANGLE_1;
133 }
134
135 return angle;
136
137 }
138
139
turn_towards_xy(int x1,int y1,int x2,int y2,int angle,int turning)140 int turn_towards_xy (int x1, int y1, int x2, int y2, int angle, int turning)
141 {
142
143 int tangle = radians_to_angle (atan2 ((y2 - y1), (x2 - x1))) & 1023;
144 /* if (tangle < 0)
145 tangle += ANGLE_1;
146 if (tangle > ANGLE_1)
147 tangle -= ANGLE_1;*/
148
149 return turn_towards_angle (angle, tangle, turning);
150
151 }
152
153 // delta version just returns the change needed
delta_turn_towards_angle(int angle,int tangle,int turning)154 int delta_turn_towards_angle (int angle, int tangle, int turning)
155 {
156
157 // if ((angle < tangle && tangle > angle + ANGLE_2)
158 if ((angle < tangle && tangle > angle + ANGLE_2)
159 || (angle > tangle && tangle > angle - ANGLE_2))
160 {
161 return turning * -1;
162 }
163
164 return turning;
165
166 }
167
odd_even(int v)168 int odd_even (int v)
169 {
170 if ((v | 1) == 1)
171 return 1;
172
173 return -1;
174
175 }
176
delta_turn_towards_xy(int x1,int y1,int x2,int y2,int angle,int turning)177 int delta_turn_towards_xy (int x1, int y1, int x2, int y2, int angle,
178 int turning)
179 {
180
181 int tangle = radians_to_angle (atan2 ((y2 - y1), (x2 - x1)));
182 if (tangle < 0)
183 tangle += ANGLE_1;
184 if (tangle > ANGLE_1)
185 tangle -= ANGLE_1;
186
187 return delta_turn_towards_angle (angle, tangle, turning);
188
189 }
190
191
192
193 // speed must be at least 4, and a factor of 1024
pulsate(int speed,int amount,int county)194 int pulsate (int speed, int amount, int county)
195 {
196 return xpart ((county * speed) & 1023, amount);
197 }
198
error_message_out(const char * errm)199 void error_message_out (const char *errm)
200 {
201 set_gfx_mode (GFX_TEXT, 0, 0, 0, 0);
202 allegro_message ("%s", errm);
203 exit (1);
204 }
205
206
angle_difference(int a1,int a2)207 int angle_difference (int a1, int a2)
208 {
209 int d1, d2;
210
211 d1 = (a1 - a2 + ANGLE_1) % ANGLE_1;
212 d2 = (a2 - a1 + ANGLE_1) % ANGLE_1;
213
214 if (d1 < d2)
215 return abs (d1);
216
217 return abs (d2);
218 }
219
220
pos_or_neg(int a)221 int pos_or_neg (int a)
222 {
223 if (grand (2) == 0)
224 return a;
225
226 return a * -1;
227
228 }
229