1 /*
2  * WinRecord.cxx
3  * Daniel Nelson - 10/22/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 the win/loss record.
26  */
27 
28 #include <GL/glut.h>
29 
30 #include "glext.h"
31 
32 using namespace std;
33 
34 #include "Game.h"
35 #include "WinRecord.h"
36 #include "Displayer.h"
37 #include "Random.h"
38 
39 int WinRecord::current_game;
40 bool WinRecord::won;
41 bool WinRecord::concession;
42 int WinRecord::games_won;
43 int WinRecord::games_lost;
44 int WinRecord::record[GC_GAMES_PER_MATCH];
45 
46 Star WinRecord::stars[GC_GAMES_PER_MATCH];
47 int WinRecord::dynamic_star;
48 int WinRecord::displaced_star;
49 GLfloat WinRecord::win_star_x;
50 GLfloat WinRecord::win_star_y;
51 GLfloat WinRecord::win_star_v_x;
52 GLfloat WinRecord::win_star_v_y;
53 GLfloat WinRecord::old_star_a;
54 GLfloat WinRecord::old_star_size;
55 bool WinRecord::draw_old_star;
56 
initialize()57 void WinRecord::initialize (   )
58 {
59   for (int n = GC_GAMES_PER_MATCH; n--; )
60     record[n] = GR_NOT_PLAYED;
61   current_game = -1;
62   concession = false;
63   games_won = 0;
64   games_lost = 0;
65 
66   dynamic_star = -1;
67   displaced_star = -1;
68   for (int n = GC_GAMES_PER_MATCH; n--; )
69     stars[n].a = 0.0f;
70 }
71 
gameStart()72 void WinRecord::gameStart (   )
73 {
74   if (MetaState::mode & CM_SOLO)
75     current_game = 1;
76   else
77     current_game++;
78 
79   record[current_game] = GR_BEING_PLAYED;
80 }
81 
gameWon()82 void WinRecord::gameWon (   )
83 {
84   won = true;
85   games_won++;
86   record[current_game] = GR_WON;
87 
88   if (MetaState::mode & CM_REALLY_LOW_GRAPHICS) {
89     // The star will disappear and pop into existance in the play area.  After a
90     // few moments, it will fly to it's original location.
91 
92     // record star's old location; for a time, two stars will be drawn, as one
93     // pops in and the other pops away
94     draw_old_star = true;
95     old_star_a = stars[current_game].a;
96     old_star_size = 5.0f;
97 
98     // displace the star into the play area and set it's starting parameters
99     displaced_star = current_game;
100     stars[current_game].a = DC_STAR_WIN_MIN_ANGULAR_DEVIATION
101      + DC_STAR_WIN_SPREAD_ANGULAR_DEVIATION * Random::number();
102     if (Random::chanceIn2(2))
103       stars[current_game].a = -stars[current_game].a;
104     stars[current_game].v_a = 0.0f;
105     stars[current_game].size = 0.0f;
106     stars[current_game].v_size = 0.0f;
107     win_star_x = (-DC_LEFT_EXTERNAL_CENTER + DC_STAR_DISPLACEMENT
108      * (GC_GAMES_PER_MATCH - 1) / 2.0f + DC_STAR_WIN_OFFSET_X)
109      - DC_STAR_DISPLACEMENT * current_game;
110 
111     if (MetaState::mode & CM_SOLO)
112       win_star_y = -DC_STAR_OFFSET_Y + DC_STAR_WIN_SOLO_OFFSET_Y;
113     else
114       win_star_y = -DC_STAR_OFFSET_Y + DC_STAR_WIN_OFFSET_Y;
115 
116     // set the kick velocity; choice of two aesthetically pleasing preset values
117     // or, for variety, a random 270 degree arc
118     switch (Random::number(3)) {
119     case 0:
120       win_star_v_x = DC_STAR_WIN_PRESET_1_VELOCITY_X;
121       win_star_v_y = DC_STAR_WIN_PRESET_1_VELOCITY_Y;
122       break;
123     case 1:
124       win_star_v_x = DC_STAR_WIN_PRESET_2_VELOCITY_X;
125       win_star_v_y = DC_STAR_WIN_PRESET_2_VELOCITY_Y;
126       break;
127     default:
128       // too infrequent to warrent a random direction table
129       float v = DC_STAR_WIN_MIN_VELOCITY
130        + DC_STAR_WIN_SPREAD_VELOCITY * Random::number();
131       float angle = Random::number() * (3.0f * PI / 2.0f) - (PI / 2.0f);
132       win_star_v_x = v * cos(angle);
133       win_star_v_y = v * sin(angle);
134       break;
135     }
136   }
137 }
138 
gameLoss()139 void WinRecord::gameLoss (   )
140 {
141   won = false;
142   games_lost++;
143   record[current_game] = GR_LOST;
144 }
145 
timeStep()146 void WinRecord::timeStep (   )
147 {
148   for (int n = GC_GAMES_PER_MATCH; n--; ) {
149     Star &star = stars[n];
150 
151     switch (record[n]) {
152 
153     // game being played
154     case GR_BEING_PLAYED:
155       if (Game::time_step >= GC_START_PAUSE_DELAY)
156         star.a += DC_STAR_PLAY_ANGULAR_VELOCITY;
157       else
158         star.a += Game::time_step
159          * (DC_STAR_PLAY_ANGULAR_VELOCITY / (float) GC_START_PAUSE_DELAY);
160       break;
161 
162     // game has been lost
163     case GR_LOST:
164       if (current_game == n && Game::time_step < DC_CELEBRATION_TIME)
165         star.a += (DC_CELEBRATION_TIME - Game::time_step)
166          * (DC_STAR_PLAY_ANGULAR_VELOCITY / (float) DC_CELEBRATION_TIME);
167       break;
168 
169     // game has been won
170     case GR_WON:
171       // wait for win message to hit before dynamics
172       if (current_game != n || Game::time_step > DC_WIN_FADE_TIME) {
173 
174         star.size += star.v_size;
175         if (star.size < 0.0f) star.size = 0.0f;
176         star.v_size += -DC_STAR_WIN_SIZE_DRAG * star.v_size
177          - DC_STAR_WIN_SIZE_SPRING * (star.size - DC_STAR_SIZE_EQUILIBRIUM);
178 
179         if (fabs(star.v_size) < DC_STAR_WIN_SIZE_EPSILON
180          && Random::chanceIn(DC_STAR_WIN_SIZE_PULSE_CHANCE_IN))
181           star.v_size += DC_STAR_WIN_SIZE_PULSE_VELOCITY * Random::number();
182 
183         star.v_a += -DC_STAR_WIN_ANGULAR_SPRING * star.a;
184 
185         star.a += star.v_a;
186 
187         // begin motion
188         if (Game::time_step == DC_WIN_FADE_TIME + DC_STAR_WIN_KICK_DELAY
189          && current_game == n) {
190           displaced_star = -1;
191           dynamic_star = n;
192         }
193 
194         // if we're dynamic;
195         if (dynamic_star == n) {
196           win_star_x += win_star_v_x;
197           win_star_y += win_star_v_y;
198 
199           win_star_v_x += -DC_STAR_WIN_SPRING * win_star_x
200            - DC_STAR_WIN_DRAG * win_star_v_x;
201           win_star_v_y += -DC_STAR_WIN_SPRING * win_star_y
202            - DC_STAR_WIN_DRAG * win_star_v_y;
203 
204           // if we're there, stop being dynamic
205           if (fabs(win_star_v_x) < DC_STAR_WIN_VELOCITY_EPSILON
206            && fabs(win_star_v_y) < DC_STAR_WIN_VELOCITY_EPSILON
207            && fabs(win_star_x) < DC_STAR_WIN_EPSILON
208            && fabs(win_star_y) < DC_STAR_WIN_EPSILON)
209             dynamic_star = -1;
210         }
211       }
212 
213       // shrink the old star as the new one apears
214       if (draw_old_star && current_game == n) {
215         if (star.size < DC_STAR_SIZE_EQUILIBRIUM) {
216           old_star_size = DC_STAR_SIZE_EQUILIBRIUM - star.size;
217           old_star_a += DC_STAR_PLAY_ANGULAR_VELOCITY;
218         } else
219           draw_old_star = false;
220       }
221 
222       break;
223     }
224   }
225 }
226