diff --git a/data/sprites/dwarfhead-small.png b/data/sprites/dwarfhead-small.png index f7da02a..1d9242d 100644 Binary files a/data/sprites/dwarfhead-small.png and b/data/sprites/dwarfhead-small.png differ diff --git a/defs.h b/defs.h index 6185638..d109391 100644 --- a/defs.h +++ b/defs.h @@ -214,7 +214,7 @@ #define S_SLOPE 2 // Sprite types -#define MAXPTYPES 53 +#define MAXPTYPES 55 #define P_PLAYER 0 #define P_RAT 1 #define P_CHEESE 2 @@ -268,6 +268,8 @@ #define P_SLUG 50 #define P_BUBBLE 51 #define P_PHONE 52 +#define P_HONEY 53 +#define P_LIFE 54 // powerups #define PW_NONE 0 @@ -491,6 +493,7 @@ typedef struct sprite_s { int nety; // y position of end of net (used when shooting >1 net) int netxstart; // x position of start of net int netystart; // y position of start of net + int netsticky; // can net pick up powerups? int powerup; // what temp powerup does the player have? int ontramp; // on a trampoline? diff --git a/rc.c b/rc.c index ce6fbd8..bf5e894 100644 --- a/rc.c +++ b/rc.c @@ -52,12 +52,13 @@ int fruittypes[] = { /* the order in which powerups will appear */ int poweruptypes[] = { P_NUMNETS, - P_BELL, P_BIGNET, + P_BELL, P_GEMBOOST, P_NUMNETS, - P_GEMBOOST, + P_HONEY, P_NUMNETS, + P_GEMBOOST, P_HELMET, -1 }; @@ -82,6 +83,7 @@ sprite_t *lastsprite; SDL_Color red = {255, 0, 0, 0}; +SDL_Color orange = {255, 167, 88, 1}; SDL_Color black = {0, 0, 0, 0}; SDL_Color blue = {0, 0, 255, 0}; SDL_Color cyan = {0, 255, 255, 0}; @@ -299,7 +301,8 @@ int main (int argc, char **argv) { player->netmax = 4; // all nets player->netbig = B_TRUE; // big net player->speed = 2; // fast - sprintf(tempm, "Full power!"); + player->netsticky = B_TRUE; + sprintf(tempm, "Cheat!"); addoutlinetext(player->x,player->y - player->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY); toggletimer = 80; } @@ -1339,7 +1342,7 @@ void checkcollide(sprite_t *s) { /* check for colission with our net */ if (s->netting ) { - if (isnettable(s2->id) && !s2->invuln) { + if ((isnettable(s2->id) && !s2->invuln) || (s->netsticky && isfruit(s2->id))){ xdiff = (s->x + s->netlen*s->netdir) - s2->x; if (xdiff < 0) xdiff = -xdiff; ydiff = s->netystart - (s2->y - s2->img->h/2); @@ -1356,48 +1359,54 @@ void checkcollide(sprite_t *s) { if ((xdiff <= s2->img->w/2) && (ydiff <= ythresh)) { // we hit something! - // if we have a boxing glove, it dies - if (s->powerup == PW_BOXING) { - s2->dead = D_BOUNCING;// die as soon as it hits a wall - s2->bounces = 1; - s2->quickdie = B_TRUE; - - /* go FAST in the direction player is facing */ - s2->xs = s->dir * 5; - s2->ys = 0; - - /* slightly raise the sprite to avoid isonground() being true */ - s2->y -= 3; - - /* make sure we're not too high since we'll never get lower now */ - if (s2->y <= TILEH) s2->y = TILEH+1; - - // become something special - s2->willbecome = P_DIAMOND; - - playfx(FX_KILL); - sprintf(tempm, bifftext[rand() % MAXBIFFTEXT]); - addoutlinetext(s2->x,s2->y - s->img->h/2, TEXTSIZE_BIFF, tempm,&red,&yellow,POINTSDELAY); - - keepchecking = B_FALSE; - } else if (s2->iced) { - // it dies - playfx(FX_ICEBREAK); - if (s2->id == P_SNAIL) s2->id = P_SLUG; - die(s2); + if (s->netsticky && isfruit(s2->id)) { + getfruit(s, s2); } else { - // otherwise we caught it if we have enough nets - - if (s->netcaught < s->netmax) { - s2->caughtby = s; - s2->jumping = B_FALSE; - s2->falling = 0; - s2->caughtstate = C_NETTING; - s->netcaught++; - + // Otherwise, it must be a monster + + // if we have a boxing glove, it dies + if (s->powerup == PW_BOXING) { + s2->dead = D_BOUNCING;// die as soon as it hits a wall + s2->bounces = 1; + s2->quickdie = B_TRUE; + + /* go FAST in the direction player is facing */ + s2->xs = s->dir * 5; + s2->ys = 0; + + /* slightly raise the sprite to avoid isonground() being true */ + s2->y -= 3; + + /* make sure we're not too high since we'll never get lower now */ + if (s2->y <= TILEH) s2->y = TILEH+1; + + // become something special + s2->willbecome = P_DIAMOND; + + playfx(FX_KILL); + sprintf(tempm, bifftext[rand() % MAXBIFFTEXT]); + addoutlinetext(s2->x,s2->y - s->img->h/2, TEXTSIZE_BIFF, tempm,&red,&yellow,POINTSDELAY); + keepchecking = B_FALSE; + } else if (s2->iced) { + // it dies + playfx(FX_ICEBREAK); + if (s2->id == P_SNAIL) s2->id = P_SLUG; + die(s2); + } else { + // otherwise we caught it if we have enough nets + + if (s->netcaught < s->netmax) { + s2->caughtby = s; + s2->jumping = B_FALSE; + s2->falling = 0; + s2->caughtstate = C_NETTING; + s->netcaught++; + + keepchecking = B_FALSE; + } } - } + } // end if isfruit or ismonster } } } // end if s->netting @@ -1420,18 +1429,7 @@ void checkcollide(sprite_t *s) { if (s == player) { //if (isfruit(s2->id) && (s2->teleporting == 0)) { if (isfruit(s2->id)) { - int gotscore = s2->score; - - /* kill the fruit */ - s2->dead = D_FINAL; - /* give points to the player */ - addscore(player, gotscore); - /* handle fruit effects */ - if (!dofruiteffect(s2)) { - playfx(FX_FRUIT); - sprintf(tempm, "%d", gotscore); - addoutlinetext(s2->x,s2->y - s2->img->h/2, TEXTSIZE_POINTS, tempm, &white,&black,POINTSDELAY); - } + getfruit(player, s2); } else if (ismonster(s2->id) || isbullet(s2->id)) { if (s2->iced) { // monster dies @@ -3451,7 +3449,11 @@ void drawnetting(sprite_t *s) { yy += y; xx = s->x + s->netdir*s->netlen; - drawline16(screen,sx,s->nety,xx,yy,white); + if (s->netsticky) { + drawdotline16(screen,sx,s->nety,xx,yy,orange,yellow); + } else { + drawline16(screen,sx,s->nety,xx,yy,white); + } // add sparkle xx = s->x + s->netdir*s->netlen; addsprite(P_SPARKLE, xx + (rand() % 14) - 7, yy + (rand() % 8) - 4, "sparkle"); @@ -3464,23 +3466,33 @@ void drawnetting(sprite_t *s) { double dist; int x,y; int ii; + SDL_Color *col1,*col2; dist = (s->slamangle * (180/M_PI))/2; s->netxstart = s->x + cos(s->slamangle-(180*(M_PI/180)))*dist*s->dir; s->netystart = s->y + sin(s->slamangle-(180*(M_PI/180)))*dist; - /* middle line */ - drawline16(screen,s->x,s->y - s->img->h/2, - s->netxstart,s->netystart,white); - /* left line */ + // select colours + if (s->netsticky) { + col1 = &orange; + col2 = &yellow; + } else { + col1 = &white; + col2 = &white; + } + + /* middle dotline */ + drawdotline16(screen,s->x,s->y - s->img->h/2, + s->netxstart,s->netystart,*col1,*col2); + /* left dotline */ x = s->x + cos(s->slamangle-(5*(M_PI/180))-(180*(M_PI/180)))*dist*s->dir; y = s->y + sin(s->slamangle-(5*(M_PI/180))-(180*(M_PI/180)))*dist; - drawline16(screen,s->x,s->y - s->img->h/2,x, y, white); + drawdotline16(screen,s->x,s->y - s->img->h/2,x, y, *col1,*col2); - /* right line */ + /* right dotline */ x = s->x + cos(s->slamangle+(5*(M_PI/180))-(180*(M_PI/180)))*dist*s->dir; y = s->y + sin(s->slamangle+(5*(M_PI/180))-(180*(M_PI/180)))*dist; - drawline16(screen,s->x,s->y - s->img->h/2,x, y, white); + drawdotline16(screen,s->x,s->y - s->img->h/2,x, y, *col1,*col2); // add sparkles for (ii = 0 ; ii < player->netmax; ii++) { @@ -4562,6 +4574,15 @@ int dofruiteffect(sprite_t *s) { player->powerup = PW_CANNON; puffin(P_CANNON, player->x, player->y,"cannon", 0); return B_TRUE; + } else if (s->id == P_HONEY) { + playfx(FX_POWERUP); + player->netsticky = B_TRUE; + sprintf(tempm, "Sticky net!"); + addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,&black,POINTSDELAY); + return B_TRUE; + } else if (s->id == P_LIFE) { + extralife(player); + return B_TRUE; } else if (s->id == P_PHONE) { sprite_t *s2, *nexts; playfx(FX_PHONE); @@ -4947,13 +4968,17 @@ void addscore(sprite_t *s, int amt) { // each multiple of 100,000 if (s == player) { if ((s->score / 100000) > (oldscore / 100000)) { - playfx(FX_LIFE); - s->lives++; - addoutlinetext(s->x,s->y - s->img->h/2, TEXTSIZE_LIFE, "Extra life!",&green,&black,LIFEDELAY); + extralife(s); } } } +void extralife(sprite_t *which) { + playfx(FX_LIFE); + which->lives += 1; + addoutlinetext(which->x,which->y - which->img->h/2, TEXTSIZE_LIFE, "Extra life!",&green,&black,LIFEDELAY); +} + void doice(void) { int yy,xx,changed; sprite_t *s; @@ -5238,3 +5263,20 @@ void initsdl(void) { } SDL_ShowCursor(SDL_DISABLE); } + +// player collects the given fruit +void getfruit(sprite_t *giveto, sprite_t *fruit) { + char tempm[MIDBUFLEN]; + int gotscore = fruit->score; + + /* kill the fruit */ + fruit->dead = D_FINAL; + /* give points to the player */ + addscore(giveto, gotscore); + /* handle fruit effects */ + if (!dofruiteffect(fruit)) { + playfx(FX_FRUIT); + sprintf(tempm, "%d", gotscore); + addoutlinetext(fruit->x,fruit->y - fruit->img->h/2, TEXTSIZE_POINTS, tempm, &white,&black,POINTSDELAY); + } +} diff --git a/rc.h b/rc.h index b7be8a0..b02bb94 100644 --- a/rc.h +++ b/rc.h @@ -50,6 +50,7 @@ int getpoints(int id); int isladder(int tid); char *addcommas(char *buffer, int num); void addscore(sprite_t *s, int amt); +void extralife(sprite_t *s); void doice(void); void checklevelend(void); void checksprites(void); @@ -64,3 +65,4 @@ int getjumpdelay(int mid); void togglepause(void); void togglefullscreen(void); void initsdl(void); +void getfruit(sprite_t *giveto, sprite_t *fruit); diff --git a/shared.c b/shared.c index d1b7e8b..fe34f51 100644 --- a/shared.c +++ b/shared.c @@ -567,6 +567,7 @@ void setdefaults(sprite_t *s) { s->gemboost = 1; s->powerup = 0; s->netbig = 0; + s->netsticky = B_FALSE; // player-only states s->netting = 0; s->netmax = 1; @@ -1147,9 +1148,15 @@ int loadimagesets(void) { loadspriteimage(P_BOMB,F_WALK1, "sprites/bomb.png"); imageset[P_BOMB].numimages = 1; + loadspriteimage(P_LIFE,F_WALK1, "sprites/dwarfhead-small.png"); + imageset[P_LIFE].numimages = 1; + loadspriteimage(P_PHONE,F_WALK1, "sprites/phone.png"); imageset[P_PHONE].numimages = 1; + loadspriteimage(P_HONEY,F_WALK1, "sprites/honey.png"); + imageset[P_HONEY].numimages = 1; + loadspriteimage(P_SHIELD,F_WALK1, "sprites/shield.png"); imageset[P_SHIELD].numimages = 1; @@ -1659,6 +1666,7 @@ int isfruit(int id) { case P_GEMBOOST: case P_BELL: case P_TROPHY: + case P_HONEY: return FT_PERM; /* one-off level only powerups */ case P_BOXING: @@ -1666,6 +1674,7 @@ int isfruit(int id) { case P_FTODIAMOND: case P_FTOGEM: case P_BOMB: + case P_LIFE: case P_PHONE: case P_HELMET: case P_SHIELD: @@ -1818,6 +1827,80 @@ void drawline16(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c + if (d < 0) { + d += dinc1; + x += xinc1; + y += yinc1; + } else { + d += dinc2; + x += xinc2; + y += yinc2; + } + } +} + +// draw line with alternating colours +void drawdotline16(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c, SDL_Color c2) { + int deltax, deltay; + int numpixels; + int d; + int dinc1,dinc2,xinc1,xinc2,yinc1,yinc2; + int i; + int x; + int y; + int maskcount = 0; + int maskindex = 0; + + + + deltax = (x2 - x1); + if (deltax < 0) deltax = -deltax; + deltay = (y2 - y1); + if (deltay < 0) deltay = -deltay; + + if (deltax >= deltay) { + numpixels = deltax + 1; + d = (deltay*2) - deltax; + dinc1 = deltay << 1; + dinc2 = (deltay-deltax) << 1; + xinc1 = 1; + xinc2 = 1; + yinc1 = 0; + yinc2 = 1; + } else { + numpixels = deltay + 1; + d = (deltax*2) - deltay; + dinc1 = deltax << 1; + dinc2 = (deltax - deltay) << 1; + xinc1 = 0; + xinc2 = 1; + yinc1 = 1; + yinc2 = 1; + } + + if (x1 > x2) { + xinc1 = - xinc1; + xinc2 = - xinc2; + } + if (y1 > y2) { + yinc1 = - yinc1; + yinc2 = - yinc2; + } + + x = x1; y = y1; + + maskcount = 0; + maskindex = 0; + for (i = 0; i < numpixels; i++) { + + if (i % 2 == 0) { + drawpixel16(screen,x,y,c); + } else { + drawpixel16(screen,x,y,c2); + } + + + if (d < 0) { d += dinc1; x += xinc1; @@ -2241,7 +2324,7 @@ int loadlevellist(void) { int randompowerup(void) { int num; - num = rand() % 20; + num = rand() % 22; switch (num) { case 0: @@ -2285,6 +2368,10 @@ int randompowerup(void) { return P_CANNONPOWERUP; case 19: return P_PHONE; + case 20: + return P_HONEY; + case 21: + return P_LIFE; } } @@ -2403,6 +2490,8 @@ void setfruitinfo(void) { setinfo(P_SPRAY, "Fly Spray", "Sickens all monsters, causing them to slow down to half speed.","spray.png"); setinfo(P_CANNONPOWERUP, "Fusion Cannon", "A powerful weapon which will shoot out laser beams in all directions!", "cannonpowerup.png"); setinfo(P_PHONE, "Phone", "Calls in your helper cloud and immediately skips two levels.", "phone.png"); + setinfo(P_HONEY, "Honey", "Coats your net in a layer of sticky honey, allowing it to pick up fruits from afar.", "honey.png"); + setinfo(P_RAT, "Rat", "The weakest of the monsters, the rat will simply walk back and forth waiting to be caught. Beward an angry rat though, as it will try to fall or jump in order to catch you!", "rat.png"); setinfo(P_BEE, "Bee", "Bees, while still relatively weak, gain an advantage over bats in that they are able to fly. They move in a simple diagonal pattern, changing direction when they get near a wall or spikes. Bees will speed up when angry.", "newbee.png"); diff --git a/shared.h b/shared.h index b65e03c..8e7e5a9 100644 --- a/shared.h +++ b/shared.h @@ -26,6 +26,7 @@ inline void drawpixel16(SDL_Surface *screen, int x, int y, SDL_Color c); inline void drawpixel32(SDL_Surface *screen, int x, int y, SDL_Color c); inline void drawbox16(SDL_Surface *screen, int x1,int y1,int x2,int y2,SDL_Color *c,SDL_Color *fc); void drawline16(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c); +void drawdotline16(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c, SDL_Color c2); int getcolor(SDL_Surface *dest, int x, int y, SDL_Color *col); /* int chartomonster(char ch);