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
};
97 enum tile_shape shapes
[256];
98 stage
** stages
; // w by h array
102 how the above is stored in a binary file
105 short[4] z->{i, j, w, h}
106 short [number of stages N]
115 byte[4] 0x0a 0x0b 0x0c 0x0d
116 int format version (1)
118 short[4] z->{i, j, w, h}
124 short number of stages N
128 byte[4] 'exit' or 'none'
129 a zone port is next if previous was 'exit'
132 byte 'L' 'U' 'D' or 'R'
133 short number of decorations M
138 short number of waters W
163 enum cardinal
dir_of(int i
, int j
){
164 if(i
< 0) return WEST
;
165 if(j
< 0) return NORTH
;
166 if(i
> 0) return EAST
;
167 if(j
> 0) return SOUTH
;
168 fatal_error("stage.c: (%d,%d) is not a valid direction\n", i
, j
);
176 /* zones and stages */
177 zone
* find_zone_by_id(int id
){
178 list
* ptr
= zones
->next
;
181 if(z
->id
== id
) return z
;
187 zone
* zone_of_stage(stage
* s
){
188 return find_zone_by_id(s
->zid
);
191 stage
* stage_lookup(zone
* z
, int i
, int j
){
192 if(i
< 0 || i
>= z
->w
|| j
< 0 || j
>= z
->h
){
195 return *(z
->stages
+ i
+ j
*z
->w
);
199 stage
* follow_zoneport(zoneport
* zp
){
200 zone
* z
= find_zone_by_id(zp
->zone
);
201 return stage_lookup(z
, zp
->i
, zp
->j
);
204 stage
* find_stage(stage
* home
, int i
, int j
){
205 zone
* z
= zone_of_stage(home
);
208 int di
= home
->i
- si
;
209 int dj
= home
->j
- sj
;
213 else if(home
->exit
&& home
->exit
->dir
== dir_of(di
,dj
))
214 return follow_zoneport(home
->exit
);
217 return stage_lookup(z
, si
- z
->w
, sj
- z
->h
);
222 /* collision computations */
224 int left_side_of(block bl
, int top
, int bottom
){
228 int right_side_of(block bl
, int top
, int bottom
){
232 int top_of(block bl
, int left
, int right
){
236 int bottom_of(block bl
, int left
, int right
){
240 int xhit(int v
, block block
, int top
, int bottom
){
241 if(v
> 0) return left_side_of(block
, top
, bottom
);
242 if(v
< 0) return right_side_of(block
, top
, bottom
);
246 int yhit(int v
, block block
, int left
, int right
){
247 if(v
> 0) return top_of(block
, left
, right
);
248 if(v
< 0) return bottom_of(block
, left
, right
);
252 int rect_is_on(block bl
, int L
, int R
, int T
, int B
){
257 return !(r
< L
|| l
> R
|| t
> B
|| b
< T
);
265 block
make_block(int shape
, int x
, int y
, int none
){
275 return make_block(0, 0, 0, 1);
279 return make_block(SHAPE_NULL
, 0, 0, 0);
282 block
block_of(int shape
, int x
, int y
){
283 return make_block(shape
, x
, y
, 0);
286 /* get block in s at i j */
287 block
block_from_stage(stage
* s
, int i
, int j
){
288 zone
* z
= zone_of_stage(s
);
289 int tile
= s
->fg
[i
][j
];
290 int shape
= z
->shapes
[tile
];
291 return block_of(shape
, i
, j
);
294 /* get block at absolute x y if you are in stage home */
295 block
get_block(stage
* home
, int x
, int y
){
296 zone
* z
= zone_of_stage(home
);
297 int i
= x
/1024/16 - (home
->i
+ z
->i
)*20;
298 int j
= y
/1024/16 - (home
->j
+ z
->j
)*15;
300 stage
* s
= find_stage(home
, i
, j
);
304 return block_from_stage(s
, i
, j
);
307 /* returns either a block that the rect is intersecting
308 or it returns a block with none set to 1 */
309 block
intersecting_block(stage
* s
, int left
, int right
, int top
, int bottom
){
314 case 0: bl
= get_block(s
, top
, left
); break;
315 case 1: bl
= get_block(s
, top
, right
); break;
316 case 2: bl
= get_block(s
, bottom
, left
); break;
317 case 3: bl
= get_block(s
, bottom
, right
); break;
319 if(rect_is_on(bl
, left
, right
, top
, bottom
)) return bl
;
329 /******** stage loading routines ********/
330 static int load_stage_dimensions(stage
* s
, reader
* rd
){
332 read_short(rd
, &s
->i
) ||
333 read_short(rd
, &s
->j
);
336 static int load_stage_snap(stage
* s
, reader
* rd
){
337 return read_bytes(rd
, (unsigned char*)s
->snap
, 4);
340 static int load_stage_exit(stage
* s
, reader
* rd
){
341 char what
[5] = {0,0,0,0,0};
342 if(read_bytes(rd
, (unsigned char*)what
, 4)) return -1;
344 if(strcmp(what
, "none") == 0){
347 if(strcmp(what
, "exit") == 0){
349 printf("INCOMPLETE load_stage_exit doesnt work yet\n");
353 error_msg("load_zone: invalid stage header (missing exit)\n");
357 static int load_stage_decorations(stage
* s
, reader
* rd
){
359 if(read_short(rd
, &N
)) return -1;
363 printf("INCOMPLETE load_stage_decorations doesnt work yet\n");
370 static int load_stage_waters(stage
* s
, reader
* rd
){
372 if(read_short(rd
, &N
)) return -1;
376 printf("INCOMPLETE load_stage_waters doesnt work yet\n");
383 static int load_stage_data(stage
* s
, reader
* rd
){
387 if(read_byte(rd
, (int*)&s
->fg
[i
][j
])) return -1;
392 if(read_byte(rd
, (int*)&s
->bg
[i
][j
])) return -1;
398 static stage
* load_stage(reader
* rd
){
399 stage
* s
= xmalloc(sizeof(stage
));
408 load_stage_dimensions(s
, rd
) ||
409 load_stage_snap(s
, rd
) ||
410 load_stage_exit(s
, rd
) ||
411 load_stage_decorations(s
, rd
) ||
412 load_stage_waters(s
, rd
) ||
413 load_stage_data(s
, rd
)
423 static int load_zone_bitmap(reader
* rd
, int* out
){
425 if(read_string(rd
, &filename
)){
426 error_msg("load_zone: read error (graphics list)\n");
429 if(strlen(filename
) == 0){
433 *out
= load_bitmap(filename
);
436 error_msg("load_zone: can't load graphics %s\n", filename
);
444 static int load_zone_gfx(zone
* z
, reader
* rd
){
446 load_zone_bitmap(rd
, &z
->fgtiles
) ||
447 load_zone_bitmap(rd
, &z
->bgtiles
) ||
448 load_zone_bitmap(rd
, &z
->dectiles
) ||
449 load_zone_bitmap(rd
, &z
->bgimage
);
452 static int load_zone_shapes(zone
* z
, reader
* rd
){
454 for(i
=0; i
<256; i
++){
455 if(read_byte(rd
, (int*)&z
->shapes
[i
])){
462 static int load_zone_dimensions(zone
* z
, reader
* rd
){
464 read_short(rd
, &z
->i
) ||
465 read_short(rd
, &z
->j
) ||
466 read_short(rd
, &z
->w
) ||
467 read_short(rd
, &z
->h
);
470 static int load_zone_stages(zone
* z
, reader
* rd
){
473 z
->stages
= xmalloc(z
->w
* z
->h
* sizeof(stage
*));
475 for(i
=0; i
< z
->w
; i
++){
476 for(j
=0; j
< z
->h
; j
++){
477 *(z
->stages
+ i
+ j
*z
->w
) = NULL
;
481 if(read_short(rd
, &N
)) return -1;
483 printf("number of stages %d\n", N
);
485 stage
* s
= load_stage(rd
);
486 if(s
== NULL
) return -1;
487 z
->stages
[s
->i
+ s
->j
* z
->w
] = s
;
493 int load_zone_header(zone
* z
, reader
* rd
){
494 unsigned char magic1
[4];
495 unsigned char magic2
[4] = {0x0a, 0x0b, 0x0c, 0x0d};
499 read_bytes(rd
, magic1
, 4) ||
500 read_int(rd
, &format
) ||
505 if(memcmp(magic1
, magic2
, 4) != 0){
506 error_msg("load_zone: wrong file type (missing magic)\n");
511 error_msg("load_zone: wrong format version\n");
519 int load_zone(char* filename
){
520 reader
* rd
= data_open("zones/", filename
);
522 error_msg("load_zone: error opening \"%s\"\n", filename
);
526 zone
* z
= xmalloc(sizeof(zone
));
527 strncpy(z
->name
, filename
, 32);
528 z
->id
= 0; /* supposed to be in file */
535 load_zone_header(z
, rd
) ||
536 load_zone_dimensions(z
, rd
) ||
537 load_zone_gfx(z
, rd
) ||
538 load_zone_shapes(z
, rd
) ||
539 load_zone_stages(z
, rd
)
541 error_msg("load_zone: error reading \"%s\"\n", filename
);
550 /**************************************/
556 void print_shapes(enum tile_shape shapes
[256]){
561 printf("%02x ", shapes
[i
*16 + j
]);
567 void print_dir(char snap
[4], enum cardinal dir
, char* c
){
568 if(snap
[dir
]) printf("%s", c
);
572 void print_snaps(char snap
[4]){
574 print_dir(snap
, WEST
, "L");
575 print_dir(snap
, NORTH
, "U");
576 print_dir(snap
, SOUTH
, "D");
577 print_dir(snap
, EAST
, "R");
581 void print_stages(stage
** stages
, int w
, int h
){
586 stage
* s
= stages
[j
*w
+ i
];
599 stage
* s
= stages
[j
*w
+ i
];
600 if(s
== NULL
) continue;
602 printf(" stage (%d, %d):\n", i
, j
);
603 printf(" decs: %d\n", length(s
->decs
));
604 print_snaps(s
->snap
);
605 printf(" exit: %p\n", s
->exit
);
612 void print_zone(int id
){
613 zone
* z
= find_zone_by_id(id
);
614 printf("zone: %s\n", z
->name
);
616 printf(" id: %d\n", z
->id
);
617 printf(" dimensions: %d x %d\n", z
->w
, z
->h
);
618 printf(" position: (%d, %d)\n", z
->i
, z
->j
);
619 printf(" fg: %d\n", z
->fgtiles
);
620 printf(" bg: %d\n", z
->bgtiles
);
621 printf(" dec: %d\n", z
->dectiles
);
622 printf(" bgimage: %d\n", z
->bgimage
);
623 printf(" shapes:\n");
624 print_shapes(z
->shapes
);
625 printf(" stages:\n");
626 print_stages(z
->stages
, z
->w
, z
->h
);
631 void stage_bind_camera(location l
, int* x
, int* y
){
632 //for each snap, snap x y
635 void draw_stage_fg(location loc
, int cx
, int cy
){
640 void draw_stage_bg(location loc
, int cx
, int cy
){
641 //for each visible tile
642 //bg or bg tiles or fg tiles
645 /* returns 1 if a collision will occur, 0 otherwise
646 if 1 is returned, x will be set to the collision point */
647 int stage_xcollide(location loc
, int w
, int h
, int v
, int* x
){
648 zone
* z
= find_zone_by_id(loc
.z
);
649 stage
* s
= stage_lookup(z
, loc
.i
, loc
.j
);
650 int X
= loc
.x
+ v
*10; /* FIXME dt */
654 int bottom
= loc
.y
+ h
;
656 block bl
= intersecting_block(s
, left
, right
, top
, bottom
);
658 if(bl
.none
) return 0;
660 *x
= xhit(v
, bl
, top
, bottom
);
665 int stage_ycollide(location loc
, int w
, int h
, int v
, int* y
){