g_spawn_command_line_sync used for spawning the game now.
[crack-attack.git] / src / DrawBlocks.cxx
blobce193a803eb0daa02c1bc25e63ad226d21bff1c0
1 /*
2 * DrawBlocks.cxx
3 * Daniel Nelson - 8/31/0
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.
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.
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.
21 * Daniel Nelson - aluminumangel.org
22 * 174 W. 18th Ave.
23 * Columbus, OH 43210
25 * Handle's the displaying of the blocks.
28 #include <GL/gl.h>
29 #include <GL/glut.h>
31 // FIXME: may actually need GL/glext.h
32 #include "glext.h"
34 using namespace std;
36 #include "Game.h"
37 #include "Displayer.h"
38 #include "Creep.h"
39 #include "Block.h"
40 #include "BlockManager.h"
41 #include "LightManager.h"
42 #include "Swapper.h"
43 #include "X.h"
45 const GLfloat Displayer::block_colors[BF_NUMBER][3]
46 = { { 0.73f, 0.0f, 0.73f }, // purple
47 { 0.2f, 0.2f, 0.8f }, // blue
48 { 0.0f, 0.6f, 0.05f }, // green
49 { 0.85f, 0.85f, 0.0f }, // yellow
50 { 1.0f, 0.4f, 0.0f }, // orange
51 { 1.0f, 0.0f, 0.0f }, // wild
52 { 0.4f, 0.4f, 0.4f }, // gray
53 { 0.05f, 0.05f, 0.05f }, // black
54 { 0.95f, 0.95f, 0.95f }, // white
55 { 2.0f * 0.73f, 2.0f * 0.0f, 2.0f * 0.73f }, // special purple
56 { 2.0f * 0.2f, 2.0f * 0.2f, 2.0f * 0.8f }, // special blue
57 { 2.0f * 0.0f, 2.0f * 0.6f, 2.0f * 0.05f }, // special green
58 { 2.0f * 0.85f, 2.0f * 0.85f, 2.0f * 0.0f }, // special yellow
59 { 2.0f * 1.0f, 2.0f * 0.4f, 2.0f * 0.0f } }; // special orange
61 const GLfloat creep_colors[BF_NUMBER][3]
62 = { { 0.25f * 0.73f, 0.25f * 0.0f, 0.25f * 0.73f }, // purple
63 { 0.25f * 0.2f, 0.25f * 0.2f, 0.25f * 0.8f }, // blue
64 { 0.25f * 0.0f, 0.25f * 0.6f, 0.25f * 0.05f }, // green
65 { 0.25f * 0.85f, 0.25f * 0.85f, 0.25f * 0.0f }, // yellow
66 { 0.25f * 1.0f, 0.25f * 0.4f, 0.25f * 0.0f }, // orange
67 { 0.25f * 1.0f, 0.25f * 0.0f, 0.25f * 0.0f }, // wild
68 { 0.25f * 0.4f, 0.25f * 0.4f, 0.25f * 0.4f }, // gray
69 { 0.25f * 0.05f, 0.25f * 0.05f, 0.25f * 0.05f }, // black
70 { 0.25f * 0.95f, 0.25f * 0.95f, 0.25f * 0.95f }, // white
71 { 0.5f * 0.73f, 0.5f * 0.0f, 0.5f * 0.73f }, // special purple
72 { 0.5f * 0.2f, 0.5f * 0.2f, 0.5f * 0.8f }, // special blue
73 { 0.5f * 0.0f, 0.5f * 0.6f, 0.5f * 0.05f }, // special green
74 { 0.5f * 0.85f, 0.5f * 0.85f, 0.5f * 0.0f }, // special yellow
75 { 0.5f * 1.0f, 0.5f * 0.4f, 0.5f * 0.0f } }; // special orange
77 void Displayer::setWildBlockColor ( Block &block, float flash )
79 Wild &wild = X::wild(block);
81 if (wild.alarm < GC_WILD_POLYMORPH_PERIOD) {
82 GLfloat fade = wild.alarm * (1.0f / (GLfloat) GC_WILD_POLYMORPH_PERIOD);
84 int next_color;
85 if (wild.flavor != BF_NORMAL_1)
86 next_color = wild.flavor - 1;
87 else
88 next_color = BF_WILD;
90 GLfloat color[3];
91 if (block.y != 0) {
92 color[0] = fade * block_colors[wild.flavor][0]
93 + (1.0f - fade) * block_colors[next_color][0];
94 color[1] = fade * block_colors[wild.flavor][1]
95 + (1.0f - fade) * block_colors[next_color][1];
96 color[2] = fade * block_colors[wild.flavor][2]
97 + (1.0f - fade) * block_colors[next_color][2];
98 } else {
99 color[0] = fade * creep_colors[wild.flavor][0]
100 + (1.0f - fade) * creep_colors[next_color][0];
101 color[1] = fade * creep_colors[wild.flavor][1]
102 + (1.0f - fade) * creep_colors[next_color][1];
103 color[2] = fade * creep_colors[wild.flavor][2]
104 + (1.0f - fade) * creep_colors[next_color][2];
107 glColor3f(color[0] + flash * (DC_FLASH_COLOR_RED - color[0]),
108 color[1] + flash * (DC_FLASH_COLOR_GREEN - color[1]),
109 color[2] + flash * (DC_FLASH_COLOR_BLUE - color[2]));
111 } else
112 if (block.y != 0)
113 glColor3f(block_colors[wild.flavor][0]
114 + flash * (DC_FLASH_COLOR_RED - block_colors[wild.flavor][0]),
115 block_colors[wild.flavor][1]
116 + flash * (DC_FLASH_COLOR_GREEN - block_colors[wild.flavor][1]),
117 block_colors[wild.flavor][2]
118 + flash * (DC_FLASH_COLOR_BLUE - block_colors[wild.flavor][2]));
119 else
120 glColor3f(creep_colors[wild.flavor][0]
121 + flash * (DC_FLASH_COLOR_RED - creep_colors[wild.flavor][0]),
122 creep_colors[wild.flavor][1]
123 + flash * (DC_FLASH_COLOR_GREEN - creep_colors[wild.flavor][1]),
124 creep_colors[wild.flavor][2]
125 + flash * (DC_FLASH_COLOR_BLUE - creep_colors[wild.flavor][2]));
128 void Displayer::drawBlocks ( )
130 glColorMaterial(GL_FRONT, GL_DIFFUSE);
132 // GL_FRONT_AND_BACK because the garbage uses these material properties
133 // also and I don't think it hurts with cull face on.
134 GLfloat color[4];
135 color[0] = 0.0f; color[1] = 0.0f; color[2] = 0.0f; color[3] = 1.0f;
136 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
137 color[0] = 0.5f; color[1] = 0.5f; color[2] = 0.5f; color[3] = 1.0f;
138 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
139 color[0] = 0.0f; color[1] = 0.0f; color[2] = 0.0f; color[3] = 1.0f;
140 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
141 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 10.0f);
143 // First we'll draw the non-special color blocks.
145 int c = BlockManager::block_count;
146 for (int n = 0; c; n++)
147 if (BlockManager::storeMap[n]) {
148 Block &block = BlockManager::blockStore[n];
149 c--;
151 if (BlockManager::isSpecialColorFlavor(block.flavor)) continue;
153 if (block.y > GC_SAFE_HEIGHT) continue;
155 drawBlock(block, false);
158 if (!X::specialColorActive()) return;
160 // Then we set things up for special color blocks and draw them.
162 if (opengl_version_1_2)
163 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
165 glEnable(GL_TEXTURE_1D);
167 glBindTexture(GL_TEXTURE_1D, special_block_lightmap);
169 c = X::special_color_count;
170 for (int n = 0; c; n++)
171 if (BlockManager::storeMap[n]) {
172 Block &block = BlockManager::blockStore[n];
174 if (!BlockManager::isSpecialColorFlavor(block.flavor)) continue;
175 c--;
177 glMatrixMode(GL_TEXTURE);
178 glPushMatrix();
180 glTranslatef(((Game::time_step + block.X) & (DC_GLEAM_PERIOD - 1))
181 * (1.0f / (GLfloat) DC_GLEAM_PERIOD), 0.0f, 0.0f);
182 glRotatef(DC_GLEAM_ROTATION_RATE * (Game::time_step + block.X),
183 DC_GLEAM_ROTATION_AXIS_X, DC_GLEAM_ROTATION_AXIS_Y,
184 DC_GLEAM_ROTATION_AXIS_Z);
185 glMatrixMode(GL_MODELVIEW);
187 drawBlock(block, true);
189 glMatrixMode(GL_TEXTURE);
190 glPopMatrix();
191 glMatrixMode(GL_MODELVIEW);
194 glDisable(GL_TEXTURE_1D);
196 if (opengl_version_1_2)
197 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
200 inline void Displayer::drawBlock ( Block &block, bool special )
202 GLfloat x, y;
203 GLfloat d_x;
205 glPushMatrix();
207 y = block.y * DC_GRID_ELEMENT_LENGTH
208 + block.f_y * (DC_GRID_ELEMENT_LENGTH / (GLfloat) GC_STEPS_PER_GRID)
209 + play_offset_y;
211 // normal
212 if (block.state & (BS_STATIC | BS_FALLING)) {
213 x = block.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
215 if (block.flavor != BF_WILD)
216 if (block.y != 0)
217 glColor3fv(block_colors[block.flavor]);
218 else
219 glColor3fv(creep_colors[block.flavor]);
220 else
221 setWildBlockColor(block, 0.0f);
223 LightManager::setupBlockLights(x, y);
224 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
226 if (!special)
227 glCallList(block_list);
228 else
229 glCallList(special_block_list);
231 // awaking and popping
232 } else if (block.state & BS_AWAKING) {
233 x = block.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
235 LightManager::setupBlockLights(x, y);
236 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
238 // if we haven't popped yet
239 if (block.pop_alarm != 0) {
241 // if we're just about to pop
242 if (block.pop_alarm - Game::time_step < DC_POP_ROTATE_TIME) {
243 GLfloat p = (block.pop_alarm - Game::time_step)
244 * (1.0f / (GLfloat) DC_POP_ROTATE_TIME);
246 // each block rotates a different direction
247 if (block.pop_direction & BR_DIRECTION_1) {
248 glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
249 glRotatef(45.0f * p, 0.0f, 1.0f, 0.0f);
250 } else if (block.pop_direction & BR_DIRECTION_2) {
251 glRotatef(90.0f - 45.0f * p, 1.0f, 0.0f, 0.0f);
252 glRotatef(45.0f * p, 0.0f, 1.0f, 0.0f);
253 } else if (block.pop_direction & BR_DIRECTION_3) {
254 glRotatef(90.0f - 45.0f * p, 1.0f, 0.0f, 0.0f);
255 glRotatef(-45.0f * p, 0.0f, 1.0f, 0.0f);
256 } else {
257 glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
258 glRotatef(-45.0f * p, 0.0f, 1.0f, 0.0f);
261 GLfloat scale = 1.0f - 0.5f * p;
262 glScalef(scale, scale, scale);
264 glColor3f( (1.0f - p) * block_colors[block.flavor][0]
265 + p * garbage_colors[block.pop_color][0],
266 (1.0f - p) * block_colors[block.flavor][1]
267 + p * garbage_colors[block.pop_color][1],
268 (1.0f - p) * block_colors[block.flavor][2]
269 + p * garbage_colors[block.pop_color][2]);
271 glEnable(rescale_method);
272 glCallList(block_list);
273 glDisable(rescale_method);
275 // if we're not popping
276 } else {
278 glColor3fv(garbage_colors[block.pop_color]);
280 // the small block is pre-rotated
281 glCallList(small_block_list);
284 // if we've already popped
285 } else {
286 glColor3fv(block_colors[block.flavor]);
288 glCallList(block_list);
291 // swapping
292 } else if (block.state & BS_SWAPPING) {
293 x = block.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
295 if (block.state & BS_SWAP_DIRECTION_MASK) {
296 LightManager::setupBlockLights(x + Swapper::swap_factor
297 * DC_GRID_ELEMENT_LENGTH, y);
298 d_x = -DC_GRID_ELEMENT_LENGTH / 2.0f;
300 } else {
301 LightManager::setupBlockLights(x - Swapper::swap_factor
302 * DC_GRID_ELEMENT_LENGTH, y);
303 d_x = DC_GRID_ELEMENT_LENGTH / 2.0f;
306 if (block.flavor != BF_WILD)
307 glColor3fv(block_colors[block.flavor]);
308 else
309 setWildBlockColor(block, 0.0f);
311 glTranslatef(x - d_x, y, DC_PLAY_OFFSET_Z);
312 glRotatef(-180.0f * (1.0f - Swapper::swap_factor), 0.0f, 1.0f, 0.0f);
313 glTranslatef(d_x, 0.0f, 0.0f);
315 if (!special)
316 glCallList(block_list);
317 else
318 glCallList(special_block_list);
320 // dying
321 } else if (block.state & BS_DYING) {
322 x = block.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
324 // when dying, first we flash
325 if (GC_DYING_DELAY - block.alarm < DC_DYING_FLASH_TIME) {
327 GLfloat flash = ((GLfloat) GC_DYING_DELAY - block.alarm)
328 * (4.0f / (GLfloat) DC_DYING_FLASH_TIME);
329 if (flash > 2.0f) flash = 4.0f - flash;
330 if (flash > 1.0f) flash = 2.0f - flash;
332 if (block.flavor != BF_WILD)
333 glColor3f(block_colors[block.flavor][0]
334 + flash * (DC_FLASH_COLOR_RED - block_colors[block.flavor][0]),
335 block_colors[block.flavor][1]
336 + flash * (DC_FLASH_COLOR_GREEN - block_colors[block.flavor][1]),
337 block_colors[block.flavor][2]
338 + flash * (DC_FLASH_COLOR_BLUE - block_colors[block.flavor][2]));
339 else
340 setWildBlockColor(block, flash);
342 LightManager::setupBlockLights(x, y);
343 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
344 if (!special)
345 glCallList(block_list);
346 else
347 glCallList(special_block_list);
349 // then we shrink and spin
350 } else {
351 if (block.flavor != BF_WILD)
352 glColor3fv(block_colors[block.flavor]);
353 else
354 setWildBlockColor(block, 0.0f);
356 LightManager::setupBlockLights(x, y);
357 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
358 glRotatef((GC_DYING_DELAY - DC_DYING_FLASH_TIME - block.alarm)
359 * (GC_DYING_DELAY - DC_DYING_FLASH_TIME - block.alarm)
360 * DC_DYING_ROTATE_SPEED, block.axis_x, block.axis_y, 0.0f);
362 GLfloat scale = block.alarm * DC_DYING_SHRINK_SPEED
363 + DC_DYING_SHRINK_MIN_SIZE;
364 glScalef(scale, scale, scale);
366 glEnable(rescale_method);
367 if (!special)
368 glCallList(block_list);
369 else
370 glCallList(special_block_list);
371 glDisable(rescale_method);
375 glPopMatrix();