1 /*
2  * DrawExternalCandy.cxx
3  * Daniel Nelson - 10/13/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  * Draws everything dumb outside of the play area.
26  */
27 
28 #include <GL/glut.h>
29 
30 #include "glext.h"
31 
32 using namespace std;
33 
34 #include "Game.h"
35 #include "Displayer.h"
36 #include "MetaState.h"
37 #include "Clock.h"
38 #include "Score.h"
39 #include "LoseBar.h"
40 
drawDigit(GLfloat alpha)41 inline void Displayer::drawDigit ( GLfloat alpha )
42 {
43   glColor4f(0.3f, 0.3f, 1.0f, alpha);
44 
45   glBegin(GL_TRIANGLE_STRIP);
46 
47     glTexCoord2f(0.0f, 1.0f);
48     glVertex3f(-DC_CLOCK_DIGIT_LENGTH, -DC_CLOCK_DIGIT_LENGTH, 0.0f);
49     glColor4f(0.5f, 0.5f, 1.0f, alpha);
50     glTexCoord2f(1.0f, 1.0f);
51     glVertex3f(DC_CLOCK_DIGIT_LENGTH, -DC_CLOCK_DIGIT_LENGTH, 0.0f);
52     glColor4f(0.5f, 0.5f, 1.0f, alpha);
53     glTexCoord2f(0.0f, 0.0f);
54     glVertex3f(-DC_CLOCK_DIGIT_LENGTH, DC_CLOCK_DIGIT_LENGTH, 0.0f);
55     glColor4f(1.0f, 1.0f, 1.0f, alpha);
56     glTexCoord2f(1.0f, 0.0f);
57     glVertex3f(DC_CLOCK_DIGIT_LENGTH, DC_CLOCK_DIGIT_LENGTH, 0.0f);
58 
59   glEnd();
60 }
61 
drawLeftBar(GLfloat b,GLfloat t,GLfloat color[3])62 inline void Displayer::drawLeftBar ( GLfloat b, GLfloat t, GLfloat color[3] )
63 {
64   if (t < DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f) return;
65 
66   glBegin(GL_TRIANGLE_STRIP);
67 
68     glColor3fv(color);
69     glTexCoord2f(0.0f, 0.0f);
70     glVertex3f(-DC_LOSEBAR_LENGTH / 2.0f, DC_LOSEBAR_HEIGHT / 2.0f, 0.0f);
71     glTexCoord2f(t - (DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f), 0.0f);
72     glVertex3f(b - (DC_LOSEBAR_FADE_LENGTH / 2.0f), DC_LOSEBAR_HEIGHT / 2,
73      0.0f);
74     glTexCoord2f(0.0f, 1.0f);
75     glVertex3f(-DC_LOSEBAR_LENGTH / 2.0f, -DC_LOSEBAR_HEIGHT / 2.0f, 0.0f);
76     glTexCoord2f(t - (DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f), 1.0f);
77     glVertex3f(b - (DC_LOSEBAR_FADE_LENGTH / 2.0f), -DC_LOSEBAR_HEIGHT / 2.0f,
78      0.0f);
79 
80   glEnd();
81 }
82 
drawRightBar(GLfloat b,GLfloat t,GLfloat color[3])83 inline void Displayer::drawRightBar ( GLfloat b, GLfloat t, GLfloat color[3] )
84 {
85   if (t > 1.0f - DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f) return;
86 
87   glBegin(GL_TRIANGLE_STRIP);
88 
89     glColor3fv(color);
90     glTexCoord2f(t + (DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f), 0.0f);
91     glVertex3f(b + (DC_LOSEBAR_FADE_LENGTH / 2.0f), DC_LOSEBAR_HEIGHT / 2.0f,
92      0.0f);
93     glTexCoord2f(1.0f, 0.0f);
94     glVertex3f(DC_LOSEBAR_LENGTH / 2.0f, DC_LOSEBAR_HEIGHT / 2.0f, 0.0f);
95     glTexCoord2f(t + (DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f), 1.0f);
96     glVertex3f(b + (DC_LOSEBAR_FADE_LENGTH / 2.0f), -DC_LOSEBAR_HEIGHT / 2.0f,
97      0.0f);
98     glTexCoord2f(1.0f, 1.0f);
99     glVertex3f(DC_LOSEBAR_LENGTH / 2.0f, -DC_LOSEBAR_HEIGHT / 2.0f, 0.0f);
100 
101   glEnd();
102 }
103 
drawCenterBar(GLfloat b,GLfloat t,GLfloat color1[3],GLfloat color2[3])104 inline void Displayer::drawCenterBar ( GLfloat b, GLfloat t, GLfloat color1[3],
105  GLfloat color2[3] )
106 {
107   glBegin(GL_TRIANGLE_STRIP);
108 
109     glColor3fv(color1);
110     glTexCoord2f(t - (DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f), 0.0f);
111     glVertex3f(b - (DC_LOSEBAR_FADE_LENGTH / 2.0f), DC_LOSEBAR_HEIGHT / 2.0f,
112      0.0f);
113     glColor3fv(color2);
114     glTexCoord2f(t + (DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f), 0.0f);
115     glVertex3f(b + (DC_LOSEBAR_FADE_LENGTH / 2.0f), DC_LOSEBAR_HEIGHT / 2.0f,
116      0.0f);
117     glColor3fv(color1);
118     glTexCoord2f(t - (DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f), 1.0f);
119     glVertex3f(b - (DC_LOSEBAR_FADE_LENGTH / 2.0f), -DC_LOSEBAR_HEIGHT / 2.0f,
120      0.0f);
121     glColor3fv(color2);
122     glTexCoord2f(t + (DC_LOSEBAR_FADE_TEX_LENGTH / 2.0f), 1.0f);
123     glVertex3f(b + (DC_LOSEBAR_FADE_LENGTH / 2.0f), -DC_LOSEBAR_HEIGHT / 2.0f,
124      0.0f);
125 
126   glEnd();
127 }
128 
drawFullBar(GLfloat color[3])129 inline void Displayer::drawFullBar ( GLfloat color[3] )
130 {
131   glBegin(GL_TRIANGLE_STRIP);
132 
133     glColor3fv(color);
134     glTexCoord2f(0.0f, 0.0f);
135     glVertex3f(-DC_LOSEBAR_LENGTH / 2.0f, DC_LOSEBAR_HEIGHT / 2.0f, 0.0f);
136     glTexCoord2f(1.0f, 0.0f);
137     glVertex3f(DC_LOSEBAR_LENGTH / 2.0f, DC_LOSEBAR_HEIGHT / 2.0f, 0.0f);
138     glTexCoord2f(0.0f, 1.0f);
139     glVertex3f(-DC_LOSEBAR_LENGTH / 2.0f, -DC_LOSEBAR_HEIGHT / 2.0f, 0.0f);
140     glTexCoord2f(1.0f, 1.0f);
141     glVertex3f(DC_LOSEBAR_LENGTH / 2.0f, -DC_LOSEBAR_HEIGHT / 2.0f, 0.0f);
142 
143   glEnd();
144 }
145 
drawExternalCandy()146 void Displayer::drawExternalCandy (   )
147 {
148   int texture_bound;
149 
150   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
151 
152   GLfloat b = (DC_LOSEBAR_LENGTH + DC_LOSEBAR_FADE_LENGTH)
153    * (LoseBar::bar - 0.5f);
154   GLfloat t = LoseBar::bar * (1.0f + DC_LOSEBAR_FADE_TEX_LENGTH)
155    - 0.5f * DC_LOSEBAR_FADE_TEX_LENGTH;
156 
157   glBindTexture(GL_TEXTURE_2D, losebar_texture);
158 
159   glPushMatrix();
160 
161     glTranslatef(DC_LEFT_EXTERNAL_CENTER, DC_LOSEBAR_OFFSET_Y,
162      DC_EXTERNAL_OFFSET_Z);
163 
164     GLfloat color1[3], color2[3];
165 
166     float fade;
167     switch (LoseBar::state) {
168     case LB_INACTIVE:
169       color1[0] = DC_LOSEBAR_INACTIVE_RED;
170       color1[1] = DC_LOSEBAR_INACTIVE_GREEN;
171       color1[2] = DC_LOSEBAR_INACTIVE_BLUE;
172 
173       drawFullBar(color1);
174       break;
175 
176     case LB_LOW_ALERT:
177       color1[0] = DC_LOSEBAR_LOW_ALERT_RED;
178       color1[1] = DC_LOSEBAR_LOW_ALERT_GREEN;
179       color1[2] = DC_LOSEBAR_LOW_ALERT_BLUE;
180 
181       color2[0] = DC_LOSEBAR_INACTIVE_RED;
182       color2[1] = DC_LOSEBAR_INACTIVE_GREEN;
183       color2[2] = DC_LOSEBAR_INACTIVE_BLUE;
184 
185       drawLeftBar(b, t, color1);
186       drawCenterBar(b, t, color1, color2);
187       drawRightBar(b, t, color2);
188       break;
189 
190     case LB_HIGH_ALERT:
191       color1[0] = DC_LOSEBAR_HIGH_ALERT_RED;
192       color1[1] = DC_LOSEBAR_HIGH_ALERT_GREEN;
193       color1[2] = DC_LOSEBAR_HIGH_ALERT_BLUE;
194 
195       color2[0] = DC_LOSEBAR_LOW_ALERT_RED;
196       color2[1] = DC_LOSEBAR_LOW_ALERT_GREEN;
197       color2[2] = DC_LOSEBAR_LOW_ALERT_BLUE;
198 
199       drawLeftBar(b, t, color1);
200       drawCenterBar(b, t, color1, color2);
201       drawRightBar(b, t, color2);
202       break;
203 
204     case LB_FADE_LOW_TO_INACTIVE:
205       fade = LoseBar::fade_timer * (1.0f / (GLfloat) DC_LOSEBAR_FADE_TIME);
206 
207       color1[0] = DC_LOSEBAR_INACTIVE_RED
208        + fade * (DC_LOSEBAR_LOW_ALERT_RED - DC_LOSEBAR_INACTIVE_RED);
209       color1[1] = DC_LOSEBAR_INACTIVE_GREEN
210        + fade * (DC_LOSEBAR_LOW_ALERT_GREEN - DC_LOSEBAR_INACTIVE_GREEN);
211       color1[2] = DC_LOSEBAR_INACTIVE_BLUE
212        + fade * (DC_LOSEBAR_LOW_ALERT_BLUE - DC_LOSEBAR_INACTIVE_BLUE);
213 
214       color2[0] = DC_LOSEBAR_INACTIVE_RED;
215       color2[1] = DC_LOSEBAR_INACTIVE_GREEN;
216       color2[2] = DC_LOSEBAR_INACTIVE_BLUE;
217 
218       drawLeftBar(b, t, color1);
219       drawCenterBar(b, t, color1, color2);
220       drawRightBar(b, t, color2);
221       break;
222 
223     case LB_FADE_HIGH_TO_INACTIVE:
224       fade = LoseBar::fade_timer * (1.0f / (GLfloat) DC_LOSEBAR_FADE_TIME);
225 
226       color1[0] = DC_LOSEBAR_INACTIVE_RED
227        + fade * (DC_LOSEBAR_HIGH_ALERT_RED - DC_LOSEBAR_INACTIVE_RED);
228       color1[1] = DC_LOSEBAR_INACTIVE_GREEN
229        + fade * (DC_LOSEBAR_HIGH_ALERT_GREEN - DC_LOSEBAR_INACTIVE_GREEN);
230       color1[2] = DC_LOSEBAR_INACTIVE_BLUE
231        + fade * (DC_LOSEBAR_HIGH_ALERT_BLUE - DC_LOSEBAR_INACTIVE_BLUE);
232 
233       color2[0] = DC_LOSEBAR_INACTIVE_RED
234        + fade * (DC_LOSEBAR_LOW_ALERT_RED - DC_LOSEBAR_INACTIVE_RED);
235       color2[1] = DC_LOSEBAR_INACTIVE_GREEN
236        + fade * (DC_LOSEBAR_LOW_ALERT_GREEN - DC_LOSEBAR_INACTIVE_GREEN);
237       color2[2] = DC_LOSEBAR_INACTIVE_BLUE
238        + fade * (DC_LOSEBAR_LOW_ALERT_BLUE - DC_LOSEBAR_INACTIVE_BLUE);
239 
240       drawLeftBar(b, t, color1);
241       drawCenterBar(b, t, color1, color2);
242       drawRightBar(b, t, color2);
243       break;
244 
245     case LB_FADE_RESET_HIGH:
246       fade = LoseBar::fade_timer * (1.0f / (GLfloat) DC_LOSEBAR_FADE_TIME);
247 
248       color1[0] = DC_LOSEBAR_LOW_ALERT_RED
249        + fade * (DC_LOSEBAR_HIGH_ALERT_RED - DC_LOSEBAR_LOW_ALERT_RED);
250       color1[1] = DC_LOSEBAR_LOW_ALERT_GREEN
251        + fade * (DC_LOSEBAR_HIGH_ALERT_GREEN - DC_LOSEBAR_LOW_ALERT_GREEN);
252       color1[2] = DC_LOSEBAR_LOW_ALERT_BLUE
253        + fade * (DC_LOSEBAR_HIGH_ALERT_BLUE - DC_LOSEBAR_LOW_ALERT_BLUE);
254 
255       color2[0] = DC_LOSEBAR_LOW_ALERT_RED;
256       color2[1] = DC_LOSEBAR_LOW_ALERT_GREEN;
257       color2[2] = DC_LOSEBAR_LOW_ALERT_BLUE;
258 
259       drawLeftBar(b, t, color1);
260       drawCenterBar(b, t, color1, color2);
261       drawRightBar(b, t, color2);
262       break;
263     }
264 
265   glPopMatrix();
266 
267   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
268 
269   if ((!(MetaState::mode & CM_REALLY_LOW_GRAPHICS)) || (Game::state & GS_PAUSED) || (Game::state & GS_WON) || (Game::state & GS_LOST)) {
270     // draw clock
271     if ((MetaState::mode & (CM_SERVER | CM_CLIENT)) ||
272         (MetaState::mode & (CM_AI))) {
273 
274       glPushMatrix();
275 
276         glTranslatef(DC_LEFT_EXTERNAL_CENTER - DC_CLOCK_DIGIT_OFFSET / 2,
277          DC_CLOCK_OFFSET_Y, DC_EXTERNAL_OFFSET_Z);
278 
279         glBindTexture(GL_TEXTURE_2D, clock_digit_textures[10]);
280         drawDigit(1.0f);
281 
282         glTranslatef(DC_CLOCK_CENTER_OFFSET / 2.0f
283          + 3.0f * DC_CLOCK_DIGIT_OFFSET / 2.0f, 0.0f, 0.0f);
284 
285         GLfloat alpha = Clock::tick * (1.0f / (GLfloat) GC_STEPS_PER_SECOND);
286 
287         glBindTexture(GL_TEXTURE_2D, clock_digit_textures[Clock::digits[0]]);
288         if (Clock::digits[0] != Clock::previous_digits[0]) {
289           drawDigit(alpha);
290           glBindTexture(GL_TEXTURE_2D,
291            clock_digit_textures[Clock::previous_digits[0]]);
292           drawDigit(1.0f - alpha);
293           texture_bound = Clock::previous_digits[0];
294         } else {
295           drawDigit(1.0f);
296           texture_bound = Clock::digits[0];
297         }
298 
299         glTranslatef(-DC_CLOCK_DIGIT_OFFSET, 0.0f, 0.0f);
300 
301         if (Clock::digits[1] != texture_bound)
302           glBindTexture(GL_TEXTURE_2D, clock_digit_textures[Clock::digits[1]]);
303         if (Clock::digits[1] == Clock::previous_digits[1]) {
304           drawDigit(1.0f);
305           texture_bound = Clock::digits[1];
306         } else {
307           drawDigit(alpha);
308           glBindTexture(GL_TEXTURE_2D,
309            clock_digit_textures[Clock::previous_digits[1]]);
310           drawDigit(1.0f - alpha);
311           texture_bound = Clock::previous_digits[1];
312         }
313 
314         glTranslatef(-DC_CLOCK_DIGIT_OFFSET - DC_CLOCK_CENTER_OFFSET, 0.0f, 0.0f);
315 
316         if (Clock::digits[2] != texture_bound)
317           glBindTexture(GL_TEXTURE_2D, clock_digit_textures[Clock::digits[2]]);
318         if (Clock::digits[2] == Clock::previous_digits[2]) {
319           drawDigit(1.0f);
320           texture_bound = Clock::digits[2];
321         } else {
322           drawDigit(alpha);
323           glBindTexture(GL_TEXTURE_2D,
324            clock_digit_textures[Clock::previous_digits[2]]);
325           drawDigit(1.0f - alpha);
326           texture_bound = Clock::previous_digits[2];
327         }
328 
329         if (Clock::digits[3] || Clock::previous_digits[3]) {
330           glTranslatef(-DC_CLOCK_DIGIT_OFFSET, 0.0f, 0.0f);
331 
332           if (Clock::digits[3] == Clock::previous_digits[3]) {
333             if (texture_bound != Clock::digits[3])
334               glBindTexture(GL_TEXTURE_2D,
335                clock_digit_textures[Clock::digits[3]]);
336             drawDigit(1.0f);
337           } else {
338             if (Clock::digits[3]) {
339               if (texture_bound != Clock::digits[3])
340                 glBindTexture(GL_TEXTURE_2D,
341                  clock_digit_textures[Clock::digits[3]]);
342               drawDigit(alpha);
343               texture_bound = Clock::digits[3];
344             }
345             if (Clock::previous_digits[3]) {
346               if (texture_bound != Clock::previous_digits[3])
347                 glBindTexture(GL_TEXTURE_2D,
348                  clock_digit_textures[Clock::previous_digits[3]]);
349               drawDigit(1.0f - alpha);
350             }
351           }
352         }
353 
354       glPopMatrix();
355 
356     // draw score
357     } else {
358 
359       glPushMatrix();
360 
361         glTranslatef(DC_LEFT_EXTERNAL_CENTER + ((Score::n_digits_displayed - 1)
362          * DC_CLOCK_DIGIT_OFFSET) / 2, DC_CLOCK_OFFSET_Y, DC_EXTERNAL_OFFSET_Z);
363 
364         GLfloat alpha = 1.0f - (GLfloat) Score::fade_timer
365          * Score::inverse_timer_start;
366 
367         glBindTexture(GL_TEXTURE_2D,
368          clock_digit_textures[Score::digits[0]]);
369         texture_bound = Score::digits[0];
370         drawDigit(alpha);
371         if (Score::fade_timer && Score::previous_digits[0]
372          != Score::digits[0]) {
373           glBindTexture(GL_TEXTURE_2D,
374            clock_digit_textures[Score::previous_digits[0]]);
375           texture_bound = Score::previous_digits[0];
376           drawDigit(1.0f - alpha);
377         }
378 
379         for (int n = 1; n < Score::n_digits_displayed; n++) {
380           glTranslatef(-DC_CLOCK_DIGIT_OFFSET, 0.0f, 0.0f);
381           if (texture_bound != Score::digits[n]) {
382             glBindTexture(GL_TEXTURE_2D, clock_digit_textures[Score::digits[n]]);
383             texture_bound = Score::digits[n];
384           }
385           if (Score::fade_timer && Score::previous_digits[n]
386            != Score::digits[n]) {
387             drawDigit(alpha);
388             glBindTexture(GL_TEXTURE_2D,
389              clock_digit_textures[Score::previous_digits[n]]);
390             texture_bound = Score::previous_digits[n];
391             drawDigit(1.0f - alpha);
392           } else
393             drawDigit(1.0f);
394         }
395 
396       glPopMatrix();
397     }
398   } else
399     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
400 
401   glDisable(GL_BLEND);
402 
403   // draw logo
404 
405   glBindTexture(GL_TEXTURE_2D, logo_texture);
406   glCallList(logo_list);
407 
408   // draw names
409 
410   glPushMatrix();
411     glBindTexture(GL_TEXTURE_2D, name_texture);
412     glTranslatef(DC_LEFT_EXTERNAL_CENTER, DC_NAME_OFFSET_Y,
413      DC_EXTERNAL_OFFSET_Z);
414     glScalef(DC_NAME_SCALE, DC_NAME_SCALE, 1.0f);
415     glCallList(message_2x1_list);
416   glPopMatrix();
417 }
418