From 5e40cf4c024f193f7d1693fd64d43398a6e46c3c Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Thu, 6 Nov 2008 09:15:09 +0000 Subject: [PATCH] Initial code for moving platforms --- data/levels.dat | 7 ++ data/sprites/platform.png | Bin 0 -> 1862 bytes defs.h | 15 +++- edit.c | 72 ++++++++++++++++++- edit.h | 1 + rc.c | 143 ++++++++++++++++++++++++++++++++++---- rc.h | 3 +- shared.c | 57 ++++++++++++++- shared.h | 1 + 9 files changed, 283 insertions(+), 16 deletions(-) create mode 100644 data/sprites/platform.png diff --git a/data/levels.dat b/data/levels.dat index 91255d6..0f8ee27 100644 --- a/data/levels.dat +++ b/data/levels.dat @@ -39,3 +39,10 @@ 18,level8.5.dat,Look out above... 40,level40.dat,King Snail 109,level109.dat,THE END SO FAR +99,level99.dat,TEST LEVEL +118,level118.dat,NEW LEVEL +119,level119.dat,NEW LEVEL +120,level120.dat,NEW LEVEL +121,level121.dat,NEW LEVEL +122,level122.dat,NEW LEVEL +123,level123.dat,NEW LEVEL diff --git a/data/sprites/platform.png b/data/sprites/platform.png new file mode 100644 index 0000000000000000000000000000000000000000..d4d0085f671fb19eec85fd9e19f04a833bbb86e3 GIT binary patch literal 1862 zcmV-M2f6r(P)+xKNs2U^1Oki} zlt$vDyTpN~`meXQ-uwQoAHAyVm+#%StM+qK*4L}tAcbUQBtj@O5+4WJ*wBOxE)6VA zMwdKwrl3r$wLuAiCNRZFp%Y!0!0ZXS!;21^wz$+Y&m>(sXG%L90fi)Hl2Qw-uq?8` zEjj&F_$?(TH4fdpfp?8(TBhgTZE7h6kc{L z%v_@nbSIGK&?H7ijA(N<^ekjG^Oi!#@DXY{C+Fh{Jh9>n$EnOaT=x z{zhda*6o-E%ZK3;08(@msi5yirp6()KxP6h1YSq1_h>Xxj&wLGBOySxnFB+yrH}i&UARc{m{yc)?S7QHm%0GbLFbNQ9H< z-OjQ135_Id!AQXr0^1bn?1&GEloCoRN})JCO^BtWje&&`eDYw#`G^*Y+$zFj7*=ri zpO(261P^;3$)sXBi*tKL84`8#Eqv+o`E9&IR0M(`eE6e%XuE5nVe zYsS#xd?a{JrVN|&hTx$rH6quP2N_vqP)egSjVTmT3qpv*$s>}$7=`nZF|^#cx@KM( zY!7Pkq?j;95xl1`8TTG-*!PaI%sJ%wJK9z61BjFo0B^qi&ELwkd+mYw;JKkm=nCA< z5kn-Ah$)beEY}6zc*bGk%3{gcgAqBCSnDY(!x$}B%NtB~hl&|4^^D$vN~9#PZ6Jk+ zL?I9yK3j3x>?q0{?KHd1h~Q$e3ItL~%+la{C>Mfb_wt>%F@Jgc&ELF!sQ`fQ{p8y} z@5TA8KHpqnHQn0U^DDj$$Rx3T;Anlw6h_K9pmUt{biJck2`X2!PaVTBv6>%XR3c6i zpC+_X5FFEx$jCW8+h9~l6p`gofyp%ZiD3`9Dmd9ZCes&O&lIcd;FN8Cx0=?cRXVu) zvmgBWyZ_4hQUU)N-}&8FZr@KIy>jy58GeeCg`&)6c->Oh#lOdF$`w-ae~rPe8_|Bo zU|WVUpmWLMSpQFc^x`vI7cac`i?6-=>eKT43{1vMQUEY?T>t<807*qoM6N<$f*r;M1& literal 0 HcmV?d00001 diff --git a/defs.h b/defs.h index d8afa09..f0eca58 100644 --- a/defs.h +++ b/defs.h @@ -212,6 +212,8 @@ #define MAXHISCORES 10 #define MAXHISCORENAME 12 +#define MAXWAYPOINTS 10 + #define HISCORE_DISPLAYTIME 10 // how many secs to display hiscores for // Fixed text buffer sizes @@ -320,7 +322,7 @@ #define S_SLOPE 2 // Sprite types -#define MAXPTYPES 132 +#define MAXPTYPES 133 #define P_PLAYER 0 #define P_RAT 1 #define P_CHEESE 2 @@ -458,6 +460,7 @@ #define P_KSSHELL 129 #define P_BIGNUMNETS 130 #define P_RANDOM 131 +#define P_PLATFORM 132 // cards #define CARDFONTX 4 @@ -640,6 +643,9 @@ typedef struct initialmonster_s { int startx; int starty; int id; + int wayx[MAXWAYPOINTS]; + int wayy[MAXWAYPOINTS]; + int numwaypoints; char *help; } initialmonster_t; @@ -760,6 +766,12 @@ typedef struct sprite_s { int card[MAXCARDS]; int usedcard[MAXCARDS]; + // for moving platforms + double wayx[MAXWAYPOINTS]; + double wayy[MAXWAYPOINTS]; + int numwaypoints; + int curwaypoint; + // monster only int iced; // turned to ice? SDL_Surface *iceimg; // Image to blit for ice @@ -788,6 +800,7 @@ typedef struct sprite_s { double size; // player and monster + struct sprite_s *onplatform;// are we on platform? int lives; // only for player and bosses int swimming; // are we in the water? int falling; // are we falling? diff --git a/edit.c b/edit.c index fd388af..2537e8e 100644 --- a/edit.c +++ b/edit.c @@ -35,6 +35,9 @@ int skipto = -1; int layer = 1; // which layer we are editting, either 1 or 2 int layertransparent = B_TRUE; + +sprite_t *waypointm = NULL; + SDL_Surface *whitebox; SDL_Color red = {255, 0, 0, 0}; @@ -367,6 +370,17 @@ int main (int argc, char **argv) { } } + } else if (state == LS_WAYPOINTS) { + // add waypoint at selected position + // TODO: lock x/y with keys... + if (toggletimer == 0) { + waypointm->wayx[waypointm->numwaypoints] = mx; + waypointm->wayy[waypointm->numwaypoints] = my; + waypointm->numwaypoints++; + sprintf(tempm, "Waypoint #%d added at %d,%d",waypointm->numwaypoints,mx,my); + setstatustext(tempm, &blue); + toggletimer = 20; + } } else if (state == LS_SAVE) { // get pos int i; @@ -444,6 +458,36 @@ int main (int argc, char **argv) { toggletimer = 15; } } + if (keys[SDLK_w]) { // set waypoints + int donesomething = B_FALSE; + sprite_t *s, *nextone; + + for (s = sprite ; s ; s = nextone) { + nextone = s->next; + + /* if mouse is over this sprite */ + if ( (mx >= s->x - (s->img->w/2)) && + (mx <= s->x + (s->img->w/2)) && + (my >= s->y - s->img->h) && + (my <= s->y )) { + if (isplatform(s->id)) { + // select it + waypointm = s; + state = LS_WAYPOINTS; + donesomething = B_TRUE; + } + } + } + if (donesomething) { + // clear waypoints for selection + waypointm->numwaypoints = 0; + // redraw + draweditorlevel(); + drawsprites(); + setmod(B_TRUE); + setstatustext("Waypoint selection mode...",&green); + } + } if (keys[SDLK_x]) { // delete monster int donesomething = B_FALSE; @@ -571,6 +615,14 @@ int main (int argc, char **argv) { draweditorlevel(); drawsprites(); } + } else if (state == LS_WAYPOINTS) { + if (keys[SDLK_ESCAPE]) { + waypointm = NULL; + state = LS_EDIT; + draweditorlevel(); + drawsprites(); + setstatustext("Finished adding waypoints.", &green); + } } @@ -763,6 +815,13 @@ void drawsprites(void) { sprite_t *s; for (s = sprite; s != NULL; s = s->next) { drawsprite(s); + // waypoint selection mode + if (state == LS_WAYPOINTS) { + if (waypointm == s) { + drawbox16(screen, s->x - s->img->w/2,s->y - s->img->h, + s->x + s->img->w/2, s->y, &red, NULL); + } + } } } @@ -919,7 +978,17 @@ int savelevel(int wnum, int lnum) { mid = s->id; mx = (s->x - (TILEW/2)) / TILEW; my = (s->y - TILEH/2) / TILEH; - fprintf(f,"%d %d %d\n",mid,mx,my); + if (s->numwaypoints > 0) { + int i; + fprintf(f,"%d %d %d",mid,mx,my); + for (i = 0; i < s->numwaypoints; i++) { + fprintf(f," %0.0f %0.0f",s->wayx[i],s->wayy[i]); + } + fprintf(f,"\n"); + } else { + // no waypoints + fprintf(f,"%d %d %d\n",mid,mx,my); + } } fprintf(f, "endmonsters\n"); @@ -1019,6 +1088,7 @@ int isplacabletile(int tid) { } int isplacablesprite(int sid) { + if (sid == P_PLATFORM) return B_TRUE; if (sid == P_HELP) return B_TRUE; if (sid == P_PLAYER) return B_TRUE; if (sid == P_POWERUPPOS) return B_TRUE; diff --git a/edit.h b/edit.h index a9191dc..e38e182 100644 --- a/edit.h +++ b/edit.h @@ -35,6 +35,7 @@ // level states #define LS_EDIT 0 #define LS_SAVE 1 +#define LS_WAYPOINTS 2 // Editor specific functions diff --git a/rc.c b/rc.c index 480f129..f600330 100644 --- a/rc.c +++ b/rc.c @@ -1513,6 +1513,54 @@ void cleanup(void) { printf("complete.\n"); } +void checkcollideplatform(sprite_t *s) { + double xdiff,ydiff; + double xthresh,ythresh; + sprite_t *s2; + SDL_Surface *walkimg; + + for (s2 = sprite ; s2 ; s2 = s2->next) { + // only monsters and players and fruits can be on platforms + if (!ismonster(s2->id) && (s2 != player) && (!isfruit(s2->id))) { + continue; + } + + if (s2->onplatform == s) { + // if already on us, default to not being on us in case + // it's moved away + s2->onplatform = NULL; + } + + // is s2 touching us? + /* + xdiff = s->x - s2->x; + if (xdiff < 0) xdiff = -xdiff; + + + ydiff = (s->y-(s->img->h/2)) - (s2->y-(s2->img->h/2)); + if (ydiff < 0) ydiff = -ydiff; + + xthresh = s->img->w/2 + s2->img->w/2; + ythresh = s->img->h/2 + s2->img->h/2; + */ + + //if ((xdiff <= xthresh) && (ydiff <= ythresh)) { + + walkimg = imageset[s2->id].img[F_WALK1]; + + // has it hit the top half of us? + if ((s2->x >= (s->x - s->img->w/2 - walkimg->w/2 ) ) && (s2->x <= (s->x + s->img->w/2 + walkimg->w/2)) && + (s2->y >= (s->y - s->img->h) ) && (s2->y <= s->y - s->img->h/2)) { + /* COLLISION! */ + if (!s2->jumping) { + s2->y = s->y - s->img->h; + s2->onplatform = s; + } + } + + } +} + void checkcollide(sprite_t *s) { sprite_t *s2; int keepchecking; @@ -1520,6 +1568,7 @@ void checkcollide(sprite_t *s) { double xthresh, ythresh; int netsleft; + // for all other sprites for (s2 = sprite ; s2 ; s2 = s2->next) { @@ -2141,7 +2190,7 @@ int movesprite(sprite_t *s) { // timer3 is the target y position // // move towards end position - movetostart(s, s->timer2, s->timer3, CARDSPEED, CARDSPEED); + moveto(s, s->timer2, s->timer3, CARDSPEED, CARDSPEED); // are we there yet? if ((s->x == s->timer2) && (s->y == s->timer3)) { @@ -2236,7 +2285,7 @@ int movesprite(sprite_t *s) { } } else { // move towards centre of the screen - movetostart(s, 320, 240, FIVECARDSPEED, FIVECARDSPEED); + moveto(s, 320, 240, FIVECARDSPEED, FIVECARDSPEED); } } else if (s->id == P_MASK) { // mask effect // stay on top of player @@ -2920,6 +2969,42 @@ int movesprite(sprite_t *s) { } } + } else if (s->id == P_PLATFORM) { // moving platform + double dstx,dsty; + int rv; + + if (s->numwaypoints > 0) { + sprite_t *s2; + double oldx,oldy,xdiff,ydiff; + + oldx = s->x; + oldy = s->y; + // move torwaeds next waypoints + dstx = s->wayx[s->curwaypoint]; + dsty = s->wayy[s->curwaypoint]; + rv = moveto(s,dstx,dsty,getspeed(s),getspeed(s)); + + // got there? + if (rv) { + // go to next waypoint + s->curwaypoint++; + if (s->curwaypoint >= s->numwaypoints) { + s->curwaypoint = 0; + } + } + + // remember how far we moved + xdiff = s->x - oldx; + ydiff = s->y - oldy; + + // move anything on top of us by the same amount + for (s2 = sprite ; s2 ; s2 = s2->next) { + if (s2->onplatform == s) { + s2->x += xdiff; + s2->y += ydiff; + } + } + } } else if (s->id == P_TICK) { if (!s->falling) { @@ -3758,7 +3843,7 @@ void drawlevel(void) { // the real one along. for (x = 0; x < 640; x += speed) { // move player - movetostart(player,dstx,dsty,pspeed,pspeed); + moveto(player,dstx,dsty,pspeed,pspeed); // set cloud location cloud->x = player->x; cloud->y = player->y + (cloud->img->h / 2); @@ -3822,7 +3907,7 @@ void drawlevel(void) { // the real one along. for (y = 0; y < 480; y += speed) { // move player - movetostart(player,dstx,dsty,pspeed,pspeed); + moveto(player,dstx,dsty,pspeed,pspeed); // set cloud location cloud->x = player->x; cloud->y = player->y + (cloud->img->h / 2); @@ -3886,7 +3971,7 @@ void drawlevel(void) { // the real one along. for (y = 0; y < 480; y += speed) { // move player - movetostart(player,dstx,dsty,pspeed,pspeed); + moveto(player,dstx,dsty,pspeed,pspeed); // set cloud location cloud->x = player->x; cloud->y = player->y + (cloud->img->h / 2); @@ -3950,7 +4035,7 @@ void drawlevel(void) { // the real one along. for (x = 0; x < 640; x += speed) { // move player - movetostart(player,dstx,dsty,pspeed,pspeed); + moveto(player,dstx,dsty,pspeed,pspeed); // set cloud location cloud->x = player->x; cloud->y = player->y + (cloud->img->h / 2); @@ -4052,6 +4137,8 @@ double getspeed(sprite_t *s ) { else speed = 1.5; } else if (id == P_KINGRAT) { speed = 1.5; + } else if (id == P_PLATFORM) { + speed = 2; } if (isinwater(s) && (s->id != P_FISH)) { @@ -4739,6 +4826,10 @@ int isroofnabove(sprite_t *s, int howfar) { } int isonground(sprite_t *s) { + // are we on a platform? + if (s->onplatform) { + return B_TRUE; + } /* get tile below sprite's feet */ if (isongroundpoint(s, s->x, s->y)) { return B_TRUE; @@ -4773,6 +4864,10 @@ int isongroundpoint(sprite_t *s, int x,int y) { int xoff; int groundy; + if (s->onplatform) { + return B_TRUE; + } + tt = gettileat(x,y, &tilex, &tiley); @@ -6268,8 +6363,10 @@ void channeldone(int channel) { // move player towards new position -void movetostart(sprite_t *p, int dstx, int dsty, double xspeed, double yspeed) { +// return true if we're there +int moveto(sprite_t *p, int dstx, int dsty, double xspeed, double yspeed) { double ang,xs,ys; + int therex = B_FALSE,therey = B_FALSE; // figure out angle to player ang = atan2(dsty - p->y, dstx - p->x); xs = (cos(ang) * xspeed); @@ -6277,20 +6374,38 @@ void movetostart(sprite_t *p, int dstx, int dsty, double xspeed, double yspeed) if (p->x < dstx) { p->x += xs; - if (p->x > dstx) p->x = dstx; + if (p->x >= dstx) { + p->x = dstx; + } } if (p->x > dstx) { p->x += xs; - if (p->x < dstx) p->x = dstx; + if (p->x <= dstx) { + p->x = dstx; + } + } + if (p->x == dstx) { + therex = B_TRUE; } if (p->y < dsty) { p->y += ys; - if (p->y > dsty) p->y = dsty; + if (p->y >= dsty) { + p->y = dsty; + } } if (p->y > dsty) { p->y += ys; - if (p->y < dsty) p->y = dsty; + if (p->y <= dsty) { + p->y = dsty; + } } + if (p->y == dsty) { + therey = B_TRUE; + } + + if (therex && therey) return B_TRUE; + + return B_FALSE; } // grabs area behind a sprite into a temp buffer @@ -6648,7 +6763,11 @@ void checkcollideall(void) { checkcollide(s); } } else if (needscollisions(s->id)) { - checkcollide(s); + if (isplatform(s->id)) { + checkcollideplatform(s); + } else { + checkcollide(s); + } } } } diff --git a/rc.h b/rc.h index 1f38b8f..b7de957 100644 --- a/rc.h +++ b/rc.h @@ -26,6 +26,7 @@ int isonbridge(sprite_t *s); int isladderabove(sprite_t *s); int dofruiteffect(sprite_t *s); void checkcollide(sprite_t *s); +void checkcollideplatform(sprite_t *s); void die(sprite_t *s); void nextlevel(void); void jump(sprite_t *s, int dir); @@ -42,7 +43,7 @@ void playfx(int num); void playmusic(Mix_Music *toplay); void stopmusic(void); void channeldone(int channel); -void movetostart(sprite_t *p, int dstx, int dsty, double xspeed,double yspeed); +int moveto(sprite_t *p, int dstx, int dsty, double xspeed,double yspeed); SDL_Surface *grabbehind(sprite_t *s, SDL_Surface *surf); void dumpsprites(void); int countmonsters(int montype); diff --git a/shared.c b/shared.c index cd33ea4..9d623bc 100644 --- a/shared.c +++ b/shared.c @@ -257,6 +257,26 @@ int loadlevel(int wnum, int lnum, int wantmonsters) { } y = atoi(p); // monster y pos + // waypoints + if (isplatform(monid)) { + level->initm[level->nummonsters].numwaypoints = 0; + // read waypoints + p = strtok(NULL, " "); + while (p) { + level->initm[level->nummonsters].wayx[level->initm[level->nummonsters].numwaypoints] = atoi(p); + p = strtok(NULL, " "); + level->initm[level->nummonsters].wayy[level->initm[level->nummonsters].numwaypoints] = atoi(p); + level->initm[level->nummonsters].numwaypoints++; + + // go to next one + p = strtok(NULL, " "); + } + + if ( level->initm[level->nummonsters].numwaypoints <= 0 ){ + printf("missing waypoint data for platform!\n"); + } + } + if (monid == P_PLAYER) { level->p1x = x; @@ -520,7 +540,19 @@ int loadlevel(int wnum, int lnum, int wantmonsters) { level->initm[i].startx, level->initm[i].starty, name ); #else - puffin(level->initm[i].id, level->initm[i].startx, level->initm[i].starty, name, delay ); + if (isplatform(level->initm[i].id)) { + sprite_t *newsp; + int w; + + newsp = addsprite(level->initm[i].id, level->initm[i].startx, level->initm[i].starty, name ); + newsp->numwaypoints = level->initm[i].numwaypoints; + for (w = 0; w < newsp->numwaypoints; w++) { + newsp->wayx[w] = level->initm[i].wayx[w]; + newsp->wayy[w] = level->initm[i].wayy[w]; + } + } else { + puffin(level->initm[i].id, level->initm[i].startx, level->initm[i].starty, name, delay ); + } #endif } } @@ -596,6 +628,8 @@ void setdefaults(sprite_t *s) { s->frame = 0; + s->onplatform = NULL; + s->hasmask = B_FALSE; s->hasbell = B_FALSE; s->gemboost = 1; @@ -609,6 +643,7 @@ void setdefaults(sprite_t *s) { s->recoiling = B_FALSE; s->teleporting = 0; s->climbing = 0; + s->swimming = 0; s->jumping = 0; s->jumpspeed = 0; s->jumpdir = 1; @@ -763,6 +798,10 @@ sprite_t *addsprite(int id, int x, int y, char *name ) { } s->iceimg = NULL; + // waypoints for moving platforms + s->numwaypoints = 0; + s->curwaypoint = 0; + // don't set these in setdefaults() as setdefaults() is called after each player death s->permspeed = B_FALSE; s->permbignet = B_FALSE; @@ -1355,6 +1394,11 @@ int loadimagesets(void) { loadspriteimage(P_ZAPPOWERUP,F_WALK1, "sprites/zapper.png"); imageset[P_ZAPPOWERUP].numimages = 1; + // moving platforms + loadspriteimage(P_PLATFORM,F_WALK1, "sprites/platform.png"); + imageset[P_PLATFORM].numimages = 1; + + loadspriteimage(P_ZAPPER,0, "sprites/zap1.png"); loadspriteimage(P_ZAPPER,1, "sprites/zap2.png"); loadspriteimage(P_ZAPPER,2, "sprites/zap3.png"); @@ -2172,6 +2216,15 @@ int isbullet(int id) { return B_FALSE; } +int isplatform(int id) { + switch (id) { + case P_PLATFORM: + return B_TRUE; + } + + return B_FALSE; +} + int iseffect(int id) { switch (id) { case P_PUFF: @@ -2193,6 +2246,7 @@ int iseffect(int id) { // these last two aren't REALLY effects since they never have a sprite allocated case P_WINGLEFT: case P_WINGRIGHT: + case P_PLATFORM: return B_TRUE; } @@ -2204,6 +2258,7 @@ int needscollisions(int id) { if (id == P_STAR) return B_TRUE; if (id == P_METEOR) return B_TRUE; if (id == P_ZAPPER) return B_TRUE; + if (isplatform(id)) return B_TRUE; return B_FALSE; } diff --git a/shared.h b/shared.h index b2691c5..87ecbdf 100644 --- a/shared.h +++ b/shared.h @@ -20,6 +20,7 @@ int isfruit(int id); int isflower(int id); int iscard(int id); int iseffect(int id); +int isplatform(int id); int needscollisions(int id); int candoslopes(int sid); int flowertogem(int id);