Initial code for moving platforms

This commit is contained in:
Rob Pearce 2008-11-06 09:15:09 +00:00
parent 7e2a9cf509
commit 5e40cf4c02
9 changed files with 283 additions and 16 deletions

View File

@ -39,3 +39,10 @@
18,level8.5.dat,Look out above... 18,level8.5.dat,Look out above...
40,level40.dat,King Snail 40,level40.dat,King Snail
109,level109.dat,THE END SO FAR 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

BIN
data/sprites/platform.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

15
defs.h
View File

@ -212,6 +212,8 @@
#define MAXHISCORES 10 #define MAXHISCORES 10
#define MAXHISCORENAME 12 #define MAXHISCORENAME 12
#define MAXWAYPOINTS 10
#define HISCORE_DISPLAYTIME 10 // how many secs to display hiscores for #define HISCORE_DISPLAYTIME 10 // how many secs to display hiscores for
// Fixed text buffer sizes // Fixed text buffer sizes
@ -320,7 +322,7 @@
#define S_SLOPE 2 #define S_SLOPE 2
// Sprite types // Sprite types
#define MAXPTYPES 132 #define MAXPTYPES 133
#define P_PLAYER 0 #define P_PLAYER 0
#define P_RAT 1 #define P_RAT 1
#define P_CHEESE 2 #define P_CHEESE 2
@ -458,6 +460,7 @@
#define P_KSSHELL 129 #define P_KSSHELL 129
#define P_BIGNUMNETS 130 #define P_BIGNUMNETS 130
#define P_RANDOM 131 #define P_RANDOM 131
#define P_PLATFORM 132
// cards // cards
#define CARDFONTX 4 #define CARDFONTX 4
@ -640,6 +643,9 @@ typedef struct initialmonster_s {
int startx; int startx;
int starty; int starty;
int id; int id;
int wayx[MAXWAYPOINTS];
int wayy[MAXWAYPOINTS];
int numwaypoints;
char *help; char *help;
} initialmonster_t; } initialmonster_t;
@ -760,6 +766,12 @@ typedef struct sprite_s {
int card[MAXCARDS]; int card[MAXCARDS];
int usedcard[MAXCARDS]; int usedcard[MAXCARDS];
// for moving platforms
double wayx[MAXWAYPOINTS];
double wayy[MAXWAYPOINTS];
int numwaypoints;
int curwaypoint;
// monster only // monster only
int iced; // turned to ice? int iced; // turned to ice?
SDL_Surface *iceimg; // Image to blit for ice SDL_Surface *iceimg; // Image to blit for ice
@ -788,6 +800,7 @@ typedef struct sprite_s {
double size; double size;
// player and monster // player and monster
struct sprite_s *onplatform;// are we on platform?
int lives; // only for player and bosses int lives; // only for player and bosses
int swimming; // are we in the water? int swimming; // are we in the water?
int falling; // are we falling? int falling; // are we falling?

72
edit.c
View File

@ -35,6 +35,9 @@ int skipto = -1;
int layer = 1; // which layer we are editting, either 1 or 2 int layer = 1; // which layer we are editting, either 1 or 2
int layertransparent = B_TRUE; int layertransparent = B_TRUE;
sprite_t *waypointm = NULL;
SDL_Surface *whitebox; SDL_Surface *whitebox;
SDL_Color red = {255, 0, 0, 0}; 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) { } else if (state == LS_SAVE) {
// get pos // get pos
int i; int i;
@ -444,6 +458,36 @@ int main (int argc, char **argv) {
toggletimer = 15; 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 if (keys[SDLK_x]) { // delete monster
int donesomething = B_FALSE; int donesomething = B_FALSE;
@ -571,6 +615,14 @@ int main (int argc, char **argv) {
draweditorlevel(); draweditorlevel();
drawsprites(); 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; sprite_t *s;
for (s = sprite; s != NULL; s = s->next) { for (s = sprite; s != NULL; s = s->next) {
drawsprite(s); 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; mid = s->id;
mx = (s->x - (TILEW/2)) / TILEW; mx = (s->x - (TILEW/2)) / TILEW;
my = (s->y - TILEH/2) / TILEH; 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"); fprintf(f, "endmonsters\n");
@ -1019,6 +1088,7 @@ int isplacabletile(int tid) {
} }
int isplacablesprite(int sid) { int isplacablesprite(int sid) {
if (sid == P_PLATFORM) return B_TRUE;
if (sid == P_HELP) return B_TRUE; if (sid == P_HELP) return B_TRUE;
if (sid == P_PLAYER) return B_TRUE; if (sid == P_PLAYER) return B_TRUE;
if (sid == P_POWERUPPOS) return B_TRUE; if (sid == P_POWERUPPOS) return B_TRUE;

1
edit.h
View File

@ -35,6 +35,7 @@
// level states // level states
#define LS_EDIT 0 #define LS_EDIT 0
#define LS_SAVE 1 #define LS_SAVE 1
#define LS_WAYPOINTS 2
// Editor specific functions // Editor specific functions

143
rc.c
View File

@ -1513,6 +1513,54 @@ void cleanup(void) {
printf("complete.\n"); 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) { void checkcollide(sprite_t *s) {
sprite_t *s2; sprite_t *s2;
int keepchecking; int keepchecking;
@ -1520,6 +1568,7 @@ void checkcollide(sprite_t *s) {
double xthresh, ythresh; double xthresh, ythresh;
int netsleft; int netsleft;
// for all other sprites // for all other sprites
for (s2 = sprite ; s2 ; s2 = s2->next) { for (s2 = sprite ; s2 ; s2 = s2->next) {
@ -2141,7 +2190,7 @@ int movesprite(sprite_t *s) {
// timer3 is the target y position // timer3 is the target y position
// //
// move towards end 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? // are we there yet?
if ((s->x == s->timer2) && (s->y == s->timer3)) { if ((s->x == s->timer2) && (s->y == s->timer3)) {
@ -2236,7 +2285,7 @@ int movesprite(sprite_t *s) {
} }
} else { } else {
// move towards centre of the screen // 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 } else if (s->id == P_MASK) { // mask effect
// stay on top of player // 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) { } else if (s->id == P_TICK) {
if (!s->falling) { if (!s->falling) {
@ -3758,7 +3843,7 @@ void drawlevel(void) {
// the real one along. // the real one along.
for (x = 0; x < 640; x += speed) { for (x = 0; x < 640; x += speed) {
// move player // move player
movetostart(player,dstx,dsty,pspeed,pspeed); moveto(player,dstx,dsty,pspeed,pspeed);
// set cloud location // set cloud location
cloud->x = player->x; cloud->x = player->x;
cloud->y = player->y + (cloud->img->h / 2); cloud->y = player->y + (cloud->img->h / 2);
@ -3822,7 +3907,7 @@ void drawlevel(void) {
// the real one along. // the real one along.
for (y = 0; y < 480; y += speed) { for (y = 0; y < 480; y += speed) {
// move player // move player
movetostart(player,dstx,dsty,pspeed,pspeed); moveto(player,dstx,dsty,pspeed,pspeed);
// set cloud location // set cloud location
cloud->x = player->x; cloud->x = player->x;
cloud->y = player->y + (cloud->img->h / 2); cloud->y = player->y + (cloud->img->h / 2);
@ -3886,7 +3971,7 @@ void drawlevel(void) {
// the real one along. // the real one along.
for (y = 0; y < 480; y += speed) { for (y = 0; y < 480; y += speed) {
// move player // move player
movetostart(player,dstx,dsty,pspeed,pspeed); moveto(player,dstx,dsty,pspeed,pspeed);
// set cloud location // set cloud location
cloud->x = player->x; cloud->x = player->x;
cloud->y = player->y + (cloud->img->h / 2); cloud->y = player->y + (cloud->img->h / 2);
@ -3950,7 +4035,7 @@ void drawlevel(void) {
// the real one along. // the real one along.
for (x = 0; x < 640; x += speed) { for (x = 0; x < 640; x += speed) {
// move player // move player
movetostart(player,dstx,dsty,pspeed,pspeed); moveto(player,dstx,dsty,pspeed,pspeed);
// set cloud location // set cloud location
cloud->x = player->x; cloud->x = player->x;
cloud->y = player->y + (cloud->img->h / 2); cloud->y = player->y + (cloud->img->h / 2);
@ -4052,6 +4137,8 @@ double getspeed(sprite_t *s ) {
else speed = 1.5; else speed = 1.5;
} else if (id == P_KINGRAT) { } else if (id == P_KINGRAT) {
speed = 1.5; speed = 1.5;
} else if (id == P_PLATFORM) {
speed = 2;
} }
if (isinwater(s) && (s->id != P_FISH)) { if (isinwater(s) && (s->id != P_FISH)) {
@ -4739,6 +4826,10 @@ int isroofnabove(sprite_t *s, int howfar) {
} }
int isonground(sprite_t *s) { int isonground(sprite_t *s) {
// are we on a platform?
if (s->onplatform) {
return B_TRUE;
}
/* get tile below sprite's feet */ /* get tile below sprite's feet */
if (isongroundpoint(s, s->x, s->y)) { if (isongroundpoint(s, s->x, s->y)) {
return B_TRUE; return B_TRUE;
@ -4773,6 +4864,10 @@ int isongroundpoint(sprite_t *s, int x,int y) {
int xoff; int xoff;
int groundy; int groundy;
if (s->onplatform) {
return B_TRUE;
}
tt = gettileat(x,y, &tilex, &tiley); tt = gettileat(x,y, &tilex, &tiley);
@ -6268,8 +6363,10 @@ void channeldone(int channel) {
// move player towards new position // 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; double ang,xs,ys;
int therex = B_FALSE,therey = B_FALSE;
// figure out angle to player // figure out angle to player
ang = atan2(dsty - p->y, dstx - p->x); ang = atan2(dsty - p->y, dstx - p->x);
xs = (cos(ang) * xspeed); 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) { if (p->x < dstx) {
p->x += xs; p->x += xs;
if (p->x > dstx) p->x = dstx; if (p->x >= dstx) {
p->x = dstx;
}
} }
if (p->x > dstx) { if (p->x > dstx) {
p->x += xs; 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) { if (p->y < dsty) {
p->y += ys; p->y += ys;
if (p->y > dsty) p->y = dsty; if (p->y >= dsty) {
p->y = dsty;
}
} }
if (p->y > dsty) { if (p->y > dsty) {
p->y += ys; 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 // grabs area behind a sprite into a temp buffer
@ -6648,7 +6763,11 @@ void checkcollideall(void) {
checkcollide(s); checkcollide(s);
} }
} else if (needscollisions(s->id)) { } else if (needscollisions(s->id)) {
checkcollide(s); if (isplatform(s->id)) {
checkcollideplatform(s);
} else {
checkcollide(s);
}
} }
} }
} }

3
rc.h
View File

@ -26,6 +26,7 @@ int isonbridge(sprite_t *s);
int isladderabove(sprite_t *s); int isladderabove(sprite_t *s);
int dofruiteffect(sprite_t *s); int dofruiteffect(sprite_t *s);
void checkcollide(sprite_t *s); void checkcollide(sprite_t *s);
void checkcollideplatform(sprite_t *s);
void die(sprite_t *s); void die(sprite_t *s);
void nextlevel(void); void nextlevel(void);
void jump(sprite_t *s, int dir); void jump(sprite_t *s, int dir);
@ -42,7 +43,7 @@ void playfx(int num);
void playmusic(Mix_Music *toplay); void playmusic(Mix_Music *toplay);
void stopmusic(void); void stopmusic(void);
void channeldone(int channel); 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); SDL_Surface *grabbehind(sprite_t *s, SDL_Surface *surf);
void dumpsprites(void); void dumpsprites(void);
int countmonsters(int montype); int countmonsters(int montype);

View File

@ -257,6 +257,26 @@ int loadlevel(int wnum, int lnum, int wantmonsters) {
} }
y = atoi(p); // monster y pos 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) { if (monid == P_PLAYER) {
level->p1x = x; level->p1x = x;
@ -520,7 +540,19 @@ int loadlevel(int wnum, int lnum, int wantmonsters) {
level->initm[i].startx, level->initm[i].starty, name ); level->initm[i].startx, level->initm[i].starty, name );
#else #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 #endif
} }
} }
@ -596,6 +628,8 @@ void setdefaults(sprite_t *s) {
s->frame = 0; s->frame = 0;
s->onplatform = NULL;
s->hasmask = B_FALSE; s->hasmask = B_FALSE;
s->hasbell = B_FALSE; s->hasbell = B_FALSE;
s->gemboost = 1; s->gemboost = 1;
@ -609,6 +643,7 @@ void setdefaults(sprite_t *s) {
s->recoiling = B_FALSE; s->recoiling = B_FALSE;
s->teleporting = 0; s->teleporting = 0;
s->climbing = 0; s->climbing = 0;
s->swimming = 0;
s->jumping = 0; s->jumping = 0;
s->jumpspeed = 0; s->jumpspeed = 0;
s->jumpdir = 1; s->jumpdir = 1;
@ -763,6 +798,10 @@ sprite_t *addsprite(int id, int x, int y, char *name ) {
} }
s->iceimg = NULL; 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 // don't set these in setdefaults() as setdefaults() is called after each player death
s->permspeed = B_FALSE; s->permspeed = B_FALSE;
s->permbignet = B_FALSE; s->permbignet = B_FALSE;
@ -1355,6 +1394,11 @@ int loadimagesets(void) {
loadspriteimage(P_ZAPPOWERUP,F_WALK1, "sprites/zapper.png"); loadspriteimage(P_ZAPPOWERUP,F_WALK1, "sprites/zapper.png");
imageset[P_ZAPPOWERUP].numimages = 1; 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,0, "sprites/zap1.png");
loadspriteimage(P_ZAPPER,1, "sprites/zap2.png"); loadspriteimage(P_ZAPPER,1, "sprites/zap2.png");
loadspriteimage(P_ZAPPER,2, "sprites/zap3.png"); loadspriteimage(P_ZAPPER,2, "sprites/zap3.png");
@ -2172,6 +2216,15 @@ int isbullet(int id) {
return B_FALSE; return B_FALSE;
} }
int isplatform(int id) {
switch (id) {
case P_PLATFORM:
return B_TRUE;
}
return B_FALSE;
}
int iseffect(int id) { int iseffect(int id) {
switch (id) { switch (id) {
case P_PUFF: 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 // these last two aren't REALLY effects since they never have a sprite allocated
case P_WINGLEFT: case P_WINGLEFT:
case P_WINGRIGHT: case P_WINGRIGHT:
case P_PLATFORM:
return B_TRUE; return B_TRUE;
} }
@ -2204,6 +2258,7 @@ int needscollisions(int id) {
if (id == P_STAR) return B_TRUE; if (id == P_STAR) return B_TRUE;
if (id == P_METEOR) return B_TRUE; if (id == P_METEOR) return B_TRUE;
if (id == P_ZAPPER) return B_TRUE; if (id == P_ZAPPER) return B_TRUE;
if (isplatform(id)) return B_TRUE;
return B_FALSE; return B_FALSE;
} }

View File

@ -20,6 +20,7 @@ int isfruit(int id);
int isflower(int id); int isflower(int id);
int iscard(int id); int iscard(int id);
int iseffect(int id); int iseffect(int id);
int isplatform(int id);
int needscollisions(int id); int needscollisions(int id);
int candoslopes(int sid); int candoslopes(int sid);
int flowertogem(int id); int flowertogem(int id);