2 Cantaveria - action adventure platform game
3 Copyright (C) 2009 2010 Evan Rinehart
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
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
35 enum cardinal
{NORTH
, SOUTH
, EAST
, WEST
};
78 enum cardinal snap
[4];
90 enum tile_shape shapes
[256];
91 stage
** stages
; // w by h array
112 enum cardinal
dir_of(int i
, int j
){
113 if(i
< 0) return WEST
;
114 if(j
< 0) return NORTH
;
115 if(i
> 0) return EAST
;
116 if(j
> 0) return SOUTH
;
117 fatal_error("stage.c: (%d,%d) is not a valid direction\n", i
, j
);
125 /* zones and stages */
126 zone
* find_zone_by_id(int id
){
127 list
* ptr
= zones
->next
;
130 if(z
->id
== id
) return z
;
136 zone
* zone_of_stage(stage
* s
){
137 return find_zone_by_id(s
->zid
);
140 stage
* stage_lookup(zone
* z
, int i
, int j
){
141 if(i
< 0 || i
>= z
->w
|| j
< 0 || j
>= z
->h
){
144 return *(z
->stages
+ i
+ j
*z
->w
);
148 stage
* follow_zoneport(zoneport
* zp
){
149 zone
* z
= find_zone_by_id(zp
->zone
);
150 return stage_lookup(z
, zp
->i
, zp
->j
);
153 stage
* find_stage(stage
* home
, int i
, int j
){
154 zone
* z
= zone_of_stage(home
);
157 int di
= home
->i
- si
;
158 int dj
= home
->j
- sj
;
162 else if(home
->exit
&& home
->exit
->dir
== dir_of(di
,dj
))
163 return follow_zoneport(home
->exit
);
166 return stage_lookup(z
, si
- z
->w
, sj
- z
->h
);
169 stage
* load_stage(reader
* rd
){
171 stage
* s
= xmalloc(sizeof(stage
));
172 s
->i
= read_short(rd
);
173 s
->j
= read_short(rd
);
174 read_byte(rd
); // flags ?
177 char* str
= read_string(rd
);
183 s
->fg
[i
][j
] = read_byte(rd
);
190 /* collision computations */
192 int left_side_of(block bl
, int top
, int bottom
){
196 int right_side_of(block bl
, int top
, int bottom
){
200 int top_of(block bl
, int left
, int right
){
204 int bottom_of(block bl
, int left
, int right
){
208 int xhit(int v
, block block
, int top
, int bottom
){
209 if(v
> 0) return left_side_of(block
, top
, bottom
);
210 if(v
< 0) return right_side_of(block
, top
, bottom
);
214 int yhit(int v
, block block
, int left
, int right
){
215 if(v
> 0) return top_of(block
, left
, right
);
216 if(v
< 0) return bottom_of(block
, left
, right
);
220 int rect_is_on(block bl
, int L
, int R
, int T
, int B
){
225 return !(r
< L
|| l
> R
|| t
> B
|| b
< T
);
233 block
make_block(int shape
, int x
, int y
, int none
){
243 return make_block(0, 0, 0, 1);
247 return make_block(SHAPE_NULL
, 0, 0, 0);
250 block
block_of(int shape
, int x
, int y
){
251 return make_block(shape
, x
, y
, 0);
254 /* get block in s at i j */
255 block
block_from_stage(stage
* s
, int i
, int j
){
256 zone
* z
= zone_of_stage(s
);
257 int tile
= s
->fg
[i
][j
];
258 int shape
= z
->shapes
[tile
];
259 return block_of(shape
, i
, j
);
262 /* get block at absolute x y if you are in stage home */
263 block
get_block(stage
* home
, int x
, int y
){
264 zone
* z
= zone_of_stage(home
);
265 int i
= x
/1024/16 - (home
->i
+ z
->i
)*20;
266 int j
= y
/1024/16 - (home
->j
+ z
->j
)*15;
268 stage
* s
= find_stage(home
, i
, j
);
272 return block_from_stage(s
, i
, j
);
275 /* returns either a block that the rect is intersecting
276 or it returns a block with none set to 1 */
277 block
intersecting_block(stage
* s
, int left
, int right
, int top
, int bottom
){
282 case 0: bl
= get_block(s
, top
, left
); break;
283 case 1: bl
= get_block(s
, top
, right
); break;
284 case 2: bl
= get_block(s
, bottom
, left
); break;
285 case 3: bl
= get_block(s
, bottom
, right
); break;
287 if(rect_is_on(bl
, left
, right
, top
, bottom
)) return bl
;
303 int load_zone_gfx(reader
* rd
){
304 char* filename
= read_string(rd
);
305 int id
= load_bitmap(filename
);
311 int load_zone(char* filename
){
314 reader
* rd
= data_open("zones/", filename
);
315 zone
* z
= xmalloc(sizeof(zone
)); /* load routine */
317 strncpy(z
->name
, filename
, 32);
319 z
->fgtiles
= load_zone_gfx(rd
);
320 // z->bgtiles = load_zone_gfx(rd);
321 // z->dectiles = load_zone_gfx(rd);;
322 z
->bgimage
= load_bitmap("background.tga");
324 for(i
=0; i
<256; i
++){
325 z
->shapes
[i
] = read_byte(rd
);
328 z
->i
= read_short(rd
);
329 z
->j
= read_short(rd
);
330 z
->w
= read_short(rd
);
331 z
->h
= read_short(rd
);
332 z
->stages
= xmalloc(z
->w
* z
->h
* sizeof(stage
*));
334 for(i
=0; i
< z
->w
; i
++){
335 for(j
=0; j
< z
->h
; j
++){
336 *(z
->stages
+ i
+ j
*z
->w
) = NULL
;
340 int N
= read_short(rd
);
342 stage
* s
= load_stage(rd
);
343 z
->stages
[s
->i
+ s
->j
* z
->w
] = s
;
351 void print_zone(int id
){
352 zone
* z
= find_zone_by_id(id
);
353 printf("zone: %p\n", z
);
357 void stage_bind_camera(location l
, int* x
, int* y
){
358 //for each snap, snap x y
361 void draw_stage_fg(location loc
, int cx
, int cy
){
366 void draw_stage_bg(location loc
, int cx
, int cy
){
367 //for each visible tile
368 //bg or bg tiles or fg tiles
371 /* returns 1 if a collision will occur, 0 otherwise
372 if 1 is returned, x will be set to the collision point */
373 int stage_xcollide(location loc
, int w
, int h
, int v
, int* x
){
374 zone
* z
= find_zone_by_id(loc
.z
);
375 stage
* s
= stage_lookup(z
, loc
.i
, loc
.j
);
376 int X
= loc
.x
+ v
*10; /* FIXME dt */
380 int bottom
= loc
.y
+ h
;
382 block bl
= intersecting_block(s
, left
, right
, top
, bottom
);
384 if(bl
.none
) return 0;
386 *x
= xhit(v
, bl
, top
, bottom
);
391 int stage_ycollide(location loc
, int w
, int h
, int v
, int* y
){