console: Format tabs semi-intelligently
[attac-man.git] / render_map.c
blob64faf12d2024da6d87c516ef1b2765c5c2ac391b
1 /*
2 Pacman Arena
3 Copyright (C) 2003 Nuno Subtil
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 static const char cvsid[] =
21 "$Id: render_map.c,v 1.4 2003/11/30 17:43:55 nsubtil Exp $";
23 #ifdef _WIN32
24 #include <windows.h>
25 #endif
27 #include <SDL.h>
28 #include <GL/gl.h>
29 #include <GL/glu.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <math.h>
35 #include "object.h"
36 #include "game.h"
37 #include "player.h"
38 #include "render.h"
39 #include "gfx.h"
40 #include "m_math.h"
41 #include "shot.h"
43 #include "map.h"
46 prepara-se para desenhar um tile do mapa
48 void map_setup_wall(struct game *game, int x, int y)
50 struct map *map;
51 #if 0
52 static struct image_rgba32 *rocket_lightmap = NULL;
53 int c;
55 if(rocket_lightmap == NULL)
57 rocket_lightmap = gfx_get("gfx/rocket-highlight.tga");
58 gfx_alpha_from_intensity("gfx/rocket-highlight.tga");
59 gfx_upload_texture("gfx/rocket-highlight.tga");
61 #endif
63 map = game->map;
65 glMatrixMode(GL_MODELVIEW);
66 glLoadIdentity();
68 glTranslatef((GLfloat)x + 0.5, -0.5, (GLfloat)y + 0.5);
70 glEnable(GL_DEPTH_TEST);
71 glDepthMask(GL_TRUE);
72 // glDisable(GL_TEXTURE_2D);
73 // glDisable(GL_BLEND);
75 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
76 glEnable(GL_COLOR_MATERIAL);
78 #if 0
79 /* compute lightmaps */
80 for(c = 0; c < game->n_shots; c++)
82 if(game->shots[c].type == SHOT_TYPE_ROCKET && game->shots[c].state == SHOT_STATE_ACTIVE)
84 int rx, ry;
86 rx = (int)game->shots[c].position[X];
87 ry = (int)game->shots[c].position[Z];
89 switch(MAP(game->map, x, y).wall)
91 case MAP_WALL_HORIZONTAL:
92 if(rx == x && (ry == y - 1 || ry == y + 1))
94 GLfloat params[4];
96 /* XXX - multitexturing! */
97 glActiveTexture(GL_TEXTURE0_ARB);
98 glDisable(GL_TEXTURE_2D);
100 glActiveTexture(GL_TEXTURE1_ARB);
101 glBindTexture(GL_TEXTURE_2D, rocket_lightmap->id);
102 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
104 glEnable(GL_TEXTURE_2D);
106 map_lightmap_param_rocket(params, game, x, y, c);
108 params[X] = 1.0;
109 params[Y] = 1.0;
110 params[Z] = 1.0;
111 params[W] = 1.0;
112 glTexGenfv(GL_S, GL_OBJECT_PLANE, params);
113 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
114 glEnable(GL_TEXTURE_GEN_S);
116 params[X] = 1.0;
117 params[Y] = 1.0;
118 params[Z] = 1.0;
119 params[W] = 1.0;
120 glTexGenfv(GL_T, GL_OBJECT_PLANE, params);
121 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
122 glEnable(GL_TEXTURE_GEN_T);
124 glBlendFunc(GL_ONE, GL_ONE);
125 glEnable(GL_BLEND);
127 return;
130 break;
134 #endif
138 computes lightmap parameters for wall at x, y and rocket n
140 void map_lightmap_param_rocket(GLfloat params[4], struct game *game, int x, int y, int r)
142 struct map *map;
143 struct shot *rocket;
145 map = game->map;
146 rocket = &game->shots[r];
148 /* xxx - do something nice */
149 params[0] = 1.0;
150 params[1] = 1.0;
151 params[2] = 0.0;
152 params[3] = 1.0;
156 desenha uma parede vertical em x, y
158 void map_draw_vertical_wall(struct game *game, int x, int y)
160 static struct object *wall = NULL;
162 map_setup_wall(game, x, y);
164 if(wall == NULL)
166 int nframes;
168 wall = object_read_file("gfx/wall-vertical.3d", &nframes);
171 render_dlist(wall, NULL);
175 desenha uma parede horizontal em (x, y)
177 void map_draw_horizontal_wall(struct game *game, int x, int y)
179 static struct object *wall = NULL;
181 map_setup_wall(game, x, y);
183 if(wall == NULL)
185 int nframes;
187 wall = object_read_file("gfx/wall-horizontal.3d", &nframes);
188 render_compile_dlist(wall);
191 render_dlist(wall, NULL);
195 canto inferior esquerdo
197 void map_draw_ll_wall(struct game *game, int x, int y)
199 static struct object *wall = NULL;
201 map_setup_wall(game, x, y);
203 if(wall == NULL)
205 int nframes;
207 wall = object_read_file("gfx/wall-ll.3d", &nframes);
208 render_compile_dlist(wall);
211 render_dlist(wall, NULL);
215 canto inferior direito
217 void map_draw_lr_wall(struct game *game, int x, int y)
219 static struct object *wall = NULL;
221 map_setup_wall(game, x, y);
223 if(wall == NULL)
225 int nframes;
227 wall = object_read_file("gfx/wall-lr.3d", &nframes);
228 render_compile_dlist(wall);
231 render_dlist(wall, NULL);
235 canto superior direito
237 void map_draw_ur_wall(struct game *game, int x, int y)
239 static struct object *wall = NULL;
241 map_setup_wall(game, x, y);
243 if(wall == NULL)
245 int nframes;
247 wall = object_read_file("gfx/wall-ur.3d", &nframes);
248 render_compile_dlist(wall);
251 render_dlist(wall, NULL);
255 canto superior esquerdo
257 void map_draw_ul_wall(struct game *game, int x, int y)
259 static struct object *wall = NULL;
261 map_setup_wall(game, x, y);
263 if(wall == NULL)
265 int nframes;
267 wall = object_read_file("gfx/wall-ul.3d", &nframes);
268 render_compile_dlist(wall);
271 render_dlist(wall, NULL);
275 desenha comida do pacman em (x,y) no mapa
277 void map_draw_pacman_food(struct map *map, int x, int y)
279 static struct image_rgba32 *food = NULL;
281 if(food == NULL)
283 food = gfx_get("gfx/dot-yellow.tga");
284 gfx_alpha_from_intensity("gfx/dot-yellow.tga");
285 gfx_upload_texture("gfx/dot-yellow.tga");
288 glDisable(GL_LIGHTING);
289 glEnable(GL_DEPTH_TEST);
290 glEnable(GL_BLEND);
291 // glBlendFunc(GL_ONE, GL_ONE);
292 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
293 glEnable(GL_TEXTURE_2D);
294 glBindTexture(GL_TEXTURE_2D, food->id);
296 glDepthMask(GL_FALSE);
298 switch(MAP_FOOD(map, x, y).type)
300 case FOOD_TYPE_NORMAL:
301 if(MAP_FOOD(map, x, y).status == FOOD_STATUS_ACTIVE)
302 render_draw_plane((GLfloat)x + 0.5, -0.5, (GLfloat)y + 0.5, 1.0);
304 break;
306 case FOOD_TYPE_RESPAWN:
307 if(MAP_FOOD(map, x, y).status == FOOD_STATUS_EATEN)
309 if(MAP_FOOD(map, x, y).time <= MAP_FOOD(map, x, y).fade_in)
310 render_draw_plane((GLfloat)x + 0.5, -0.5, (GLfloat)y + 0.5,
311 1.0 - (MAP_FOOD(map, x, y).time /
312 MAP_FOOD(map, x, y).fade_in));
313 } else
314 /* active */
315 render_draw_plane((GLfloat)x + 0.5, -0.5, (GLfloat)y + 0.5, 1.0);
317 break;
319 case FOOD_TYPE_INTERMITTENT:
320 if(MAP_FOOD(map, x, y).status == FOOD_STATUS_ACTIVE)
322 if(MAP_FOOD(map, x, y).time <= MAP_FOOD(map, x, y).fade_out)
323 render_draw_plane((GLfloat)x + 0.5, -0.5, (GLfloat)y + 0.5,
324 (MAP_FOOD(map, x, y).time /
325 MAP_FOOD(map, x, y).fade_out));
326 else
327 render_draw_plane((GLfloat)x + 0.5, -0.5, (GLfloat)y + 0.5, 1.0);
328 } else {
329 if(MAP_FOOD(map, x, y).time <= MAP_FOOD(map, x, y).fade_in)
330 render_draw_plane((GLfloat)x + 0.5, -0.5, (GLfloat)y + 0.5,
331 1.0 - (MAP_FOOD(map, x, y).time /
332 MAP_FOOD(map, x, y).fade_in));
335 break;
338 glDepthMask(GL_TRUE);
341 void map_draw_pacman_pill(struct map *map, int x, int y)
343 static GLUquadricObj *sphere = NULL;
345 if(sphere == NULL)
347 sphere = gluNewQuadric();
348 gluQuadricNormals(sphere, GLU_SMOOTH);
349 gluQuadricTexture(sphere, GLU_FALSE);
350 gluQuadricOrientation(sphere, GLU_OUTSIDE);
351 gluQuadricDrawStyle(sphere, GLU_FILL);
354 glMatrixMode(GL_MODELVIEW);
355 glLoadIdentity();
357 /* XXX - isto a mexer fica mais giro */
358 // glTranslatef((GLfloat)x + 0.5, pill_height, (GLfloat)y + 0.5);
359 // glTranslatef((GLfloat)x + 0.5, MAP(map, x, y).c_data.pill.height, (GLfloat)y + 0.5);
360 glTranslatef((GLfloat)x + 0.5,
361 -0.5 + 0.25 * sin(PILL_BOB_FREQUENCY * (float)SDL_GetTicks() / 1000.0 +
362 MAP(map, x, y).c_data.pill.phase),
363 (GLfloat)y + 0.5);
365 glEnable(GL_DEPTH_TEST);
366 glDepthMask(GL_TRUE);
367 glDisable(GL_TEXTURE_2D);
368 glDisable(GL_BLEND);
370 glColor4f(0.91, 0.88, 0.28, 1.0);
371 gluSphere(sphere, 0.2, 15, 15);
374 void map_draw_wall(struct game *game, int x, int y)
376 struct map *map;
378 map = game->map;
380 switch(MAP(map, x, y).wall)
382 case MAP_WALL_HORIZONTAL:
383 map_draw_horizontal_wall(game, x, y);
384 break;
386 case MAP_WALL_VERTICAL:
387 map_draw_vertical_wall(game, x, y);
388 break;
390 case MAP_WALL_LL:
391 map_draw_ll_wall(game, x, y);
392 break;
394 case MAP_WALL_UL:
395 map_draw_ul_wall(game, x, y);
396 break;
398 case MAP_WALL_LR:
399 map_draw_lr_wall(game, x, y);
400 break;
402 case MAP_WALL_UR:
403 map_draw_ur_wall(game, x, y);
404 break;
406 default:
407 break;
411 void map_render_opaque_objects(struct game *game)
413 int x, y;
414 struct map *map;
416 map = game->map;
418 /* pass 1: untextured geometry */
420 glDisable(GL_BLEND);
421 glDisable(GL_TEXTURE_2D);
423 for(x = 0; x < map->width; x++)
424 for(y = 0; y < map->height; y++)
426 map_draw_wall(game, x, y);
428 glDisable(GL_BLEND);
429 glDisable(GL_TEXTURE_2D);
430 glDisable(GL_TEXTURE_GEN_S);
431 glDisable(GL_TEXTURE_GEN_T);
433 switch(MAP(map, x, y).content)
435 case MAP_CONTENT_PILL:
436 if(MAP(map, x, y).c_data.pill.status == PILL_STATUS_ACTIVE)
437 map_draw_pacman_pill(map, x, y);
438 break;
442 #ifdef UGLY_LIGHTMAPS
443 /* pass 2: additive lightmaps */
444 for(c = 0; c < game->n_shots; c++)
445 switch(game->shots[c].type)
447 case SHOT_TYPE_ROCKET:
448 if(game->shots[c].state != SHOT_STATE_ACTIVE)
449 continue;
451 map_draw_rocket_lightmap(game, c);
452 break;
454 #endif
457 void map_draw_rocket_lightmap(struct game *game, int c)
459 static struct image_rgba32 *texture = NULL;
460 struct shot *rocket;
461 int x, y;
463 /* object plane coefficients (s, t, r, q) */
464 GLfloat params[4];
466 if(texture == NULL)
468 texture = gfx_get("gfx/rocket-highlight.tga");
469 gfx_upload_texture("gfx/rocket-highlight.tga");
472 rocket = &game->shots[c];
474 /* set up texturing */
475 glBindTexture(GL_TEXTURE_2D, texture->id);
476 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
477 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
478 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
479 glEnable(GL_TEXTURE_2D);
481 /* texture coordinate generation */
482 switch(rocket->direction)
484 case DIRECTION_LEFT:
485 params[X] = -1.0;
486 params[Y] = 0.0;
487 params[Z] = 1.0;
488 params[W] = 1.0;
489 break;
491 case DIRECTION_RIGHT:
492 params[X] = 1.0;
493 params[Y] = 0.0;
494 params[Z] = 1.0;
495 params[W] = 1.0;
496 break;
498 case DIRECTION_UP:
499 params[X] = 0.0;
500 params[Y] = 0.0;
501 params[Z] = 1.0;
502 params[W] = 1.0;
503 break;
505 case DIRECTION_DOWN:
506 params[X] = 0.0;
507 params[Y] = 0.0;
508 params[Z] = -1.0;
509 params[W] = 1.0;
510 break;
513 glTexGenfv(GL_S, GL_OBJECT_PLANE, params);
514 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
515 glEnable(GL_TEXTURE_GEN_S);
517 params[X] = 0.0;
518 params[Y] = 1.0;
519 params[Z] = 0.0;
520 params[W] = 1.0;
521 glTexGenfv(GL_T, GL_OBJECT_PLANE, params);
522 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
523 glEnable(GL_TEXTURE_GEN_T);
525 /* additive alpha blending */
526 glBlendFunc(GL_ONE, GL_ONE);
527 glEnable(GL_BLEND);
529 glColor4f(1.0, 1.0, 1.0, 1.0);
531 /* draw map squares */
532 x = (int)rocket->position[X];
533 y = (int)rocket->position[Z];
535 switch(rocket->direction)
537 case DIRECTION_LEFT:
538 /* up right square */
540 /* glPolygonOffset and glDepthFunc(GL_LESS) might be a better idea
541 instead of messing with the projection matrix */
542 glMatrixMode(GL_PROJECTION);
543 glPushMatrix();
544 glTranslatef(0.0, 0.0, -0.01);
546 glMatrixMode(GL_TEXTURE);
547 glLoadIdentity();
548 glTranslatef(-(rocket->position[X] - (float)x) + 1.0, -0.5, 0.3);
550 #if 0
551 switch(MAP(game->map, x + 1, y + 1).wall)
553 case MAP_WALL_LL:
554 /* fix texturing for LL corners */
555 printf("fixing LL corner for UR\n");
556 params[X] = -1.0;
557 params[Y] = 0.0;
558 params[Z] = 1.0;
559 params[W] = 1.0;
560 break;
562 default:
563 params[X] = -1.0;
564 params[Y] = 0.0;
565 params[Z] = 1.0;
566 params[W] = 1.0;
567 break;
570 glTexGenfv(GL_S, GL_OBJECT_PLANE, params);
571 #endif
572 map_draw_wall(game, x + 1, y + 1);
574 /* up square */
575 glMatrixMode(GL_TEXTURE);
576 glLoadIdentity();
577 glTranslatef(-(rocket->position[X] - (float)x), -0.5, 0.3);
579 #if 0
580 switch(MAP(game->map, x, y + 1).wall)
582 case MAP_WALL_LL:
583 /* fix texturing for LL corners */
584 printf("fixing LL corner for UP\n");
585 params[X] = -1.0;
586 params[Y] = 0.0;
587 params[Z] = 1.0;
588 params[W] = 1.0;
589 break;
591 default:
592 params[X] = -1.0;
593 params[Y] = 0.0;
594 params[Z] = 1.0;
595 params[W] = 1.0;
596 break;
599 glTexGenfv(GL_S, GL_OBJECT_PLANE, params);
600 #endif
601 map_draw_wall(game, x, y + 1);
604 /* down right square */
605 glMatrixMode(GL_PROJECTION);
606 glPopMatrix();
607 glPushMatrix();
608 glTranslatef(0.0, 0.0, 0.01);
610 glMatrixMode(GL_TEXTURE);
611 glLoadIdentity();
612 glTranslatef(-(rocket->position[X] - (float)x), -0.5, 0.3);
614 map_draw_wall(game, x + 1, y - 1);
616 /* down square */
617 glMatrixMode(GL_TEXTURE);
618 glLoadIdentity();
619 glTranslatef(-(rocket->position[X] - (float)x) - 1.0, -0.5, 0.3);
621 map_draw_wall(game, x, y - 1);
623 glMatrixMode(GL_PROJECTION);
624 glPopMatrix();
626 break;
628 case DIRECTION_RIGHT:
629 /* up left square */
630 glMatrixMode(GL_PROJECTION);
631 glPushMatrix();
632 glTranslatef(0.0, 0.0, -0.01);
634 glMatrixMode(GL_TEXTURE);
635 glLoadIdentity();
636 glTranslatef(-(rocket->position[X] - (float)x), -0.5, 0.0);
638 map_draw_wall(game, x - 1, y + 1);
640 /* up square */
641 glMatrixMode(GL_TEXTURE);
642 glLoadIdentity();
643 glTranslatef(-(rocket->position[X] - (float)x) + 1.0, -0.5, 0.0);
645 map_draw_wall(game, x, y + 1);
648 /* down left square */
649 glMatrixMode(GL_PROJECTION);
650 glPopMatrix();
651 glPushMatrix();
652 glTranslatef(0.0, 0.0, 0.01);
654 glMatrixMode(GL_TEXTURE);
655 glLoadIdentity();
656 glTranslatef(-(rocket->position[X] - (float)x) - 1.0, -0.5, 0.0);
658 map_draw_wall(game, x - 1, y - 1);
660 /* down square */
661 glMatrixMode(GL_TEXTURE);
662 glLoadIdentity();
663 glTranslatef(-(rocket->position[X] - (float)x), -0.5, 0.0);
665 map_draw_wall(game, x, y - 1);
667 glMatrixMode(GL_PROJECTION);
668 glPopMatrix();
670 break;
672 case DIRECTION_UP:
673 /* left down square */
674 glMatrixMode(GL_PROJECTION);
675 glPushMatrix();
676 glTranslatef(0.01, 0.0, 0.0);
678 glMatrixMode(GL_TEXTURE);
679 glLoadIdentity();
680 glTranslatef(0.0, -0.5, -(rocket->position[Z] - (float)y));
682 map_draw_wall(game, x - 1, y - 1);
684 /* left square */
685 glMatrixMode(GL_TEXTURE);
686 glLoadIdentity();
687 glTranslatef(0.0, -0.5, -(rocket->position[Z] - (float)y) + 1.0);
689 map_draw_wall(game, x - 1, y);
691 /* right down square */
692 glMatrixMode(GL_PROJECTION);
693 glPopMatrix();
694 glPushMatrix();
695 glTranslatef(-0.01, 0.0, 0.0);
697 glMatrixMode(GL_TEXTURE);
698 glLoadIdentity();
699 glTranslatef(0.0, -0.5, -(rocket->position[Z] - (float)y));
701 map_draw_wall(game, x + 1, y - 1);
703 /* right square */
704 glMatrixMode(GL_TEXTURE);
705 glLoadIdentity();
706 glTranslatef(0.0, -0.5, -(rocket->position[Z] - (float)y) + 1.0);
708 map_draw_wall(game, x + 1, y);
710 glMatrixMode(GL_PROJECTION);
711 glPopMatrix();
713 break;
715 case DIRECTION_DOWN:
716 /* left up square */
717 glMatrixMode(GL_PROJECTION);
718 glPushMatrix();
719 glTranslatef(0.01, 0.0, 0.0);
721 glMatrixMode(GL_TEXTURE);
722 glLoadIdentity();
723 glTranslatef(0.0, -0.5, -(rocket->position[Z] - (float)y) + 1.0);
725 map_draw_wall(game, x - 1, y + 1);
727 /* left square */
728 glMatrixMode(GL_TEXTURE);
729 glLoadIdentity();
730 glTranslatef(0.0, -0.5, -(rocket->position[Z] - (float)y));
732 map_draw_wall(game, x - 1, y);
734 /* right up square */
735 glMatrixMode(GL_PROJECTION);
736 glPopMatrix();
737 glPushMatrix();
738 glTranslatef(-0.01, 0.0, 0.0);
740 glMatrixMode(GL_TEXTURE);
741 glLoadIdentity();
742 glTranslatef(0.0, -0.5, -(rocket->position[Z] - (float)y) + 1.0);
744 map_draw_wall(game, x + 1, y + 1);
746 /* right square */
747 glMatrixMode(GL_TEXTURE);
748 glLoadIdentity();
749 glTranslatef(0.0, -0.5, -(rocket->position[Z] - (float)y));
751 map_draw_wall(game, x + 1, y);
753 glMatrixMode(GL_PROJECTION);
754 glPopMatrix();
756 break;
759 glDisable(GL_BLEND);
760 glDisable(GL_TEXTURE_GEN_S);
761 glDisable(GL_TEXTURE_GEN_T);
762 glDisable(GL_TEXTURE_2D);
763 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
765 glMatrixMode(GL_TEXTURE);
766 glLoadIdentity();
767 glMatrixMode(GL_MODELVIEW);
770 void map_render_translucent_objects(struct game *game, int player_no)
772 int x, y;
773 struct map *map;
774 struct camera *cam;
776 if(player_no == -1)
777 cam = game->demo_camera;
778 else
779 cam = game->players[player_no].camera;
781 render_setup_plane_geometry(cam, 1.0);
783 map = game->map;
784 for(x = 0; x < map->width; x++)
785 for(y = 0; y < map->height; y++)
786 switch(MAP(map, x, y).content)
788 case MAP_CONTENT_FOOD:
789 /* comidinha do pacman */
790 map_draw_pacman_food(map, x, y);
791 break;