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
){
172 stage
* s
= xmalloc(sizeof(stage
));
173 read_short(rd
, &s
->i
);
174 read_short(rd
, &s
->j
);
175 read_byte(rd
, &dummy
); // flags ?
179 read_string(rd
, &str
);
185 read_byte(rd
, (int*)&s
->fg
[i
][j
]);
192 /* collision computations */
194 int left_side_of(block bl
, int top
, int bottom
){
198 int right_side_of(block bl
, int top
, int bottom
){
202 int top_of(block bl
, int left
, int right
){
206 int bottom_of(block bl
, int left
, int right
){
210 int xhit(int v
, block block
, int top
, int bottom
){
211 if(v
> 0) return left_side_of(block
, top
, bottom
);
212 if(v
< 0) return right_side_of(block
, top
, bottom
);
216 int yhit(int v
, block block
, int left
, int right
){
217 if(v
> 0) return top_of(block
, left
, right
);
218 if(v
< 0) return bottom_of(block
, left
, right
);
222 int rect_is_on(block bl
, int L
, int R
, int T
, int B
){
227 return !(r
< L
|| l
> R
|| t
> B
|| b
< T
);
235 block
make_block(int shape
, int x
, int y
, int none
){
245 return make_block(0, 0, 0, 1);
249 return make_block(SHAPE_NULL
, 0, 0, 0);
252 block
block_of(int shape
, int x
, int y
){
253 return make_block(shape
, x
, y
, 0);
256 /* get block in s at i j */
257 block
block_from_stage(stage
* s
, int i
, int j
){
258 zone
* z
= zone_of_stage(s
);
259 int tile
= s
->fg
[i
][j
];
260 int shape
= z
->shapes
[tile
];
261 return block_of(shape
, i
, j
);
264 /* get block at absolute x y if you are in stage home */
265 block
get_block(stage
* home
, int x
, int y
){
266 zone
* z
= zone_of_stage(home
);
267 int i
= x
/1024/16 - (home
->i
+ z
->i
)*20;
268 int j
= y
/1024/16 - (home
->j
+ z
->j
)*15;
270 stage
* s
= find_stage(home
, i
, j
);
274 return block_from_stage(s
, i
, j
);
277 /* returns either a block that the rect is intersecting
278 or it returns a block with none set to 1 */
279 block
intersecting_block(stage
* s
, int left
, int right
, int top
, int bottom
){
284 case 0: bl
= get_block(s
, top
, left
); break;
285 case 1: bl
= get_block(s
, top
, right
); break;
286 case 2: bl
= get_block(s
, bottom
, left
); break;
287 case 3: bl
= get_block(s
, bottom
, right
); break;
289 if(rect_is_on(bl
, left
, right
, top
, bottom
)) return bl
;
305 int load_zone_gfx(reader
* rd
){
307 read_string(rd
, &filename
);
308 int id
= load_bitmap(filename
);
314 int load_zone(char* filename
){
318 reader
* rd
= data_open("zones/", filename
);
319 zone
* z
= xmalloc(sizeof(zone
)); /* load routine */
321 strncpy(z
->name
, filename
, 32);
323 z
->fgtiles
= load_zone_gfx(rd
);
324 // z->bgtiles = load_zone_gfx(rd);
325 // z->dectiles = load_zone_gfx(rd);;
326 z
->bgimage
= load_bitmap("background.tga");
328 for(i
=0; i
<256; i
++){
329 read_byte(rd
, (int*)&z
->shapes
[i
]);
332 read_short(rd
, &z
->i
);
333 read_short(rd
, &z
->j
);
334 read_short(rd
, &z
->w
);
335 read_short(rd
, &z
->h
);
336 z
->stages
= xmalloc(z
->w
* z
->h
* sizeof(stage
*));
338 for(i
=0; i
< z
->w
; i
++){
339 for(j
=0; j
< z
->h
; j
++){
340 *(z
->stages
+ i
+ j
*z
->w
) = NULL
;
346 stage
* s
= load_stage(rd
);
347 z
->stages
[s
->i
+ s
->j
* z
->w
] = s
;
355 void print_zone(int id
){
356 zone
* z
= find_zone_by_id(id
);
357 printf("zone: %p\n", z
);
361 void stage_bind_camera(location l
, int* x
, int* y
){
362 //for each snap, snap x y
365 void draw_stage_fg(location loc
, int cx
, int cy
){
370 void draw_stage_bg(location loc
, int cx
, int cy
){
371 //for each visible tile
372 //bg or bg tiles or fg tiles
375 /* returns 1 if a collision will occur, 0 otherwise
376 if 1 is returned, x will be set to the collision point */
377 int stage_xcollide(location loc
, int w
, int h
, int v
, int* x
){
378 zone
* z
= find_zone_by_id(loc
.z
);
379 stage
* s
= stage_lookup(z
, loc
.i
, loc
.j
);
380 int X
= loc
.x
+ v
*10; /* FIXME dt */
384 int bottom
= loc
.y
+ h
;
386 block bl
= intersecting_block(s
, left
, right
, top
, bottom
);
388 if(bl
.none
) return 0;
390 *x
= xhit(v
, bl
, top
, bottom
);
395 int stage_ycollide(location loc
, int w
, int h
, int v
, int* y
){