1 /*
2  * SparkleManager.cxx
3  * Daniel Nelson - 9/4/0
4  *
5  * Copyright (C) 2000  Daniel Nelson
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * Daniel Nelson - aluminumangel.org
22  * 174 W. 18th Ave.
23  * Columbus, OH  43210
24  *
25  * Handles all the pretty sparkles!
26  */
27 
28 using namespace std;
29 
30 #include "Game.h"
31 #include "Displayer.h"
32 #include "MetaState.h"
33 #include "Random.h"
34 #include "SparkleManager.h"
35 
36 int SparkleManager::spark_count;
37 Spark SparkleManager::sparks[DC_MAX_SPARK_NUMBER];
38 
39 int SparkleManager::mote_count;
40 Mote SparkleManager::motes[DC_MAX_MOTE_NUMBER];
41 
42 const int SparkleManager::mote_colors[DC_NUMBER_MOTE_LEVELS]
43  = { 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11,
44      0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3 };
45 
46 const int SparkleManager::mote_light_colors[DC_NUMBER_MOTE_LEVELS]
47  = { 0, 0, 0, 0, 1, 0, 2, 3, 4, 5, 6,
48      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
49 
50 const int SparkleManager::mote_types[DC_NUMBER_MOTE_LEVELS]
51  = { MT_FOUR_POINTED_STAR, MT_FIVE_POINTED_STAR,
52      MT_SIX_POINTED_STAR, MT_SPECIAL_STAR, MT_SPECIAL_STAR, MT_SPECIAL_STAR,
53      MT_SPECIAL_STAR, MT_SPECIAL_STAR, MT_SPECIAL_STAR, MT_SPECIAL_STAR,
54      MT_SPECIAL_STAR, MT_MULTIPLIER_ONE_STAR, MT_MULTIPLIER_TWO_STAR,
55      MT_MULTIPLIER_THREE_STAR, MT_MULTIPLIER_THREE_STAR,
56      MT_MULTIPLIER_THREE_STAR, MT_MULTIPLIER_THREE_STAR,
57      MT_MULTIPLIER_THREE_STAR, MT_MULTIPLIER_THREE_STAR,
58      MT_MULTIPLIER_THREE_STAR, MT_MULTIPLIER_THREE_STAR,
59      MT_MULTIPLIER_THREE_STAR };
60 
61 const GLfloat SparkleManager::mote_sizes[DC_NUMBER_MOTE_LEVELS]
62  = { 2.0f, 2.8f, 2.8f, 3.4f, 3.4f, 3.4f, 3.4f, 3.4f, 3.4f, 3.4f, 3.4f,
63      4.0f, 2.6f, 3.5f, 3.7f, 3.9f, 4.1f, 4.3f, 4.5f, 4.7f, 4.9f, 5.1f };
64 
65 const float SparkleManager::mote_inverse_masses[DC_NUMBER_MOTE_LEVELS]
66  = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
67      1.0f, 1.0f, 1.0f, 1.0f, 1.0f / 1.4f, 1.0f / 1.8f, 1.0f / 2.2f,
68      1.0f / 2.6f, 1.0f / 3.0f, 1.0f / 3.4f, 1.0f / 3.8f, 1.0f / 4.2f };
69 
initialize()70 void SparkleManager::initialize (   )
71 {
72   spark_count = 0;
73   for (int n = DC_MAX_SPARK_NUMBER; n--; )
74     sparks[n].active = false;
75 
76   mote_count = 0;
77   for (int n = DC_MAX_MOTE_NUMBER; n--; )
78     motes[n].active = false;
79 }
80 
createBlockDeathSpark(int x,int y,int color,int n)81 void SparkleManager::createBlockDeathSpark ( int x, int y, int color, int n )
82 {
83   while (n--) {
84     if (spark_count == DC_MAX_SPARK_NUMBER) return;
85 
86     int n;
87     for (n = 0; sparks[n].active; n++);
88     Spark &spark = sparks[n];
89 
90     spark_count++;
91     spark.active = true;
92     spark.x = x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
93     spark.y = y * DC_GRID_ELEMENT_LENGTH + Displayer::play_offset_y;
94 
95     float v = DC_MIN_SPARK_VELOCITY + (Random::number() + Random::number())
96      * (0.5f * (DC_MAX_SPARK_VELOCITY - DC_MIN_SPARK_VELOCITY));
97     Random::deathSparkAngle(spark.v_x, spark.v_y);
98     spark.v_x *= v;
99     spark.v_y *= v;
100 
101     spark.a = Random::number(360);
102     spark.v_a = DC_MIN_SPARK_ANGULAR_VELOCITY
103      + (Random::number() + Random::number())
104      * (0.5f * (DC_MAX_SPARK_ANGULAR_VELOCITY - DC_MIN_SPARK_ANGULAR_VELOCITY));
105     if (Random::chanceIn2(2))
106       spark.v_a = -spark.v_a;
107 
108     switch (Random::number2(4)) {
109     case 0:
110       spark.size = DC_MIN_SPARK_SIZE;
111       break;
112     case 1:
113       spark.size = DC_MIN_SPARK_SIZE + Random::number()
114        * (1.0f - DC_MIN_SPARK_SIZE);
115       break;
116     default:
117       spark.size = 1.0f;
118       break;
119     }
120 
121     spark.color = color;
122 
123     if (Random::chanceIn(DC_CHANCE_LONG_SPARK_LIFE_TIME))
124       spark.life_time = Random::number(10 * DC_SPREAD_SPARK_LIFE_TIME)
125        + Random::number(10 * DC_SPREAD_SPARK_LIFE_TIME)
126        + 10 * (DC_MEDIUM_SPARK_LIFE_TIME - DC_SPREAD_SPARK_LIFE_TIME);
127     else
128       spark.life_time = Random::number(DC_SPREAD_SPARK_LIFE_TIME)
129        + Random::number(DC_SPREAD_SPARK_LIFE_TIME)
130        + (DC_MEDIUM_SPARK_LIFE_TIME - DC_SPREAD_SPARK_LIFE_TIME);
131   }
132 }
133 
createCelebrationSpark(int source,int color)134 void SparkleManager::createCelebrationSpark ( int source, int color )
135 {
136   if (spark_count == DC_MAX_SPARK_NUMBER) return;
137 
138   int n;
139   for (n = 0; sparks[n].active; n++);
140   Spark &spark = sparks[n];
141 
142   spark_count++;
143   spark.active = true;
144 
145   float v;
146   if (source != 4) {
147     Random::celebrationSpark1Angle(spark.v_x, spark.v_y);
148     v = DC_MIN_CSPARK_VELOCITY + DC_SPREAD_CSPARK_VELOCITY * Random::number();
149   } else {
150     Random::celebrationSpark2Angle(spark.v_x, spark.v_y);
151     v = (2.0f * DC_MIN_CSPARK_VELOCITY)
152      + (2.0f * DC_SPREAD_CSPARK_VELOCITY) * Random::number();
153   }
154   spark.v_x *= v;
155   spark.v_y *= v;
156 
157   switch (source) {
158   case 0:
159     if (MetaState::mode & CM_SOLO) {
160       spark.x = DC_PLAY_OFFSET_X + DC_SOURCE_1_SOLO_OFFSET_X;
161       spark.y = DC_PLAY_OFFSET_Y + DC_SOURCE_1_SOLO_OFFSET_Y;
162     } else {
163       spark.x = DC_PLAY_OFFSET_X + DC_SOURCE_1_OFFSET_X;
164       spark.y = DC_PLAY_OFFSET_Y + DC_SOURCE_1_OFFSET_Y;
165     }
166     break;
167   case 1:
168     spark.x = DC_PLAY_OFFSET_X + DC_SOURCE_2_OFFSET_X;
169     spark.y = DC_PLAY_OFFSET_Y + DC_SOURCE_2_OFFSET_Y;
170     break;
171   case 2:
172     if (MetaState::mode & CM_SOLO) {
173       spark.x = DC_PLAY_OFFSET_X + DC_SOURCE_3_SOLO_OFFSET_X;
174       spark.y = DC_PLAY_OFFSET_Y + DC_SOURCE_3_SOLO_OFFSET_Y;
175     } else {
176       spark.x = DC_PLAY_OFFSET_X + DC_SOURCE_3_OFFSET_X;
177       spark.y = DC_PLAY_OFFSET_Y + DC_SOURCE_3_OFFSET_Y;
178     }
179     spark.v_x = -spark.v_x;
180     break;
181   case 3:
182     spark.x = DC_PLAY_OFFSET_X + DC_SOURCE_4_OFFSET_X;
183     spark.y = DC_PLAY_OFFSET_Y + DC_SOURCE_4_OFFSET_Y;
184     spark.v_x = -spark.v_x;
185     break;
186   case 4:
187     if (MetaState::mode & CM_SOLO) {
188       spark.x = DC_PLAY_OFFSET_X + DC_SOURCE_5_SOLO_OFFSET_X;
189       spark.y = DC_PLAY_OFFSET_Y + DC_SOURCE_5_SOLO_OFFSET_Y;
190     } else {
191       spark.x = DC_PLAY_OFFSET_X + DC_SOURCE_5_OFFSET_X;
192       spark.y = DC_PLAY_OFFSET_Y + DC_SOURCE_5_OFFSET_Y;
193     }
194     break;
195   }
196 
197   spark.a = Random::number(360);
198   spark.v_a = DC_MIN_SPARK_ANGULAR_VELOCITY
199    + (Random::number() + Random::number())
200    * (0.5f * (DC_MAX_SPARK_ANGULAR_VELOCITY - DC_MIN_SPARK_ANGULAR_VELOCITY));
201   if (Random::chanceIn2(2))
202     spark.v_a = -spark.v_a;
203 
204   if (Random::chanceIn(3))
205     spark.size = DC_MIN_SPARK_SIZE
206      + Random::number() * (1.0f - DC_MIN_SPARK_SIZE);
207   else
208     spark.size = DC_MIN_SPARK_SIZE;
209 
210   spark.color = color;
211 
212   if (Random::chanceIn(DC_CHANCE_LONG_SPARK_LIFE_TIME))
213     spark.life_time = Random::number(10 * DC_SPREAD_SPARK_LIFE_TIME)
214      + Random::number(10 * DC_SPREAD_SPARK_LIFE_TIME)
215      + 10 * (DC_MEDIUM_SPARK_LIFE_TIME - DC_SPREAD_SPARK_LIFE_TIME);
216   else
217     spark.life_time = Random::number(DC_SPREAD_SPARK_LIFE_TIME)
218      + Random::number(DC_SPREAD_SPARK_LIFE_TIME)
219      + (DC_MEDIUM_SPARK_LIFE_TIME - DC_SPREAD_SPARK_LIFE_TIME);
220 }
221 
createRewardMote(int x,int y,int level,int sibling_number)222 void SparkleManager::createRewardMote ( int x, int y, int level,
223  int sibling_number )
224 {
225   if (mote_count == DC_MAX_MOTE_NUMBER) return;
226 
227   int n;
228   for (n = 0; motes[n].active; n++);
229   Mote &mote = motes[n];
230 
231   if (n == 0)
232     glEnable(GL_LIGHT1);
233 
234   mote_count++;
235   mote.active = true;
236 
237   if (level >= DC_NUMBER_MOTE_LEVELS)
238     level = DC_NUMBER_MOTE_LEVELS - 1;
239   mote.color = mote_colors[level];
240   mote.light_color = mote_light_colors[level];
241   mote.type = mote_types[level];
242   mote.size = mote_sizes[level];
243   mote.inverse_mass = mote_inverse_masses[level];
244 
245   mote.x = x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X
246    - (DC_GRID_ELEMENT_LENGTH / 2.0f)
247    + (float) Random::number(20) * ((float) DC_GRID_ELEMENT_LENGTH / 20.0f);
248   mote.y = y * DC_GRID_ELEMENT_LENGTH + Displayer::play_offset_y
249    - (DC_GRID_ELEMENT_LENGTH / 2.0f)
250    + (float) Random::number(20) * ((float) DC_GRID_ELEMENT_LENGTH / 20.0f);
251 
252   // slow down big ones
253   float v = (DC_MEDIUM_MOTE_VELOCITY - DC_SPREAD_MOTE_VELOCITY
254    + Random::number() * (2.0f * DC_SPREAD_MOTE_VELOCITY)) * mote.inverse_mass;
255   if (x < GC_PLAY_WIDTH / 2)
256    mote.v_x = -0.707107 * v;
257   else
258    mote.v_x = 0.707107 * v;
259   mote.v_y = -0.707107 * v;
260 
261   mote.a = mote.initial_a = Random::number(360);
262   mote.v_a = (DC_MEDIUM_MOTE_ANGULAR_VELOCITY
263    - DC_SPREAD_MOTE_ANGULAR_VELOCITY + Random::number()
264    * (2.0f * DC_SPREAD_MOTE_ANGULAR_VELOCITY)) * mote.inverse_mass;
265   if (Random::chanceIn2(2))
266     mote.v_a = -mote.v_a;
267 
268   mote.life_time = 0;
269   mote.sibling_delay = sibling_number * DC_MULTI_MOTE_FIRE_DELAY;
270 
271   mote.associated_light = -1;
272 }
273 
timeStep()274 void SparkleManager::timeStep (   )
275 {
276   int c = spark_count;
277   for (int n = 0; c; n++)
278     if (sparks[n].active) {
279       Spark &spark = sparks[n];
280       c--;
281 
282       if (--spark.life_time == 0) {
283         spark.active = false;
284         spark_count--;
285 
286       } else {
287         spark.x += spark.v_x;
288         spark.y += spark.v_y;
289 
290         spark.a += spark.v_a;
291 
292         spark.v_y -= DC_SPARK_GRAVITY + DC_SPARK_DRAG * spark.v_y;
293         spark.v_x -= DC_SPARK_DRAG * spark.v_x;
294       }
295     }
296 
297   c = mote_count;
298   for (int n = 0; c; n++)
299     if (motes[n].active) {
300       Mote &mote = motes[n];
301       c--;
302 
303       if (mote.life_time >= 0)
304         if (++mote.life_time - mote.sibling_delay < GC_DYING_DELAY) {
305           mote.a += mote.v_a;
306           if (mote.life_time <= GC_DYING_DELAY)
307             mote.brightness = DC_MAX_MOTE_LIGHT_BRIGHTNESS
308              * mote.life_time * (1.0f / (float) GC_DYING_DELAY);
309           continue;
310         } else
311           mote.life_time = -1;
312       else if (mote.color > 0 && mote.color < DC_FIRST_SPECIAL_MOTE_COLOR)
313         mote.life_time--;
314 
315       mote.y += mote.v_y;
316       if (mote.y > DC_PLAY_HEIGHT + mote.size * (DC_SPARKLE_LENGTH / 2.0f)) {
317         mote.active = false;
318         mote_count--;
319         continue;
320       }
321 
322       mote.x += mote.v_x;
323 
324       mote.a += mote.v_a;
325 
326       mote.v_y += mote.inverse_mass * DC_MOTE_UPWARD_FORCE
327        - DC_MOTE_DRAG * mote.v_y;
328       mote.v_x -= mote.inverse_mass * DC_MOTE_CENTER_SPRING * mote.x
329        + DC_MOTE_DRAG * mote.v_x;
330 
331       mote.v_a -= mote.inverse_mass
332        * DC_MOTE_TWIST_SPRING * (mote.a - mote.initial_a);
333     }
334 }
335