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: map.c,v 1.47 2003/11/22 17:32:09 nsubtil Exp $";
45 struct map
*map_load_from_ascii(char **game_map
, char **ghost_map
, int width
, int height
)
50 ret
= (struct map
*)malloc(sizeof(struct map
));
54 ret
->tiles
= (struct map_tile
**)malloc(sizeof(struct map_tile
*) * height
);
55 for(y
= 0; y
< height
; y
++)
57 ret
->tiles
[y
] = malloc(strlen(game_map
[y
]) * sizeof(struct map_tile
));
59 for(x
= 0; x
< width
; x
++)
61 switch(game_map
[height
- 1 - y
][x
])
64 MAP(ret
, x
, y
).wall
= MAP_WALL_UL
;
65 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
66 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
67 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
71 MAP(ret
, x
, y
).wall
= MAP_WALL_LL
;
72 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
73 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
74 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
78 MAP(ret
, x
, y
).wall
= MAP_WALL_UR
;
79 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
80 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
81 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
85 MAP(ret
, x
, y
).wall
= MAP_WALL_LR
;
86 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
87 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
88 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
92 MAP(ret
, x
, y
).wall
= MAP_WALL_HORIZONTAL
;
93 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
94 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
95 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
99 MAP(ret
, x
, y
).wall
= MAP_WALL_VERTICAL
;
100 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
101 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
102 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
106 MAP(ret
, x
, y
).wall
= MAP_WALL_GHOST_ONLY
;
107 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
108 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
109 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
113 MAP(ret
, x
, y
).wall
= MAP_WALL_GHOST_ONLY
;
114 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
115 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
116 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_UP
;
120 MAP(ret
, x
, y
).wall
= MAP_WALL_NONE
;
121 MAP(ret
, x
, y
).content
= MAP_CONTENT_TELEPORT
;
122 /* XXX - ugly, terrible hack, don't look! */
123 MAP(ret
, x
, y
).c_data
.teleport
.dest_x
= 0;
124 MAP(ret
, x
, y
).c_data
.teleport
.dest_y
= y
;
125 MAP_TELEPORT(ret
, x
, y
).direction
= DIRECTION_RIGHT
;
126 /* it is safe to look again now */
127 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
128 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_LEFT
;
132 MAP(ret
, x
, y
).wall
= MAP_WALL_NONE
;
133 MAP(ret
, x
, y
).content
= MAP_CONTENT_TELEPORT
;
134 /* XXX - close your eyes... */
135 MAP(ret
, x
, y
).c_data
.teleport
.dest_x
= ret
->width
- 1;
136 MAP(ret
, x
, y
).c_data
.teleport
.dest_y
= y
;
137 MAP_TELEPORT(ret
, x
, y
).direction
= DIRECTION_LEFT
;
139 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
140 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_RIGHT
;
144 MAP(ret
, x
, y
).wall
= MAP_WALL_NONE
;
145 MAP(ret
, x
, y
).content
= MAP_CONTENT_FOOD
;
146 MAP(ret
, x
, y
).c_data
.food
.type
= FOOD_TYPE_NORMAL
;
147 MAP(ret
, x
, y
).c_data
.food
.status
= FOOD_STATUS_ACTIVE
;
148 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
149 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
153 MAP(ret
, x
, y
).wall
= MAP_WALL_NONE
;
154 MAP(ret
, x
, y
).content
= MAP_CONTENT_PILL
;
155 MAP(ret
, x
, y
).c_data
.pill
.status
= PILL_STATUS_ACTIVE
;
156 MAP(ret
, x
, y
).c_data
.pill
.phase
=
157 2.0 * M_PI
* (float)((rand() % 10) / 9.0);
158 MAP(ret
, x
, y
).flags
= MAP_FLAGS_NONE
;
159 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
163 MAP(ret
, x
, y
).wall
= MAP_WALL_GHOST_ONLY
;
164 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
165 MAP(ret
, x
, y
).flags
= MAP_FLAG_GHOST_START_POSITION
;
166 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
170 MAP(ret
, x
, y
).wall
= MAP_WALL_NONE
;
171 MAP(ret
, x
, y
).content
= MAP_CONTENT_NONE
;
172 MAP(ret
, x
, y
).flags
= MAP_FLAG_PACMAN_START_POSITION
;
173 MAP(ret
, x
, y
).ghost_dir_alive
= DIRECTION_NONE
;
177 printf("map_load_from_ascii: ora portantos temos aqui um %d... (y %d, x %d, w %d, h %d)\n", game_map
[height
- 1 - y
][x
], y
, x
, width
, height
);
182 if(ghost_map
== NULL
)
183 MAP(ret
, x
, y
).ghost_dir
= DIRECTION_NONE
;
185 switch(ghost_map
[height
- 1 - y
][x
])
188 MAP(ret
, x
, y
).ghost_dir
= DIRECTION_UP
;
192 MAP(ret
, x
, y
).ghost_dir
= DIRECTION_DOWN
;
196 MAP(ret
, x
, y
).ghost_dir
= DIRECTION_LEFT
;
200 MAP(ret
, x
, y
).ghost_dir
= DIRECTION_RIGHT
;
204 MAP(ret
, x
, y
).ghost_dir
= DIRECTION_NONE
;
213 void map_free(struct map
*map
)
217 for(c
= 0; c
< map
->height
; c
++)
224 void map_update(struct map
*map
, float delta
)
228 for(x
= 0; x
< map
->width
; x
++)
229 for(y
= 0; y
< map
->height
; y
++)
231 switch(MAP(map
, x
, y
).content
)
233 case MAP_CONTENT_FOOD
:
235 switch(MAP_FOOD(map
, x
, y
).type
)
237 case FOOD_TYPE_RESPAWN
:
238 if(MAP_FOOD(map
, x
, y
).status
== FOOD_STATUS_EATEN
)
240 MAP_FOOD(map
, x
, y
).time
-= delta
;
241 if(MAP_FOOD(map
, x
, y
).time
<= 0.0)
242 MAP_FOOD(map
, x
, y
).status
=
248 case FOOD_TYPE_INTERMITTENT
:
249 MAP_FOOD(map
, x
, y
).time
-= delta
;
250 if(MAP_FOOD(map
, x
, y
).time
<= 0.0)
252 switch(MAP_FOOD(map
, x
, y
).status
)
254 case FOOD_STATUS_ACTIVE
:
255 MAP_FOOD(map
, x
, y
).status
=
257 MAP_FOOD(map
, x
, y
).time
=
258 MAP_FOOD(map
, x
, y
).inactive_time
;
261 case FOOD_STATUS_EATEN
:
262 MAP_FOOD(map
, x
, y
).status
=
264 MAP_FOOD(map
, x
, y
).time
=
265 MAP_FOOD(map
, x
, y
).active_time
;
274 int map_collision_square(struct game
*game
, int x
, int y
)
280 if(MAP(map
, x
, y
).wall
== MAP_WALL_NONE
||
281 MAP(map
, x
, y
).wall
== MAP_WALL_GHOST_ONLY
)
288 detects collisions on the map along a line between two points
289 returns 0 if no collision is detected or 1 with the tile where collision occurs in ret
291 int map_detect_collision(struct game
*game
, float start_pos
[3], float end_pos
[3], int ret
[2])
293 /* bresenham line algorithm with extended coverage */
294 /* http://www.ese-metz.fr/~dedu/projects/bresenham/ */
295 /* XXX - is this even correct ? the original doesn't look very good */
296 int c
, step_x
, step_y
, error
;//, last_error;
298 int x
, y
, dx
, dy
, ddx
, ddy
;
300 /* for 3d collisions */
301 float h
, step_h
, dist
, tmp
[3];
303 end
[X
] = (int)end_pos
[X
];
304 end
[Y
] = (int)end_pos
[Z
];
306 x
= (int)start_pos
[X
];
307 y
= (int)start_pos
[Z
];
309 math_sub_vec3(tmp
, end_pos
, start_pos
);
310 dist
= math_norm_vec3(tmp
);
312 step_h
= tmp
[Y
] / dist
;
317 /* check first point */
318 if(x
< 0 || x
>= game
->map
->width
||
319 y
< 0 || y
>= game
->map
->height
)
322 if(h
> -1.0 && map_collision_square(game
, x
, y
))
324 /* collision at x, y */
352 for(c
= 0; c
< dx
; c
++)
358 if(h
< -1.0 && step_h
< 0.0)
359 /* gone over the map, no collision possible */
367 if(error
+ last_error
< ddx
)
370 map_collision_square(game
, x
, y
- step_y
))
372 /* collision at x, y - step_y */
378 if(error
+ last_error
> ddx
)
381 map_collision_square(game
, x
- step_x
, y
))
383 /* collision at x - step_x, y */
390 map_collision_square(game
, x
, y
- step_y
))
398 map_collision_square(game
, x
- step_x
, y
))
409 if(x
< 0 || x
>= game
->map
->width
||
410 y
< 0 || y
>= game
->map
->height
)
413 if(h
> -1.0 && map_collision_square(game
, x
, y
))
424 for(c
= 0; c
< dy
; c
++)
430 if(h
< -1.0 && step_h
< 0.0)
431 /* gone over the map, no collision possible */
439 if(error
+ last_error
< ddy
)
442 map_collision_square(game
, x
- step_x
, y
))
449 if(error
+ last_error
> ddy
)
452 map_collision_square(game
, x
, y
- step_y
))
460 map_collision_square(game
, x
- step_x
, y
))
468 map_collision_square(game
, x
, y
- step_y
))
479 if(x
< 0 || x
>= game
->map
->width
||
480 y
< 0 || y
>= game
->map
->height
)
484 map_collision_square(game
, x
, y
))
496 int map_inside(struct game
*game
, int x
, int y
)
498 if(x
< 0 || x
> game
->map
->width
||
499 y
< 0 || y
> game
->map
->height
)