From 79cb33f10ab9ee493233e9ff287307d56361bf0b Mon Sep 17 00:00:00 2001 From: EvanR Date: Sun, 29 Aug 2010 16:17:37 -0500 Subject: [PATCH] Added entities. Rewrote stage, half 'working'. --- Makefile | 2 +- ent0.c | 51 ++ entity.c | 180 ++++++ stage.h => entity.h | 35 +- inner.c | 37 +- stage.c | 1628 ++++++++++++++++++++++++--------------------------- stage.h | 12 +- 7 files changed, 1059 insertions(+), 886 deletions(-) create mode 100644 ent0.c create mode 100644 entity.c copy stage.h => entity.h (54%) rewrite stage.c (61%) diff --git a/Makefile b/Makefile index 69b548a..e451110 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ SRC=video.c audio.c input.c kernel.c main.c gameover.c \ intro.c title.c splash.c inner.c \ synth.c seq.c midi.c orc.c dsp.c \ rng.c util.c list.c zip.c \ - hud.c camera.c testplayer.c + hud.c camera.c entity.c ent0.c OBJ:=$(SRC:.c=.o) CC=gcc LIBS=-lSDL -lGL -lm -lz diff --git a/ent0.c b/ent0.c new file mode 100644 index 0000000..9b97b13 --- /dev/null +++ b/ent0.c @@ -0,0 +1,51 @@ +#include +#include + +#include +#include +#include +#include +#include + +static int update(Y* e){ + e->x = e->x + e->r.a; + e->y = e->y + e->r.b; + e->r.b += 10; + return 0; +} + +static int stage(Y* e, struct stghit hit){ + e->x = hit.x; + e->y = hit.y; +/* if(hit.surface == 0){ + e->r.a = hit.vx * 0.80; + e->r.b = hit.vy * 0; + } + if(hit.surface == 1){ + e->r.a = hit.vx * 0.5; + e->r.b = hit.vy; + } + if(hit.surface == 2){ + e->r.a = hit.vx; + e->r.b = 0; + }*/ + e->r.a = hit.vx; + e->r.b = hit.vy * 0.1; + return 0; +} + +/* make an entity that moves in a circular path */ +Y* mk_ent0(){ + Y* e = mk_dummy_ent(16*14*1024,16*3*1024); + e->update = update; + e->stage = stage; + e->r.a = 0; + e->r.b = 0; + e->box.w = 8; + e->box.h = 8; + e->box.w *= 1024; + e->box.h *= 1024; + return e; +} + + diff --git a/entity.c b/entity.c new file mode 100644 index 0000000..e3cbc11 --- /dev/null +++ b/entity.c @@ -0,0 +1,180 @@ +#include +#include + +#include +#include +#include +#include +#include + + +extern Y* mk_ent0(void); + +#define MAX_PLAYERS 4 +#define MAX_ENTS 128 + +static Y* entities[MAX_ENTS]; +static struct {int x, y;} ent_v[MAX_ENTS]; +static int next_ent = MAX_PLAYERS; + + + +int inside_rect(int x, int y, int x0, int y0, int x1, int y1){ + return !(x < x0 || x > x1 || y < y0 || y > y1); +} + +int rects_overlap(rect r1, rect r2){ + return !( + r1.x > r2.x + r2.w || + r2.x > r1.x + r1.w || + r1.y > r2.y + r2.h || + r2.y > r1.y + r1.h + ); +} + + + +int update_noop(Y* e){ + return 0; +} + +int stage_noop(Y* e, struct stghit hit){ + return 0; +} + +int overlap_noop(Y* e, Y* f){ + return 0; +} + +int diverge_noop(Y* e, Y* f){ + return 0; +} +static void find_visible_ents(int ents[], int* count){ + +} + +void entity_master_simulate(){ + int visible_ents[MAX_ENTS]; + int visible_count = 0; + + find_visible_ents(visible_ents, &visible_count); + + { + Y* e = entities[0]; + int x0 = e->x; + int y0 = e->y; + int vx; + int vy; + int w = e->box.w; + int h = e->box.h; + struct stghit hit; + + e->update(e); + + vx = e->x - x0; + vy = e->y - y0; + + hit = stage_collide_rect( + e->x, e->y, + w, h, + vx, vy + ); + + if(hit.yes){ + e->stage(e, hit); + } + } + + /* for all pairs, if overlapping do events */ + /* for all overlaps, if not overlapping do events */ + /* for all in screen, move and record v */ + /* for all in screen, stage collision */ +} + +void draw_entities(){ + int i; + Y* e; + for(i=0; ix/1024, e->y/1024, 16, 0, 8, 8); + } + } +} + +void setup_test_entities(){ + int i; + for(i=0; ir.a = -1000; break; + case RIGHT_BUTTON: e->r.a = 1000; break; + case UP_BUTTON: e->r.b = -1000; break; + case DOWN_BUTTON: e->r.b = 1000; break; + case FIRE_BUTTON: stage_debug(); break; + default: break; + } +} + +void player_release(int player, enum input_button button){ + Y* e = entities[0]; + switch(button){ + case LEFT_BUTTON: e->r.a = 0; break; + case RIGHT_BUTTON: e->r.a = 0; break; +// case UP_BUTTON: e->r.b = 0; break; +// case DOWN_BUTTON: e->r.b = 0; break; + default: break; + } +} + +/* +struct entity { + int x; int y; spatial + int z; z order + unsigned flbits; common class + int gfx; image + struct {int a,b,c,d,e,f;} r; + struct {int x, y, w, h;} box; used to detect collision + int (*update)(Y*); + int (*stage)(Y*,int,int); + int (*overlap)(Y*,Y*); + int (*diverge)(Y*,Y*); +}; +*/ + +Y* mk_dummy_ent(int x, int y){ + memory clear_r = {0,0,0,0,0,0}; + rect standard = {0,0,16,16}; + Y* ent = malloc(sizeof(Y)); + ent->x = x; + ent->y = y; + ent->z = 0; + ent->flbits = 0; + ent->gfx = 0; + ent->r = clear_r; + ent->box = standard; + ent->update = update_noop; + ent->stage = stage_noop; + ent->overlap = overlap_noop; + ent->diverge = diverge_noop; + return ent; +} + + + + +int mini_rand(int g){ + return (g*9 + 171) % 256; +} + + + + + diff --git a/stage.h b/entity.h similarity index 54% copy from stage.h copy to entity.h index b909ba0..f7489bc 100644 --- a/stage.h +++ b/entity.h @@ -18,18 +18,37 @@ The Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA + + evanrinehart@gmail.com */ +typedef struct entity Y; +typedef struct {int x,y,w,h;} rect; +typedef struct {int a,b,c,d,e,f;} memory; + +struct entity { + int x; int y; /* spatial */ + int z; /* z order */ + int flbits; /* flag bits */ + int gfx; /* image */ + memory r; /* general registers */ + rect box; /* used to detect collision */ + int (*update)(Y*); + int (*stage)(Y*,struct stghit); + int (*overlap)(Y*,Y*); + int (*diverge)(Y*,Y*); +}; + +void draw_entities(void); +void setup_test_entities(void); +void entity_master_simulate(void); + +void player_press(int player, enum input_button button); +void player_release(int player, enum input_button button); -int load_zone(string filename); -void unload_zone(void); -void stage_debug(void); +Y* mk_dummy_ent(int x, int y); +int mini_rand(int g); -void switch_stage(string id); -void stage_draw_fg(int cx, int cy); -void stage_draw_bg(int cx, int cy); -int stage_xcollide(int x, int y, int w, int h, int v, int* xx); -int stage_ycollide(int x, int y, int w, int h, int v, int* yy); diff --git a/inner.c b/inner.c index c64642f..c80f8bb 100644 --- a/inner.c +++ b/inner.c @@ -8,22 +8,19 @@ #include #include -//#include +#include +#include #include #include #include -#include #include #include #include -#include -//typedef struct player player; -static player* pl = NULL; static void update(){ /* @@ -33,27 +30,10 @@ static void update(){ execute spawn and delete events */ - int xx; - int yy; - int x0 = pl->x; - int y0 = pl->y; - int x1; - int y1; - update_player(pl); - x1 = pl->x; - y1 = pl->y; - - if(stage_xcollide(x0, y0, pl->w, pl->h, x1-x0, &xx)){ - collide_x(pl, xx); - x1 = pl->x; - } + entity_master_simulate(); - if(stage_ycollide(x1, y0, pl->w, pl->h, y1-y0, &yy)){ - collide_y(pl, yy); - } - } static void draw(){ @@ -61,8 +41,9 @@ static void draw(){ //entity_draw_visible(cx, cy); stage_draw_fg(0, 0); // draw_gfx(dummy_gfx,px,py,16,0,8,8); - draw_player(pl); +// draw_player(pl); //hud_draw(cx, cy); + draw_entities(); } @@ -73,11 +54,11 @@ static void press(input in){ return; } - player_press(pl, in.button); + player_press(in.player, in.button); } static void release(input in){ - player_release(pl, in.button); + player_release(in.player, in.button); } void setup_inner(){ @@ -85,7 +66,9 @@ void setup_inner(){ console_clear(); set_handler(update, draw, press, release); - pl = mk_test_player(16*3,4*16); + + setup_test_entities(); + unload_zone(); int x = load_zone("woods"); diff --git a/stage.c b/stage.c dissimilarity index 61% index 9f1c137..3667bb9 100644 --- a/stage.c +++ b/stage.c @@ -1,848 +1,780 @@ -/* - Cantaveria - action adventure platform game - Copyright (C) 2009 2010 Evan Rinehart - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to - - The Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor - Boston, MA 02110-1301, USA -*/ - - -/* -stage module is responsible for modelling the static world. -it has three main functions -* load zone files into world -* draw world background and foreground layers -* calculate if and where a moving rectangle will collide with world -*/ - - - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - - - -enum tile_shape { -SHAPE_FREE = '0', /* 'air' */ -SHAPE_SQUARE = 'M', - -SHAPE_TRI_NE = 'a', -SHAPE_TRI_NW = 'b', -SHAPE_TRI_SE = 'c', -SHAPE_TRI_SW = 'd', - -SHAPE_LTRAP_FLOOR = '1', /* trapezoid */ -SHAPE_RTRAP_FLOOR = '2', -SHAPE_LSLOPE_FLOOR = '3', -SHAPE_RSLOPE_FLOOR = '4', -SHAPE_LTRAP_CEIL = '5', -SHAPE_RTRAP_CEIL = '6', -SHAPE_LSLOPE_CEIL = '7', -SHAPE_RSLOPE_CEIL = '8', - -SHAPE_HALF_FLOOR = 'm', -SHAPE_HALF_CEIL = 'w' -}; - -typedef struct { - unsigned char bg; - unsigned char fg; - unsigned char shape; -} tile; - -typedef struct stage stage; -struct stage { - char id[256]; - int w, h; - tile* tiles; - int bgimage; - int bgtiles; - int fgtiles; - int ox, oy; - stage* next; -}; - -char zone_name[256] = "NO ZONE"; -stage* stages = NULL; -stage* this_stage = NULL; - -/***/ - - -/* -STAGE MODULE - -DEADLINES AND MILESTONES - -load zones / stages from new format - May 15 -display loaded stages - May 22 -collision algorithm - May 29 - -*/ - - - -/*** collision stuff ***/ - -#define UUU(x) (1024*(x)) -#define DDD(x) ((x)/1024) - -/* does a corner test. -x y is the point of the corner -xp yp is the direction of the rectangle relative to the corner */ -static int corner_overlap(int x, int y, int xp, int yp, char shape){ - const int L = UUU(16); - switch(shape){ - case SHAPE_FREE: return 0; - case SHAPE_SQUARE: return 1; - - case SHAPE_TRI_NE: - if(xp<0 && yp>0) return y0 && yp>0) return yL-x; - else return 1; - case SHAPE_TRI_SW: - if(xp>0 && yp<0) return y>x; - else return 1; - - case SHAPE_LTRAP_FLOOR: - if(xp>0 && yp<0) return y>(x/2); - else return 1; - case SHAPE_RTRAP_FLOOR: - if(xp<0 && yp<0) return y>(L/2-x/2); - else return 1; - case SHAPE_LSLOPE_FLOOR: - if(xp>0 && yp<0) return y>(L/2+x/2); - else if(xp<0 && yp<0) return y>L/2; - else return 1; - case SHAPE_RSLOPE_FLOOR: - if(xp<0 && yp<0) return y>(L-x/2); - else if(xp>0 && yp<0) return y>L/2; - else return 1; - case SHAPE_LTRAP_CEIL: - if(xp>0 && yp>0) return y<(L-x/2); - else return 1; - case SHAPE_RTRAP_CEIL: - if(xp<0 && yp>0) return y<(L/2+x/2); - else return 1; - case SHAPE_LSLOPE_CEIL: - if(xp>0 && yp>0) return y<(L/2-x/2); - else if(xp<0 && yp>0) return y0) return y<(x/2); - else if(xp>0 && yp>0) return y 0 || y > L/2; - case SHAPE_HALF_CEIL: return yp < 0 || y < L/2; - default: return 0; - } -} - -/* calculate the collision point given a relevant cross -section and direction of motion. */ -static int x_trace(int y, int v, int shape){ - const int L = UUU(16); - switch(shape){ - case SHAPE_FREE: return 0; /* should not happen */ - case SHAPE_SQUARE: - case SHAPE_HALF_FLOOR: - case SHAPE_HALF_CEIL: return v>0 ? 0 : L; - case SHAPE_TRI_NE: return v>0 ? y : L; - case SHAPE_TRI_NW: return v>0 ? 0 : L-y; - case SHAPE_TRI_SE: return v>0 ? L-y : L; - case SHAPE_TRI_SW: return v>0 ? 0 : y; - case SHAPE_LTRAP_FLOOR: return v>0 ? 0 : 2*y; - case SHAPE_RTRAP_FLOOR: return v>0 ? L - 2*y : 0; - case SHAPE_LSLOPE_FLOOR: return v>0 ? 0 : 2*y - L; - case SHAPE_RSLOPE_FLOOR: return v>0 ? 2*L -2*y : L; - case SHAPE_LTRAP_CEIL: return v<0 ? 2*L - 2*y : L; - case SHAPE_RTRAP_CEIL: return v>0 ? 2*y - L : L; - case SHAPE_LSLOPE_CEIL: return v>0 ? 0 : L - 2*y; - case SHAPE_RSLOPE_CEIL: return v>0 ? 2*y : L; - default: return 0; - } -} - -static int y_trace(int x, int v, int shape){ - const int L = UUU(16); - switch(shape){ - case SHAPE_FREE: return 0; /* should not happen */ - case SHAPE_SQUARE: return v>0 ? 0 : L; - case SHAPE_HALF_FLOOR: return v>0 ? L/2 : L; - case SHAPE_HALF_CEIL: return v>0 ? 0 : L/2; - case SHAPE_TRI_NE: return v>0 ? 0 : x; - case SHAPE_TRI_NW: return v>0 ? 0 : L-x; - case SHAPE_TRI_SE: return v>0 ? L-x : 0; - case SHAPE_TRI_SW: return v>0 ? x : 0; - case SHAPE_LTRAP_FLOOR: return v>0 ? x/2 : L; - case SHAPE_RTRAP_FLOOR: return v>0 ? L/2 - x/2 : L; - case SHAPE_LSLOPE_FLOOR: return v>0 ? L/2 + x/2 : L; - case SHAPE_RSLOPE_FLOOR: return v>0 ? L - x/2 : L; - case SHAPE_LTRAP_CEIL: return v>0 ? 0 : L - x/2; - case SHAPE_RTRAP_CEIL: return v>0 ? 0 : L/2 + x/2; - case SHAPE_LSLOPE_CEIL: return v>0 ? 0 : L/2 - x/2; - case SHAPE_RSLOPE_CEIL: return v>0 ? 0 : x/2; - default: return 0; - } -} - -/* polarity functions -these help the top level collision tests by determining -which side of the rectangle needs to be traced. see x_trace. */ -static int y_polarity(int y_0, int y_1, int shape){ - switch(shape){ - case SHAPE_FREE: return y_0; - case SHAPE_SQUARE: return y_0; - case SHAPE_TRI_NE: return y_0; - case SHAPE_TRI_NW: return y_0; - case SHAPE_TRI_SE: return y_1; - case SHAPE_TRI_SW: return y_1; - case SHAPE_LTRAP_FLOOR: return y_1; - case SHAPE_RTRAP_FLOOR: return y_1; - case SHAPE_LSLOPE_FLOOR: return y_1; - case SHAPE_RSLOPE_FLOOR: return y_1; - case SHAPE_LTRAP_CEIL: return y_0; - case SHAPE_RTRAP_CEIL: return y_0; - case SHAPE_LSLOPE_CEIL: return y_0; - case SHAPE_RSLOPE_CEIL: return y_0; - case SHAPE_HALF_FLOOR: return y_0; - case SHAPE_HALF_CEIL: return y_0; - default: return y_0; - } -} - -static int x_polarity(int x_0, int x_1, int shape){ - switch(shape){ - case SHAPE_FREE: return x_0; - case SHAPE_SQUARE: return x_0; - case SHAPE_TRI_NE: return x_1; - case SHAPE_TRI_NW: return x_0; - case SHAPE_TRI_SE: return x_1; - case SHAPE_TRI_SW: return x_0; - case SHAPE_LTRAP_FLOOR: return x_0; - case SHAPE_RTRAP_FLOOR: return x_1; - case SHAPE_LSLOPE_FLOOR: return x_0; - case SHAPE_RSLOPE_FLOOR: return x_1; - case SHAPE_LTRAP_CEIL: return x_0; - case SHAPE_RTRAP_CEIL: return x_1; - case SHAPE_LSLOPE_CEIL: return x_0; - case SHAPE_RSLOPE_CEIL: return x_1; - case SHAPE_HALF_FLOOR: return x_0; - case SHAPE_HALF_CEIL: return x_0; - default: return x_0; - } -} - -/* -return the corner tiles of the test rectangle in id. -if all corners are the same, return 0 -if all corners are different, return 3 -if the top two (and bottom two) are the same, return 2 -if the left two (and right two) are the same, return 1 -*/ -static int calc_corners(int x, int y, int w, int h, int id[4]){ - int W = this_stage->w; - - int x1 = DDD(x)/16; - int x2 = DDD(x+w)/16; - int y1 = DDD(y)/16; - int y2 = DDD(y+h)/16; - - id[0] = x1+y1*W; - id[1] = x2+y1*W; - id[2] = x1+y2*W; - id[3] = x2+y2*W; - - /* single tile test */ - if(id[0] == id[1] && id[0] == id[2] && - id[0] == id[2] && id[0] == id[3]) return 0; - - /* line of tile tests */ - if(id[0] == id[1]) return 2; - if(id[1] == id[3]) return 3; - - /* at least 4 tile tests */ - return 1; -} - - -/* collision algorithm -strategy: if the rectangle adjusted by v overlaps something in -the stage, return 1 and set *xx or *yy to the collision point. - -current holes: -for a large rectangle, it only tests the corners. it should -also do edge test or middle test on none corner (but not inner) -tiles. - -the x collide and y collide are almost the same thing. it might -be possible to combine them into one function. - -*/ - -int stage_xcollide(int x, int y, int w, int h, int v, int* xx){ - int corners[4]; - int type = calc_corners(x+v,y,w,h,corners); -// int x_min = INT_MAX; -// int x_max = INT_MIN; - int L = UUU(16); - int xbase = (x+v) / L * L; - int x_ = (x+v) % L; - int y_ = y % L; - int yz; - tile* t = NULL; - - if(v == 0) return 0; - - if(type==0){ - t = this_stage->tiles + corners[0]; - if(corner_overlap(x_,y_,1,1,t->shape) && - corner_overlap(x_+w,y_,-1,1,t->shape) && - corner_overlap(x_,y_+h,1,-1,t->shape) && - corner_overlap(x_+w,y_+h,-1,-1,t->shape)) - { - yz = y_polarity(y_,y_+h,t->shape); - *xx = xbase+x_trace(yz,v,t->shape); - return 1; - } - else{ - return 0; - } - } - else if(type==2){ - t = this_stage->tiles + corners[0]; /* and 1 */ - if(corner_overlap(x_,y_,1,1,t->shape) && - corner_overlap(x_+w,y_,-1,1,t->shape)) - { - yz = y_polarity(y_,L,t->shape); - *xx = xbase+x_trace(yz,v,t->shape); - return 1; - } - - y_ = (y+h) % L; - t = this_stage->tiles + corners[2]; /* and 3 */ - if(corner_overlap(x_,y_,1,-1,t->shape) && - corner_overlap(x_+w,y_,-1,-1,t->shape)) - { - yz = y_polarity(0,y_,t->shape); - *xx = xbase+x_trace(yz,v,t->shape); - return 1; - } - - /* also check middle edge */ - - return 0; - } - else if(type==3){ - t = this_stage->tiles + corners[0]; /* and 2 */ - if(corner_overlap(x_,y_,1,1,t->shape) && - corner_overlap(x_,y_+h,1,-1,t->shape)) - { - yz = y_polarity(y_,y_+h,t->shape); - *xx = xbase+x_trace(yz,v,t->shape); - return 1; - } - - xbase = (x+v+w) / L * L; - x_ = (x+v+w) % L; - t = this_stage->tiles + corners[1]; /* and 3 */ - if(corner_overlap(x_,y_,-1,1,t->shape) && - corner_overlap(x_,y_+h,-1,-1,t->shape)) - { - yz = y_polarity(y_,y_+h,t->shape); - *xx = xbase+x_trace(yz,v,t->shape); - return 1; - } - - /* also check middle edge */ - - return 0; - } - else if(type==1){ - t = this_stage->tiles + corners[0]; - if(corner_overlap(x_,y_,1,1,t->shape)){ - yz = y_polarity(y_,L,t->shape); - *xx = xbase+x_trace(yz,v,t->shape); - return 1; - } - - y_ = (y+h)%L; - t = this_stage->tiles + corners[2]; - if(corner_overlap(x_,y_,1,-1,t->shape)){ - yz = y_polarity(0,y_,t->shape); - *xx = xbase+x_trace(yz,v,t->shape); - return 1; - } - - xbase = (x+v+w) / L * L; - x_ = (x+v+w) % L; - y_ = y % L; - t = this_stage->tiles + corners[1]; - if(corner_overlap(x_,y_,-1,1,t->shape)){ - yz = y_polarity(y_,L,t->shape); - *xx = xbase+x_trace(yz,v,t->shape); - return 1; - } - - y_ = (y+h)%L; - t = this_stage->tiles + corners[3]; - if(corner_overlap(x_,y_,-1,-1,t->shape)){ - yz = y_polarity(0,y_,t->shape); - *xx = xbase+x_trace(yz,v,t->shape); - return 1; - } - /* check all edges and inside */ - - return 0; - } - else{ - return 0; - } -} - -int stage_ycollide(int x, int y, int w, int h, int v, int* yy){ - int corners[4]; - int type = calc_corners(x,y+v,w,h,corners); -// int x_min = INT_MAX; -// int x_max = INT_MIN; - int L = UUU(16); - int ybase = (y+v) / L * L; - int y_ = (y+v) % L; - int x_ = x % L; - int xz; - tile* t = NULL; - - if(v == 0) return 0; - - if(type==0){ - t = this_stage->tiles + corners[0]; - if(corner_overlap(x_,y_,1,1,t->shape) && - corner_overlap(x_+w,y_,-1,1,t->shape) && - corner_overlap(x_,y_+h,1,-1,t->shape) && - corner_overlap(x_+w,y_+h,-1,-1,t->shape)) - { - xz = x_polarity(x_,x_+w,t->shape); - *yy = ybase+y_trace(xz,v,t->shape); - return 1; - } - else{ - return 0; - } - } - else if(type==2){ - t = this_stage->tiles + corners[0]; /* and 1 */ - if(corner_overlap(x_,y_,1,1,t->shape) && - corner_overlap(x_+w,y_,-1,1,t->shape)) - { - xz = x_polarity(x_,x_+w,t->shape); - *yy = ybase+y_trace(xz,v,t->shape); - return 1; - } - - ybase = (y+v+h) / L * L; - y_ = (y+v+h) % L; - t = this_stage->tiles + corners[2]; /* and 3 */ - if(corner_overlap(x_,y_,1,-1,t->shape) && - corner_overlap(x_+w,y_,-1,-1,t->shape)) - { - xz = x_polarity(x_,x_+w,t->shape); - *yy = ybase+y_trace(xz,v,t->shape); - return 1; - } - - /* also check middle edge */ - - return 0; - } - else if(type==3){ - t = this_stage->tiles + corners[0]; /* and 2 */ - if(corner_overlap(x_,y_,1,1,t->shape) && - corner_overlap(x_,y_+h,1,-1,t->shape)) - { - xz = x_polarity(x_,L,t->shape); - *yy = ybase+y_trace(xz,v,t->shape); - return 1; - } - - x_ = (x+w) % L; - t = this_stage->tiles + corners[1]; /* and 3 */ - if(corner_overlap(x_,y_,-1,1,t->shape) && - corner_overlap(x_,y_+h,-1,-1,t->shape)) - { - xz = x_polarity(0,x_,t->shape); - *yy = ybase+y_trace(xz,v,t->shape); - return 1; - } - - /* also check middle edge */ - - return 0; - } - else if(type==1){ - t = this_stage->tiles + corners[0]; - if(corner_overlap(x_,y_,1,1,t->shape)){ - xz = x_polarity(x_,L,t->shape); - *yy = ybase+y_trace(xz,v,t->shape); - return 1; - } - - x_ = (x+w)%L; - t = this_stage->tiles + corners[1]; - if(corner_overlap(x_,y_,-1,1,t->shape)){ - xz = x_polarity(0,x_,t->shape); - *yy = ybase+y_trace(xz,v,t->shape); - return 1; - } - - ybase = (y+v+h) / L * L; - y_ = (y+v+h) % L; - x_ = x % L; - t = this_stage->tiles + corners[2]; - if(corner_overlap(x_,y_,1,-1,t->shape)){ - xz = x_polarity(x_,L,t->shape); - *yy = ybase+y_trace(xz,v,t->shape); - return 1; - } - - x_ = (x+w)%L; - t = this_stage->tiles + corners[3]; - if(corner_overlap(x_,y_,-1,-1,t->shape)){ - xz = x_polarity(0,x_,t->shape); - *yy = ybase+y_trace(xz,v,t->shape); - return 1; - } - - /* check all edges and inside */ - - return 0; - } - else{ - return 0; - } -} - - - - -/*** end collision stuff ***/ - - - - -static void initialize_tiles(int n, tile* tiles){ - int i; - for(i=0; ibgimage = load_bitmap(gfx); - - loader_scanline(f, "%s", buf); - strcpy(gfx, gfxpath); - strcat(gfx, buf); - s->bgtiles = load_bitmap(gfx); - - loader_scanline(f, "%s", buf); - strcpy(gfx, gfxpath); - strcat(gfx, buf); - s->fgtiles = load_bitmap(gfx); - - s->tiles = malloc(w*h*sizeof(tile)); - initialize_tiles(w*h, s->tiles); - s->w = w; - s->h = h; - s->ox = ox; - s->oy = oy; - strncpy(s->id, filename, 256); - s->id[255] = '\0'; - - while(!loader_feof(f)){ - loader_scanline(f, "%d %d %d %d %c", &x, &y, &fg, &bg, &shape); - tptr = s->tiles + (x+ox) + (s->w * (y+oy)); - tptr->fg = fg; - tptr->bg = bg; - tptr->shape = shape; - } - - s->next = stages; - stages = s; - - loader_close(f); - return 0; -} - -/***/ - - -int load_zone(string name){ - /* -loading a zone from a file -a zone consists of one or more stages -each stage has its own tileset graphics and background -it also has a large array of tiles - -the stage files are in zones/zonename/ -the name of the file will be used as the id - */ - - list* dirs; - list* ptr; - char stagesdir[256] = ""; - char gfxpath[256] = ""; - char* stagepath; - - strcat(stagesdir, "zones/"); - strcat(stagesdir, name); - strcat(stagesdir, "/stages/"); - - strcat(gfxpath, "zones/"); - strcat(gfxpath, name); - strcat(gfxpath, "/gfx/"); - - strncpy(zone_name, name, 256); - zone_name[255] = '\0'; - - dirs = loader_readdir((string)stagesdir); - if(dirs == NULL){ - printf("ERROR cant read dirs\n"); - return -1; - } - - ptr = dirs->next; - while(ptr){ - stagepath = ptr->item; - if(load_stage(gfxpath, stagepath) < 0){ - printf("ERROR cant load stage\n"); - loader_freedirlist(dirs); - return -1; - } - ptr = ptr->next; - } - - loader_freedirlist(dirs); - return 0; -} - -void unload_zone(){ - stage* ptr = stages; - stage* prev; - while(ptr){ - free(ptr->tiles); - prev = ptr; - ptr = ptr->next; - free(prev); - } - - strcpy(zone_name, "NO ZONE"); -} - -void switch_stage(string id){ - stage* ptr = stages; - while(ptr){ - if(strcmp(id, ptr->id) == 0){ - this_stage = ptr; - return; - } - ptr = ptr->next; - } - - printf("ERROR stage not found\n"); -} - - -static void draw_tiles(int gfx, char layer, int cx, int cy){ - tile* tbase = this_stage->tiles; - tile* t; - int tw = this_stage->w; - int th = this_stage->h; - int id; - int gx, gy; - - int i; - int j; - int io = cx/16; - int jo = cy/16; - int i_ = io + 20; - int j_ = jo + 15; - - int extra_x = 0; - int extra_y = 0; - int W, H; - screen_dimensions(&W, &H); - if(W>320){ - extra_x = (W - 320)/16/2 + 2; - } - if(H>240){ - extra_y = (H - 240)/16/2 + 2; - } - - io -= extra_x; - jo -= extra_y; - i_ += extra_x; - j_ += extra_y+1; - - if(io > tw-1) return; - if(jo > th-1) return; - - if(io < 0) io = 0; - if(jo < 0) jo = 0; - if(i_ > tw) i_ = tw; - if(j_ > th) j_ = th; - - for(j=jo; jbg; - else if(layer=='f') id = t->fg; - else id = 0; - gx = 16*(id%16); - gy = 16*(id/16); - draw_gfx(gfx, i*16-cx, j*16-cy, gx, gy, 16, 16); - } - } -} - -/* -cx, cy is the camera position -x, y i think is the offset from 0,0 you should shift -w, h i think is the width and height of the screen -*/ -void stage_draw_bg(int cx, int cy){ - int i; - int bw, bh, screen_w, screen_h; - int bgimage; - int bgshift; - int parallax = 2; - - if(this_stage == NULL) return; - - /* draw background vertically centered - tile horizontally at fraction of camera x */ - bgimage = this_stage->bgimage; - gfx_dimensions(bgimage, &bw, &bh); - screen_dimensions(&screen_w, &screen_h); - bgshift = cx/parallax/bw; - for(i=-1; i<(screen_w/bw)+2; i++){ - draw_gfx_raw( - bgimage, - (i+bgshift)*bw-cx/parallax, - (screen_h-bh)/2, - 0, 0, bw, bh - ); - } - - draw_tiles(this_stage->bgtiles, 'b', cx, cy); -} - -void stage_draw_fg(int cx, int cy){ - draw_tiles(this_stage->bgtiles, 'f', cx, cy); -} - - - - -void stage_init(){ - /* does nothing */ -} - - - - - -/*** debug ***/ - -void stage_debug(){ - stage* ptr = stages; - int i, j; - char c; - - printf("stage debug:\n\n"); - printf("zone: %s\n\n", zone_name); - - while(ptr){ - printf("stage: %s\n", ptr->id); - printf("size: %dx%d\n", ptr->w, ptr->h); - printf("origin: (%d, %d)\n", ptr->ox, ptr->oy); - printf("bgimage: %d\n", ptr->bgimage); - printf("bgtiles: %d\n", ptr->bgtiles); - printf("fgtiles: %d\n", ptr->fgtiles); - printf("tiles:\n"); - - for(j=0; jh; j++){ - for(i=0; iw; i++){ - c = (ptr->tiles + i + ptr->w*j)->fg; - /* - if(isprint(c)) printf("%d", c); - else printf("?");*/ - printf("[%02x]", c); - } - printf("\n"); - } - - - printf("\n"); - ptr = ptr->next; - } -} +/* + Cantaveria - action adventure platform game + Copyright (C) 2009 2010 Evan Rinehart + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to + + The Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor + Boston, MA 02110-1301, USA +*/ + + +/* +stage module is responsible for modelling the static world. +it has three main functions +* load zone files into world +* draw world background and foreground layers +* calculate if and where a moving rectangle will collide with world +*/ + + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + + +enum tile_shape { +SHAPE_FREE = '0', /* 'air' */ +SHAPE_SQUARE = 'M', + +SHAPE_TRI_NE = 'a', +SHAPE_TRI_NW = 'b', +SHAPE_TRI_SE = 'c', +SHAPE_TRI_SW = 'd', + +SHAPE_LTRAP_FLOOR = '1', /* trapezoid */ +SHAPE_RTRAP_FLOOR = '2', +SHAPE_LSLOPE_FLOOR = '3', +SHAPE_RSLOPE_FLOOR = '4', +SHAPE_LTRAP_CEIL = '5', +SHAPE_RTRAP_CEIL = '6', +SHAPE_LSLOPE_CEIL = '7', +SHAPE_RSLOPE_CEIL = '8', + +SHAPE_HALF_FLOOR = 'm', +SHAPE_HALF_CEIL = 'w' +}; + +typedef struct stghit Q; + +typedef struct { + unsigned char bg; + unsigned char fg; + unsigned char shape; + unsigned char config; /* maintest | sideconfig */ +} tile; + +typedef struct stage stage; +struct stage { + char id[256]; + int w, h; + tile* tiles; + int bgimage; + int bgtiles; + int fgtiles; + int ox, oy; + stage* next; +}; + +typedef Q (*test)(int x, int y, int vx, int vy); + +static test maintests[16]; +static test sidetests[4]; + +char zone_name[256] = "NO ZONE"; +stage* stages = NULL; +stage* this_stage = NULL; + +#define SIN26(X) ((X) * 458 / 1024) +#define COS26(X) ((X) * 916 / 1024) +#define SIN45(X) ((X) * 724 / 1024) +#define COS45(X) ((X) * 724 / 1024) +#define UUU(X) ((X) * 1024) +#define DDD(X) ((X) / 1024) + +static const int L = UUU(16); +static const struct stghit nohit = {0,0,0,0,0,0,0}; + + +static unsigned char pack_config(int maintest, int sideconfig){ + return (maintest << 4) | sideconfig; +} + +static void unpack_config(unsigned char config, int* mtout, int* scout){ + *scout = config & 0x0f; + *mtout = (config & 0xf0) >> 4; +} + +static void get_sidetests(int sideconfig, test tests[3]){ + int i = 0; + int sc = sideconfig; + tests[0] = NULL; + tests[1] = NULL; + tests[2] = NULL; + + if(sc==0xf) { + printf("stage: problem with tile config\n"); + return; + } + + if(sc&1) tests[i++]=sidetests[0]; + if(sc&2) tests[i++]=sidetests[1]; + if(sc&4) tests[i++]=sidetests[2]; + if(sc&8) tests[i++]=sidetests[3]; +} + + + +static int min4(int a, int b, int c, int d){ + int m = INT_MAX; + if(a < m) m = a; + if(b < m) m = b; + if(c < m) m = c; + if(d < m) m = d; + return m; +} + +static int min3(int a, int b, int c){ + int m = INT_MAX; + if(a < m) m = a; + if(b < m) m = b; + if(c < m) m = c; + return m; +} + +static int max4(int a, int b, int c, int d){ + int m = INT_MIN; + if(a > m) m = a; + if(b > m) m = b; + if(c > m) m = c; + if(d > m) m = d; + return m; +} + +static struct stghit mkhit(int x, int y, int vx, int vy, int s, int z){ + struct stghit hit; + hit.yes = 1; + hit.x = x; + hit.y = y; + hit.vx = vx; + hit.vy = vy; + hit.surface = s; + hit.depth = z; + return hit; +} + + +static Q st_left(int x, int y, int vx, int vy){ + return mkhit(-1,y,-vx,vy,1,x); +} +static Q st_right(int x, int y, int vx, int vy){ + return mkhit(L,y,-vx,vy,1,L-x); +} +static Q st_top(int x, int y, int vx, int vy){ + return mkhit(x,-1,vx,-vy,0,y); +} +static Q st_bottom(int x, int y, int vx, int vy){ + return mkhit(x,L,vx,-vy,2,L-y); +} + + + + +static Q mt_square(int x, int y, int vx, int vy){ + int z1,z2,z3,z4,z; + int xx, yy, vvx, vvy; + z1 = x; + z2 = y; + z3 = L - x; + z4 = L - y; + z = min4(z1,z2,z3,z4); + if(z == z1) return mkhit(-1,y,-vx,vy,1,z); + if(z == z2) return mkhit(x,-1,vx,-vy,0,z); + if(z == z3) return mkhit(L,y,-vx,vy,1,z); + if(z == z4) return mkhit(x,L,vx,-vy,2,z); + return nohit; +} + +static Q mt_half_floor(int x, int y, int vx, int vy){ + if(y < L/2) return nohit; + else return mkhit(x,L/2,vx,-vy,0,y-L/2); +} + +static Q mt_half_ceil(int x, int y, int vx, int vy){ + if(y > L/2) return nohit; + else return mkhit(x,L/2,vx,-vy,0,L/2-y); +} + + +static Q mt_ltrap_floor(int x, int y, int vx, int vy){ + int dot, z; + if(y < x/2) return nohit; + z = COS26(y - x/2); + dot = SIN26(vx) - COS26(vy); + return mkhit( + x + SIN26(z), + y - COS26(z), + vx - SIN26(2 * dot), + vy - -COS26(2 * dot), + 0, + z + ); +} +static Q mt_rtrap_floor(int x, int y, int vx, int vy){ + return nohit; +} + +static Q mt_ltrap_ceil(int x, int y, int vx, int vy){ + return nohit; +} + +static Q mt_rtrap_ceil(int x, int y, int vx, int vy){ + return nohit; +} + +static Q mt_lslope_floor(int x, int y, int vx, int vy){ + int dot, z; + if(y < x/2 + L/2) return nohit; + z = COS26(y - x/2 - L/2); + dot = SIN26(vx) - COS26(vy); + return mkhit( + x + SIN26(z), + y - COS26(z), + vx - SIN26(2 * dot), + vy - -COS26(2 * dot), + 0, + z + ); +} +static Q mt_rslope_floor(int x, int y, int vx, int vy){ + return nohit; +} + +static Q mt_lslope_ceil(int x, int y, int vx, int vy){ + return nohit; +} + +static Q mt_rslope_ceil(int x, int y, int vx, int vy){ + return nohit; +} + + +static Q mt_triangle_ne(int x, int y, int vx, int vy){ + return nohit; +} + +static Q mt_triangle_nw(int x, int y, int vx, int vy){ + return nohit; +} + +static Q mt_triangle_se(int x, int y, int vx, int vy){ + return nohit; +} + +static Q mt_triangle_sw(int x, int y, int vx, int vy){ + int z,dot; + if(y < x) return nohit; + z = COS45(y - x); + dot = SIN45(vx) - COS45(vy); + return mkhit( + x + COS45(z), + y - SIN45(z), + vx - COS45(2 * dot), + vy - -SIN45(2 * dot), + 0, + z + ); +} + +static Q nulltest(int x, int y, int vx, int vy){ + return nohit; +} + + +static Q general_test( + int x, int y, int vx, int vy, + test maintest, test side1, test side2, test side3 +) { + int sides = 3; + int z0,z1,z2,z3,z; + Q hit0 = maintest(x,y,vx,vy); + Q hit1, hit2, hit3; + if(!hit0.yes) return nohit; + if(side3 == NULL) sides -= 1; + if(side2 == NULL) sides -= 1; + if(side1 == NULL) sides -= 1; + + z0 = hit0.depth; + if(side1) {hit1 = side1(x,y,vx,vy); z1 = hit1.depth;} + if(side2) {hit2 = side2(x,y,vx,vy); z2 = hit2.depth;} + if(side3) {hit3 = side3(x,y,vx,vy); z3 = hit3.depth;} + + if(sides == 0) return hit0; + if(sides == 1){ + if(z0 < z1) return hit0; + else return hit1; + } + if(sides == 2){ + z = min3(z0,z1,z2); + if(z==z0) return hit0; + if(z==z1) return hit1; + if(z==z2) return hit2; + printf("stage: general test is broken (code 2)\n"); + return nohit; + } + if(sides == 3){ + z = min4(z0,z1,z2,z3); + if(z==z0) return hit0; + if(z==z1) return hit1; + if(z==z2) return hit2; + if(z==z3) return hit3; + printf("stage: general test is broken (code 0)\n"); + return nohit; + } + printf("stage: general test is broken (code 1)\n"); + return nohit; +} + + + +/* +test a single moving point for collision with the stage. +if a collision occurs the result will contain the collision +point, a new velocity, penetration depth, and surface type. +this data can be used in several ways by the client code. +testing moving rectangles is expected to use several calls. +this model has problems with sharp acute corners, so levels +should avoid them. +*/ +struct stghit stage_collide(int x, int y, int vx, int vy){ + int tx = DDD(x) / 16; + int ty = DDD(y) / 16; + int x_ = x % L; + int y_ = y % L; + int W = this_stage->w; + tile* t = this_stage->tiles + tx + ty*W; + int mt; + int sc; + test sides[3]; + Q hit; + + unpack_config(t->config, &mt, &sc); + if(maintests[mt] == NULL) mt = 1; + get_sidetests(sc, sides); + hit = general_test(x_, y_, vx, vy, maintests[mt], + sides[0], sides[1], sides[2]); + + if(hit.yes){ + hit.x += UUU(tx * 16); + hit.y += UUU(ty * 16); + } + return hit; +} + + +/* i believe this only works for rectangles strictly smaller than + * a tile. 'works' means level should avoid sharp points. + */ +struct stghit stage_collide_rect(int x, int y, int w, int h, int vx, int vy){ + struct stghit hit0, hit1, hit2, hit3; + int z0,z1,z2,z3,z; +// struct stghit hit4, hit5, hit6, hit7; +// int z4,z5,z6,z7; + + hit0 = stage_collide(x,y,vx,vy); + hit1 = stage_collide(x+w,y,vx,vy); + hit2 = stage_collide(x,y+h,vx,vy); + hit3 = stage_collide(x+w,y+h,vx,vy); + + z0 = hit0.yes ? hit0.depth : INT_MIN; + z1 = hit1.yes ? hit1.depth : INT_MIN; + z2 = hit2.yes ? hit2.depth : INT_MIN; + z3 = hit3.yes ? hit3.depth : INT_MIN; + + z = max4(z0,z1,z2,z3); + + if(z == z0) return hit0; + if(z == z1){ + hit1.x -= w; + return hit1; + } + if(z == z2){ + hit2.y -= h; + return hit2; + } + if(z == z3){ + hit3.x -= w; + hit3.y -= h; + return hit3; + } + + return nohit; +} + + +/* end collision stuff */ + + + + + + +static void initialize_tiles(int n, tile* tiles){ + int i; + for(i=0; ibgimage = load_bitmap(gfx); + + loader_scanline(f, "%s", buf); + strcpy(gfx, gfxpath); + strcat(gfx, buf); + s->bgtiles = load_bitmap(gfx); + + loader_scanline(f, "%s", buf); + strcpy(gfx, gfxpath); + strcat(gfx, buf); + s->fgtiles = load_bitmap(gfx); + + s->tiles = malloc(w*h*sizeof(tile)); + initialize_tiles(w*h, s->tiles); + s->w = w; + s->h = h; + s->ox = ox; + s->oy = oy; + strncpy(s->id, filename, 256); + s->id[255] = '\0'; + + while(!loader_feof(f)){ + loader_scanline(f, "%d %d %d %d %c", &x, &y, &fg, &bg, &shape); + tptr = s->tiles + (x+ox) + (s->w * (y+oy)); + tptr->fg = fg; + tptr->bg = bg; + tptr->shape = shape; + tptr->config = base_config(shape); + } + + fix_tile_sides(s); + + s->next = stages; + stages = s; + + loader_close(f); + return 0; +} + +/***/ + + +int load_zone(string name){ + /* +loading a zone from a file +a zone consists of one or more stages +each stage has its own tileset graphics and background +it also has a large array of tiles + +the stage files are in zones/zonename/ +the name of the file will be used as the id + */ + + list* dirs; + list* ptr; + char stagesdir[256] = ""; + char gfxpath[256] = ""; + char* stagepath; + + strcat(stagesdir, "zones/"); + strcat(stagesdir, name); + strcat(stagesdir, "/stages/"); + + strcat(gfxpath, "zones/"); + strcat(gfxpath, name); + strcat(gfxpath, "/gfx/"); + + strncpy(zone_name, name, 256); + zone_name[255] = '\0'; + + dirs = loader_readdir((string)stagesdir); + if(dirs == NULL){ + printf("ERROR cant read dirs\n"); + return -1; + } + + ptr = dirs->next; + while(ptr){ + stagepath = ptr->item; + if(load_stage(gfxpath, stagepath) < 0){ + printf("ERROR cant load stage\n"); + loader_freedirlist(dirs); + return -1; + } + ptr = ptr->next; + } + + loader_freedirlist(dirs); + return 0; +} + +void unload_zone(){ + stage* ptr = stages; + stage* prev; + while(ptr){ + free(ptr->tiles); + prev = ptr; + ptr = ptr->next; + free(prev); + } + + strcpy(zone_name, "NO ZONE"); +} + +void switch_stage(string id){ + stage* ptr = stages; + while(ptr){ + if(strcmp(id, ptr->id) == 0){ + this_stage = ptr; + return; + } + ptr = ptr->next; + } + + printf("ERROR stage not found\n"); +} + + +static void draw_tiles(int gfx, char layer, int cx, int cy){ + tile* tbase = this_stage->tiles; + tile* t; + int tw = this_stage->w; + int th = this_stage->h; + int id; + int gx, gy; + + int i; + int j; + int io = cx/16; + int jo = cy/16; + int i_ = io + 20; + int j_ = jo + 15; + + int extra_x = 0; + int extra_y = 0; + int W, H; + screen_dimensions(&W, &H); + if(W>320){ + extra_x = (W - 320)/16/2 + 2; + } + if(H>240){ + extra_y = (H - 240)/16/2 + 2; + } + + io -= extra_x; + jo -= extra_y; + i_ += extra_x; + j_ += extra_y+1; + + if(io > tw-1) return; + if(jo > th-1) return; + + if(io < 0) io = 0; + if(jo < 0) jo = 0; + if(i_ > tw) i_ = tw; + if(j_ > th) j_ = th; + + for(j=jo; jbg; + else if(layer=='f') id = t->fg; + else id = 0; + gx = 16*(id%16); + gy = 16*(id/16); + draw_gfx(gfx, i*16-cx, j*16-cy, gx, gy, 16, 16); + } + } +} + +/* +cx, cy is the camera position +x, y i think is the offset from 0,0 you should shift +w, h i think is the width and height of the screen +*/ +void stage_draw_bg(int cx, int cy){ + int i; + int bw, bh, screen_w, screen_h; + int bgimage; + int bgshift; + int parallax = 2; + + if(this_stage == NULL) return; + + /* draw background vertically centered + tile horizontally at fraction of camera x */ + bgimage = this_stage->bgimage; + gfx_dimensions(bgimage, &bw, &bh); + screen_dimensions(&screen_w, &screen_h); + bgshift = cx/parallax/bw; + for(i=-1; i<(screen_w/bw)+2; i++){ + draw_gfx_raw( + bgimage, + (i+bgshift)*bw-cx/parallax, + (screen_h-bh)/2, + 0, 0, bw, bh + ); + } + + draw_tiles(this_stage->bgtiles, 'b', cx, cy); +} + +void stage_draw_fg(int cx, int cy){ + draw_tiles(this_stage->bgtiles, 'f', cx, cy); +} + + +void stage_init(){ + int i; + for(i=0; i<14; i++){ + maintests[i] = NULL; + } + + sidetests[0] = st_left; + sidetests[1] = st_right; + sidetests[2] = st_top; + sidetests[3] = st_bottom; + + maintests[0] = nulltest; + maintests[1] = mt_square; + maintests[2] = mt_triangle_ne; + maintests[3] = mt_triangle_nw; + maintests[4] = mt_triangle_se; + maintests[5] = mt_triangle_sw; + maintests[6] = mt_ltrap_floor; + maintests[7] = mt_rtrap_floor; + maintests[8] = mt_lslope_floor; + maintests[9] = mt_rslope_floor; + maintests[10] = mt_ltrap_ceil; + maintests[11] = mt_rtrap_ceil; + maintests[12] = mt_lslope_ceil; + maintests[13] = mt_rslope_ceil; + maintests[14] = mt_half_floor; + maintests[15] = mt_half_ceil; +} + + + +/*** debug ***/ + +void stage_debug(){ + stage* ptr = stages; + int i, j; + char c; + + printf("stage debug:\n\n"); + printf("zone: %s\n\n", zone_name); + + while(ptr){ + printf("stage: %s\n", ptr->id); + printf("size: %dx%d\n", ptr->w, ptr->h); + printf("origin: (%d, %d)\n", ptr->ox, ptr->oy); + printf("bgimage: %d\n", ptr->bgimage); + printf("bgtiles: %d\n", ptr->bgtiles); + printf("fgtiles: %d\n", ptr->fgtiles); + printf("tiles:\n"); + + for(j=0; jh; j++){ + for(i=0; iw; i++){ + c = (ptr->tiles + i + ptr->w*j)->fg; + /* + if(isprint(c)) printf("%d", c); + else printf("?");*/ + printf("[%02x]", c); + } + printf("\n"); + } + + + printf("\n"); + ptr = ptr->next; + } +} diff --git a/stage.h b/stage.h index b909ba0..29ddc73 100644 --- a/stage.h +++ b/stage.h @@ -20,6 +20,13 @@ Boston, MA 02110-1301, USA */ +struct stghit { + int yes; + int x, y; + int vx, vy; + int surface; + int depth; +}; int load_zone(string filename); void unload_zone(void); @@ -30,6 +37,7 @@ void switch_stage(string id); void stage_draw_fg(int cx, int cy); void stage_draw_bg(int cx, int cy); -int stage_xcollide(int x, int y, int w, int h, int v, int* xx); -int stage_ycollide(int x, int y, int w, int h, int v, int* yy); + +struct stghit stage_collide(int x, int y, int vx, int vy); +struct stghit stage_collide_rect(int x, int y, int w, int h, int vx, int vy); -- 2.11.4.GIT