Really low graphics patch thanks to Stephan Beyer
[crack-attack.git] / src / DrawBlocks.cxx
blobd169e08dd97f58465679cef6262df45990768543
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/glut.h>
30 #ifndef _WIN32
31 #else
32 # include <glext.h>
33 #endif
35 using namespace std;
37 #include "Game.h"
38 #include "Displayer.h"
39 #include "Creep.h"
40 #include "Block.h"
41 #include "BlockManager.h"
42 #include "LightManager.h"
43 #include "Swapper.h"
44 #include "X.h"
46 const GLfloat Displayer::block_colors[BF_NUMBER][3]
47 = { { 0.73f, 0.0f, 0.73f }, // purple
48 { 0.2f, 0.2f, 0.8f }, // blue
49 { 0.0f, 0.6f, 0.05f }, // green
50 { 0.85f, 0.85f, 0.0f }, // yellow
51 { 1.0f, 0.4f, 0.0f }, // orange
52 { 1.0f, 0.0f, 0.0f }, // wild
53 { 0.4f, 0.4f, 0.4f }, // gray
54 { 0.05f, 0.05f, 0.05f }, // black
55 { 0.95f, 0.95f, 0.95f }, // white
56 { 2.0f * 0.73f, 2.0f * 0.0f, 2.0f * 0.73f }, // special purple
57 { 2.0f * 0.2f, 2.0f * 0.2f, 2.0f * 0.8f }, // special blue
58 { 2.0f * 0.0f, 2.0f * 0.6f, 2.0f * 0.05f }, // special green
59 { 2.0f * 0.85f, 2.0f * 0.85f, 2.0f * 0.0f }, // special yellow
60 { 2.0f * 1.0f, 2.0f * 0.4f, 2.0f * 0.0f } }; // special orange
62 const GLfloat creep_colors[BF_NUMBER][3]
63 = { { 0.25f * 0.73f, 0.25f * 0.0f, 0.25f * 0.73f }, // purple
64 { 0.25f * 0.2f, 0.25f * 0.2f, 0.25f * 0.8f }, // blue
65 { 0.25f * 0.0f, 0.25f * 0.6f, 0.25f * 0.05f }, // green
66 { 0.25f * 0.85f, 0.25f * 0.85f, 0.25f * 0.0f }, // yellow
67 { 0.25f * 1.0f, 0.25f * 0.4f, 0.25f * 0.0f }, // orange
68 { 0.25f * 1.0f, 0.25f * 0.0f, 0.25f * 0.0f }, // wild
69 { 0.25f * 0.4f, 0.25f * 0.4f, 0.25f * 0.4f }, // gray
70 { 0.25f * 0.05f, 0.25f * 0.05f, 0.25f * 0.05f }, // black
71 { 0.25f * 0.95f, 0.25f * 0.95f, 0.25f * 0.95f }, // white
72 { 0.5f * 0.73f, 0.5f * 0.0f, 0.5f * 0.73f }, // special purple
73 { 0.5f * 0.2f, 0.5f * 0.2f, 0.5f * 0.8f }, // special blue
74 { 0.5f * 0.0f, 0.5f * 0.6f, 0.5f * 0.05f }, // special green
75 { 0.5f * 0.85f, 0.5f * 0.85f, 0.5f * 0.0f }, // special yellow
76 { 0.5f * 1.0f, 0.5f * 0.4f, 0.5f * 0.0f } }; // special orange
78 void Displayer::setWildBlockColor ( Block &block, float flash )
80 Wild &wild = X::wild(block);
82 if (wild.alarm < GC_WILD_POLYMORPH_PERIOD) {
83 GLfloat fade = wild.alarm * (1.0f / (GLfloat) GC_WILD_POLYMORPH_PERIOD);
85 int next_color;
86 if (wild.flavor != BF_NORMAL_1)
87 next_color = wild.flavor - 1;
88 else
89 next_color = BF_WILD;
91 GLfloat color[3];
92 if (block.y != 0) {
93 color[0] = fade * block_colors[wild.flavor][0]
94 + (1.0f - fade) * block_colors[next_color][0];
95 color[1] = fade * block_colors[wild.flavor][1]
96 + (1.0f - fade) * block_colors[next_color][1];
97 color[2] = fade * block_colors[wild.flavor][2]
98 + (1.0f - fade) * block_colors[next_color][2];
99 } else {
100 color[0] = fade * creep_colors[wild.flavor][0]
101 + (1.0f - fade) * creep_colors[next_color][0];
102 color[1] = fade * creep_colors[wild.flavor][1]
103 + (1.0f - fade) * creep_colors[next_color][1];
104 color[2] = fade * creep_colors[wild.flavor][2]
105 + (1.0f - fade) * creep_colors[next_color][2];
108 glColor3f(color[0] + flash * (DC_FLASH_COLOR_RED - color[0]),
109 color[1] + flash * (DC_FLASH_COLOR_GREEN - color[1]),
110 color[2] + flash * (DC_FLASH_COLOR_BLUE - color[2]));
112 } else
113 if (block.y != 0)
114 glColor3f(block_colors[wild.flavor][0]
115 + flash * (DC_FLASH_COLOR_RED - block_colors[wild.flavor][0]),
116 block_colors[wild.flavor][1]
117 + flash * (DC_FLASH_COLOR_GREEN - block_colors[wild.flavor][1]),
118 block_colors[wild.flavor][2]
119 + flash * (DC_FLASH_COLOR_BLUE - block_colors[wild.flavor][2]));
120 else
121 glColor3f(creep_colors[wild.flavor][0]
122 + flash * (DC_FLASH_COLOR_RED - creep_colors[wild.flavor][0]),
123 creep_colors[wild.flavor][1]
124 + flash * (DC_FLASH_COLOR_GREEN - creep_colors[wild.flavor][1]),
125 creep_colors[wild.flavor][2]
126 + flash * (DC_FLASH_COLOR_BLUE - creep_colors[wild.flavor][2]));
129 void Displayer::drawBlocks ( )
131 glColorMaterial(GL_FRONT, GL_DIFFUSE);
133 // GL_FRONT_AND_BACK because the garbage uses these material properties
134 // also and I don't think it hurts with cull face on.
135 GLfloat color[4];
136 color[0] = 0.0f; color[1] = 0.0f; color[2] = 0.0f; color[3] = 1.0f;
137 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
138 color[0] = 0.5f; color[1] = 0.5f; color[2] = 0.5f; color[3] = 1.0f;
139 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
140 color[0] = 0.0f; color[1] = 0.0f; color[2] = 0.0f; color[3] = 1.0f;
141 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
142 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 10.0f);
144 // First we'll draw the non-special color blocks.
146 int c = BlockManager::block_count;
147 for (int n = 0; c; n++)
148 if (BlockManager::storeMap[n]) {
149 Block &block = BlockManager::blockStore[n];
150 c--;
152 if (BlockManager::isSpecialColorFlavor(block.flavor)) continue;
154 if (block.y > GC_SAFE_HEIGHT) continue;
156 drawBlock(block, false);
159 if (!X::specialColorActive()) return;
161 // Then we set things up for special color blocks and draw them.
163 if (opengl_version_1_2)
164 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
166 glEnable(GL_TEXTURE_1D);
168 glBindTexture(GL_TEXTURE_1D, special_block_lightmap);
170 c = X::special_color_count;
171 for (int n = 0; c; n++)
172 if (BlockManager::storeMap[n]) {
173 Block &block = BlockManager::blockStore[n];
175 if (!BlockManager::isSpecialColorFlavor(block.flavor)) continue;
176 c--;
178 glMatrixMode(GL_TEXTURE);
179 glPushMatrix();
181 glTranslatef(((Game::time_step + block.X) & (DC_GLEAM_PERIOD - 1))
182 * (1.0f / (GLfloat) DC_GLEAM_PERIOD), 0.0f, 0.0f);
183 glRotatef(DC_GLEAM_ROTATION_RATE * (Game::time_step + block.X),
184 DC_GLEAM_ROTATION_AXIS_X, DC_GLEAM_ROTATION_AXIS_Y,
185 DC_GLEAM_ROTATION_AXIS_Z);
186 glMatrixMode(GL_MODELVIEW);
188 drawBlock(block, true);
190 glMatrixMode(GL_TEXTURE);
191 glPopMatrix();
192 glMatrixMode(GL_MODELVIEW);
195 glDisable(GL_TEXTURE_1D);
197 if (opengl_version_1_2)
198 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR);
201 inline void Displayer::drawBlock ( Block &block, bool special )
203 GLfloat x, y;
204 GLfloat d_x;
206 glPushMatrix();
208 y = block.y * DC_GRID_ELEMENT_LENGTH
209 + block.f_y * (DC_GRID_ELEMENT_LENGTH / (GLfloat) GC_STEPS_PER_GRID)
210 + play_offset_y;
212 // normal
213 if (block.state & (BS_STATIC | BS_FALLING)) {
214 x = block.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
216 if (block.flavor != BF_WILD)
217 if (block.y != 0)
218 glColor3fv(block_colors[block.flavor]);
219 else
220 glColor3fv(creep_colors[block.flavor]);
221 else
222 setWildBlockColor(block, 0.0f);
224 LightManager::setupBlockLights(x, y);
225 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
227 if (!special)
228 glCallList(block_list);
229 else
230 glCallList(special_block_list);
232 // awaking and popping
233 } else if (block.state & BS_AWAKING) {
234 x = block.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
236 LightManager::setupBlockLights(x, y);
237 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
239 // if we haven't popped yet
240 if (block.pop_alarm != 0) {
242 // if we're just about to pop
243 if (block.pop_alarm - Game::time_step < DC_POP_ROTATE_TIME) {
244 GLfloat p = (block.pop_alarm - Game::time_step)
245 * (1.0f / (GLfloat) DC_POP_ROTATE_TIME);
247 // each block rotates a different direction
248 if (block.pop_direction & BR_DIRECTION_1) {
249 glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
250 glRotatef(45.0f * p, 0.0f, 1.0f, 0.0f);
251 } else if (block.pop_direction & BR_DIRECTION_2) {
252 glRotatef(90.0f - 45.0f * p, 1.0f, 0.0f, 0.0f);
253 glRotatef(45.0f * p, 0.0f, 1.0f, 0.0f);
254 } else if (block.pop_direction & BR_DIRECTION_3) {
255 glRotatef(90.0f - 45.0f * p, 1.0f, 0.0f, 0.0f);
256 glRotatef(-45.0f * p, 0.0f, 1.0f, 0.0f);
257 } else {
258 glRotatef(45.0f * p, 1.0f, 0.0f, 0.0f);
259 glRotatef(-45.0f * p, 0.0f, 1.0f, 0.0f);
262 GLfloat scale = 1.0f - 0.5f * p;
263 glScalef(scale, scale, scale);
265 glColor3f( (1.0f - p) * block_colors[block.flavor][0]
266 + p * garbage_colors[block.pop_color][0],
267 (1.0f - p) * block_colors[block.flavor][1]
268 + p * garbage_colors[block.pop_color][1],
269 (1.0f - p) * block_colors[block.flavor][2]
270 + p * garbage_colors[block.pop_color][2]);
272 glEnable(rescale_method);
273 glCallList(block_list);
274 glDisable(rescale_method);
276 // if we're not popping
277 } else {
279 glColor3fv(garbage_colors[block.pop_color]);
281 // the small block is pre-rotated
282 glCallList(small_block_list);
285 // if we've already popped
286 } else {
287 glColor3fv(block_colors[block.flavor]);
289 glCallList(block_list);
292 // swapping
293 } else if (block.state & BS_SWAPPING) {
294 x = block.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
296 if (block.state & BS_SWAP_DIRECTION_MASK) {
297 LightManager::setupBlockLights(x + Swapper::swap_factor
298 * DC_GRID_ELEMENT_LENGTH, y);
299 d_x = -DC_GRID_ELEMENT_LENGTH / 2.0f;
301 } else {
302 LightManager::setupBlockLights(x - Swapper::swap_factor
303 * DC_GRID_ELEMENT_LENGTH, y);
304 d_x = DC_GRID_ELEMENT_LENGTH / 2.0f;
307 if (block.flavor != BF_WILD)
308 glColor3fv(block_colors[block.flavor]);
309 else
310 setWildBlockColor(block, 0.0f);
312 glTranslatef(x - d_x, y, DC_PLAY_OFFSET_Z);
313 glRotatef(-180.0f * (1.0f - Swapper::swap_factor), 0.0f, 1.0f, 0.0f);
314 glTranslatef(d_x, 0.0f, 0.0f);
316 if (!special)
317 glCallList(block_list);
318 else
319 glCallList(special_block_list);
321 // dying
322 } else if (block.state & BS_DYING) {
323 x = block.x * DC_GRID_ELEMENT_LENGTH + DC_PLAY_OFFSET_X;
325 // when dying, first we flash
326 if (GC_DYING_DELAY - block.alarm < DC_DYING_FLASH_TIME) {
328 GLfloat flash = ((GLfloat) GC_DYING_DELAY - block.alarm)
329 * (4.0f / (GLfloat) DC_DYING_FLASH_TIME);
330 if (flash > 2.0f) flash = 4.0f - flash;
331 if (flash > 1.0f) flash = 2.0f - flash;
333 if (block.flavor != BF_WILD)
334 glColor3f(block_colors[block.flavor][0]
335 + flash * (DC_FLASH_COLOR_RED - block_colors[block.flavor][0]),
336 block_colors[block.flavor][1]
337 + flash * (DC_FLASH_COLOR_GREEN - block_colors[block.flavor][1]),
338 block_colors[block.flavor][2]
339 + flash * (DC_FLASH_COLOR_BLUE - block_colors[block.flavor][2]));
340 else
341 setWildBlockColor(block, flash);
343 LightManager::setupBlockLights(x, y);
344 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
345 if (!special)
346 glCallList(block_list);
347 else
348 glCallList(special_block_list);
350 // then we shrink and spin
351 } else {
352 if (block.flavor != BF_WILD)
353 glColor3fv(block_colors[block.flavor]);
354 else
355 setWildBlockColor(block, 0.0f);
357 LightManager::setupBlockLights(x, y);
358 glTranslatef(x, y, DC_PLAY_OFFSET_Z);
359 glRotatef((GC_DYING_DELAY - DC_DYING_FLASH_TIME - block.alarm)
360 * (GC_DYING_DELAY - DC_DYING_FLASH_TIME - block.alarm)
361 * DC_DYING_ROTATE_SPEED, block.axis_x, block.axis_y, 0.0f);
363 GLfloat scale = block.alarm * DC_DYING_SHRINK_SPEED
364 + DC_DYING_SHRINK_MIN_SIZE;
365 glScalef(scale, scale, scale);
367 glEnable(rescale_method);
368 if (!special)
369 glCallList(block_list);
370 else
371 glCallList(special_block_list);
372 glDisable(rescale_method);
376 glPopMatrix();