diff --git a/defs.h b/defs.h index 9016f13..1e2a151 100644 --- a/defs.h +++ b/defs.h @@ -4,7 +4,7 @@ #include /* Macros */ -#define OPENGL +//#define OPENGL // sound channel numbers #define CH_LASTCHANNEL 21 @@ -27,16 +27,18 @@ #define PUFFAPPEAR 4 // frame at which puff will turn into a gem // text sizes +#define TEXTSIZE_POINTS 10 +#define TEXTSIZE_SCORE 14 +#define TEXTSIZE_BONUS 20 #define TEXTSIZE_HELP 20 #define TEXTSIZE_DEATH 20 -#define TEXTSIZE_POINTS 10 -#define TEXTSIZE_BONUS 20 -#define TEXTSIZE_BIFF 26 -#define TEXTSIZE_HURRY 50 -#define TEXTSIZE_BOMB 36 -#define TEXTSIZE_LEVEL 32 #define TEXTSIZE_LEVEL2 22 -#define TEXTSIZE_SCORE 14 +#define TEXTSIZE_BIFF 26 +#define TEXTSIZE_LEVEL 32 +#define TEXTSIZE_LIFE 36 +#define TEXTSIZE_BOMB 36 +#define TEXTSIZE_HURRY 50 +#define TEXTSIZE_GAMEOVER 50 // text delays #define TEXTSPEED 2 // how fast text zooms in @@ -45,10 +47,12 @@ #define POINTSDELAY 40 #define BONUSDELAY 50 #define HURRYDELAY 50 +#define LIFEDELAY 50 #define LEVELWINDELAY 80 -#define LEVELDELAY 100 #define DIEDELAY 80 #define HELPDELAY 80 +#define LEVELDELAY 100 +#define GAMEOVERDELAY 200 @@ -94,13 +98,13 @@ #define B_FALSE 0 // Other -#define WANTFPS 75 // try to run at this many frames per sec +#define WANTFPS 60 // try to run at this many frames per sec /* enums */ /* sounds */ -#define MAXFX 18 +#define MAXFX 19 #define FX_SHOOT 0 #define FX_SLAM 1 #define FX_KILL 2 @@ -119,6 +123,8 @@ #define FX_TELEPORT 15 #define FX_SPLASH 16 #define FX_MACE 17 +#define FX_LIFE 18 +#define FX_GAMEOVER 19 // Slope types #define S_NOTSOLID 0 @@ -193,6 +199,8 @@ #define LV_WAIT 2 // LEVEL COMPLETE displayed, delay to collect fruits #define LV_FINAL 3 // delay 5 seconds more... #define LV_NEXTLEV 4 // end of delay, nextlevel() in 5 seconds +#define LV_GAMEOVER 6 // No lives left. + // Tile types #define T_BLANK 0 @@ -322,6 +330,7 @@ typedef struct sprite_s { // CURRENT STATE // player only + int lives; int slamming; // are we slamming our net (player only) double slamangle;// are what point around is our net? int netting; // are we shooting our net out? @@ -393,7 +402,7 @@ imageset_t imageset[MAXPTYPES]; /* external globals */ extern SDL_Color black; -extern SDL_Surface *screen, *temps, *levelbg; +extern SDL_Surface *screen, *temps, *levelbg, *head, *headsmall; extern sprite_t *sprite, *lastsprite, *player; extern level_t *curlevel; extern tiletype_t fakeblock; diff --git a/globals.h b/globals.h index f933bef..74c5546 100644 --- a/globals.h +++ b/globals.h @@ -10,6 +10,7 @@ int numlevels; SDL_Surface *levelbg; // level background image SDL_Surface *temps; // temporary surface SDL_Surface *screen; // the actual video screen +SDL_Surface *head,*headsmall; // img in corner showing number of lives sprite_t *sprite; // head of sprite linked list sprite_t *lastsprite; // tail of sprite linked list sprite_t *player; // pointer to the player's sprite diff --git a/levels.dat b/levels.dat index ab620d2..3d2dd24 100644 --- a/levels.dat +++ b/levels.dat @@ -6,15 +6,15 @@ 7,level6.dat,Roller school 6,level5.5.dat,The Pit 8,level7.dat,Platforms and Ladders -9,level7.5.dat,The Snake Pit -10,level8.dat,Smile! 12,level9.dat,The Garden 14,level10.dat,Planks 15,level11.dat,The Hive +9,level7.5.dat,The Snake Pit 16,level11.5.dat,Underground Lakes 17,level12.dat,Bee Pods 18,level13.dat,Dual Hives 19,level14.dat,The Chimney +10,level8.dat,Smile! 11,level8.5.dat,Look out above... 99,level99.dat,TEST LEVEL 13,level9.5.dat,Back and Forth diff --git a/rc.c b/rc.c index 587e0f6..e6b2362 100644 --- a/rc.c +++ b/rc.c @@ -20,8 +20,8 @@ FPSmanager manager; SDL_Surface *temps; - SDL_Surface *screen; + TTF_Font *font[MAXLETTERHEIGHT]; Mix_Music *curmusic = NULL; // pointer to currently playing music @@ -94,6 +94,7 @@ int main (int argc, char **argv) { cheat = B_FALSE; levelbg = NULL; + /* handle arguments */ if (argc >= 2) { for (i = 1; i < argc; i++) { @@ -126,17 +127,22 @@ int main (int argc, char **argv) { atexit(cleanup); #ifdef OPENGL - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); + SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); + SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + //SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); screen = SDL_SetVideoMode(640,480,16,SDL_OPENGLBLIT|vidargs); #else - screen = SDL_SetVideoMode(640,480,16,SDL_SWSURFACE|SDL_DOUBLEBUF|vidargs); + //screen = SDL_SetVideoMode(640,480,16,SDL_SWSURFACE|SDL_DOUBLEBUF|vidargs); + screen = SDL_SetVideoMode(640,480,16,SDL_SWSURFACE|vidargs); #endif if (!screen) { - printf("Failed to open OpenGL window: %s\n", SDL_GetError()); + printf("Failed to open window: %s\n", SDL_GetError()); exit(1); } @@ -212,6 +218,7 @@ int main (int argc, char **argv) { player->invuln = INVULNTIME; player->score = 0; + player->lives = 3; while (1) { removeall(); @@ -222,12 +229,24 @@ int main (int argc, char **argv) { nextsprite = s->next; if (s->dead == D_FINAL) { if (s == player) { - /* TODO: lose a life */ - /* if we have lives left, go back to start position */ - setdefaults(s); - s->x = (curlevel->p1x * TILEW) + (TILEW/2); - s->y = (curlevel->p1y * TILEH) + (TILEH/2); - s->invuln = INVULNTIME; + if (player->lives > 0) { + /* if we have lives left, go back to start position */ + setdefaults(s); + s->x = (curlevel->p1x * TILEW) + (TILEW/2); + s->y = (curlevel->p1y * TILEH) + (TILEH/2); + s->invuln = INVULNTIME; + } else { + if (levelcomplete == LV_GAMEOVER) { + // TODO: Wait until "game over" text is gone, then slowly fade out the screen + // then show hiscores + // then back to title screen + } else { + addoutlinetext(320,240,TEXTSIZE_GAMEOVER,"Game Over",&red,&black,GAMEOVERDELAY); + levelcomplete = LV_GAMEOVER; + stopmusic(); + playfx(FX_GAMEOVER); + } + } } else { killsprite(s); // check for level completion @@ -239,7 +258,6 @@ int main (int argc, char **argv) { /* check for end of level */ if (levelcomplete == LV_CLEAR) { - addoutlinetext(320,240,TEXTSIZE_LEVEL,"Level Complete!",&green,&black,LEVELWINDELAY); levelcomplete = LV_WAIT; playfx(FX_WINLEVEL); @@ -273,6 +291,12 @@ int main (int argc, char **argv) { if (keys[SDLK_q]) { gtime = nexthurryup-1; } + if (keys[SDLK_p]) { + if (toggletimer == 0) { + addscore(player, 100001); + toggletimer = 80; + } + } if (keys[SDLK_n]) { if (toggletimer == 0) { nextlevel(); @@ -384,11 +408,6 @@ int main (int argc, char **argv) { } else { whichway = 0; } - if (player->ontramp) { - playfx(FX_SPRING); - } else { - playfx(FX_JUMP); - } jump(player, whichway); } @@ -431,7 +450,7 @@ int main (int argc, char **argv) { } } else { - if (player->netcaught < player->netmax) { + if ((player->netcaught < player->netmax) && (player->climbing == B_FALSE)) { /* shoot net */ playfx(FX_SHOOT); player->netting = 1; @@ -600,7 +619,7 @@ void tick(void) { stopmusic(); Mix_PlayChannel(CH_HURRYUP, sfx[FX_HURRYUP], 0); } - } else if (gtime == nexthurryup + 10) { + } else if (gtime == nexthurryup + 15) { // 15 secs after hurryup if (!levelcomplete) { addsprite(P_CLOUD, 320,240,"cloud"); addoutlinetext(320,240,TEXTSIZE_HURRY, "Too slow!", &red,&black,HURRYDELAY); @@ -723,7 +742,14 @@ void jump(sprite_t *s, int dir) { } } // stop climbing - player->climbing = B_FALSE; + s->climbing = B_FALSE; + if (s == player) { + if (player->ontramp) { + playfx(FX_SPRING); + } else { + playfx(FX_JUMP); + } + } } } @@ -746,6 +772,9 @@ void die(sprite_t *s) { if (s == player) { int tnum; + /* lose a life */ + player->lives--; + /* play sound */ playfx(FX_DIE); @@ -808,6 +837,8 @@ void checkcollide(sprite_t *s) { sprite_t *s2; int keepchecking; int xdiff,ydiff; + int ythresh; + int netsleft; for (s2 = sprite ; s2 ; s2 = s2->next) { @@ -828,7 +859,15 @@ void checkcollide(sprite_t *s) { ydiff = s->netystart - (s2->y - s2->img->h/2); if (ydiff < 0) ydiff = -ydiff; - if ((xdiff <= s2->img->w/2) && (ydiff <= s2->img->h)) { + // take numnets into account for y check + ythresh = s2->img->h; + netsleft = s->netmax - s->netcaught; + if (netsleft > 1) { + ythresh += ((int)s->img->h / (int)(netsleft+1) ); + } + + //if ((xdiff <= s2->img->w/2) && (ydiff <= s2->img->h)) { + if ((xdiff <= s2->img->w/2) && (ydiff <= ythresh)) { // we hit something! // if we have a boxing glove, it dies @@ -894,7 +933,7 @@ void checkcollide(sprite_t *s) { /* kill the fruit */ s2->dead = D_FINAL; /* give points to the player */ - player->score = player->score + gotscore; + addscore(player, gotscore); /* handle fruit effects */ if (!dofruiteffect(s2)) { playfx(FX_FRUIT); @@ -1716,24 +1755,25 @@ void dotileeffects(sprite_t *s) { finished = B_TRUE; } else if (tt->id == T_TRAMPUP) { /* tile changes to trampoline down */ - - // are we on a trampoline already? - if (s->ontramp) { - // a different one? - if ((s->trampx != tilex) || (s->trampy != tiley)) { - // if a different one, release it - curlevel->map[s->trampy * LEVELW + s->trampx] = getuniq(T_TRAMPUP); - drawtile(temps, s->trampx, s->trampy); + if (!isfruit(s->id) && !iseffect(s->id) && !isbullet(s->id)) { + // are we on a trampoline already? + if (s->ontramp) { + // a different one? + if ((s->trampx != tilex) || (s->trampy != tiley)) { + // if a different one, release it + curlevel->map[s->trampy * LEVELW + s->trampx] = getuniq(T_TRAMPUP); + drawtile(temps, s->trampx, s->trampy); + } + } else { + // remember we were on it so it can release + s->ontramp = B_TRUE; + s->trampx = tilex; + s->trampy = tiley; + + // move it down then draw it + curlevel->map[tiley*LEVELW+tilex] = getuniq(T_TRAMPDOWN); + drawtile(temps, tilex, tiley); } - } else { - // remember we were on it so it can release - s->ontramp = B_TRUE; - s->trampx = tilex; - s->trampy = tiley; - - // move it down then draw it - curlevel->map[tiley*LEVELW+tilex] = getuniq(T_TRAMPDOWN); - drawtile(temps, tilex, tiley); } finished = B_TRUE; } else if (tt->id == T_TRAMPDOWN) { @@ -1763,7 +1803,7 @@ void drawlevel(void) { int turns; double pxspeed,pyspeed; SDL_Rect area,dst; - int speed = 8; + int speed = 16; SDL_Surface *playerbg; /* TODO: chekc for memory leak here with temps - @@ -1778,6 +1818,8 @@ void drawlevel(void) { screen->format->Gmask,screen->format->Bmask, screen->format->Amask); + SDL_DisplayFormat(temps); + // change player to floating image player->img = imageset[P_PLAYER].img[F_SHOOT]; @@ -1787,9 +1829,10 @@ void drawlevel(void) { screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); + SDL_DisplayFormat(playerbg); - // draw the full level onto a temporary surface + // draw the full level onto the temporary surface for (x = 0; x < LEVELW; x++) { for (y = 0; y < LEVELH; y++) { drawtile(temps,x,y); @@ -1805,15 +1848,19 @@ void drawlevel(void) { xdis = player->x - dstx; if (xdis < 0) xdis = -xdis; ydis = player->y - dsty; if (ydis < 0) ydis = -ydis; + + // figure out how many loops it will take to scroll to the next level switch (oldexitdir) { case D_LEFT: case D_RIGHT: + speed = 16; turns = 640 / speed; break; case D_UP: case D_DOWN: default: + speed = 12; turns = 480 / speed; break; } @@ -2126,8 +2173,9 @@ void movetext(void) { void drawscore(void) { SDL_Surface *score; SDL_Rect area; + int i; - sprintf(tempm, "%d",player->score); + addcommas(tempm, player->score); /* shadow */ score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], tempm, black); @@ -2145,6 +2193,37 @@ void drawscore(void) { area.h = 0; SDL_BlitSurface(score, NULL, screen, &area); SDL_FreeSurface(score); + + // lives +/* + sprintf(livestext, "x %d",3); + + + score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], livestext, black); + area.x = 38; + area.y = 27; + area.w = 0; + area.h = 0; + SDL_BlitSurface(score, NULL, screen, &area); + SDL_FreeSurface(score); + score = TTF_RenderText_Solid(font[TEXTSIZE_SCORE], livestext, red); + area.x = 40; + area.y = 25; + area.w = 0; + area.h = 0; + SDL_BlitSurface(score, NULL, screen, &area); + SDL_FreeSurface(score); +*/ + + // lives - show 1 less than lives + area.x = 20; + area.y = 20; + area.w = 0; + area.h = 0; + for (i = 1; i < player->lives; i++) { + SDL_BlitSurface(head, NULL, screen, &area); + area.x += (head->w + 3); + } } void drawtext(void) { @@ -2780,7 +2859,8 @@ void dogravity(sprite_t *s) { sprintf(tempm, "%d",pointsinc); addoutlinetext(xnet,ynet-TILEH, psize, tempm, &white,&black,POINTSDELAY); /* give points to player */ - s->score += pointsinc; + //s->score += pointsinc; + addscore(s, pointsinc); } } // end if slamangle > 180degrees @@ -3147,6 +3227,8 @@ int initsound(void) { loadfx(FX_TELEPORT, "teleport.wav"); loadfx(FX_SPLASH, "splash.wav"); loadfx(FX_MACE, "mace.wav"); + loadfx(FX_LIFE, "life.wav"); + loadfx(FX_GAMEOVER, "gameover.wav"); // load sound effects @@ -3250,7 +3332,6 @@ SDL_Surface *grabbehind(sprite_t *s, SDL_Surface *surf) { int randompowerup(void) { int num; num = rand() % 9; - return P_BOXING; switch (num) { case 0: @@ -3305,3 +3386,51 @@ void addoutlinetext(int x, int y, int size, char *msg, SDL_Color *col, SDL_Color addtext(x-1,y+1,size,msg,bgcol,delay); // outline addtext(x,y,size,msg,col,delay); // main text } + +char *addcommas(char *buffer, int num) { + char tempbuf[MIDBUFLEN]; + char *p; + char *p2; + int count; + + sprintf(tempbuf, "%d",num); + + p2 = buffer; + p = tempbuf; + if (strlen(tempbuf) <= 3) { + strcpy(buffer,tempbuf); + return buffer; + } else { + count = ((strlen(tempbuf)-1) % 3)+1; + } + + for (p = tempbuf; *p; p++) { + if (count == 0) { + count = 3; + *p2 = ','; + p2++; + } + *p2 = *p; + p2++; + count--; + } + *p2 = '\0'; + + return buffer; +} + +void addscore(sprite_t *s, int amt) { + int oldscore; + oldscore = s->score; + + s->score += 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); + } + } +} diff --git a/rc.h b/rc.h index 1870731..7141c9f 100644 --- a/rc.h +++ b/rc.h @@ -47,3 +47,5 @@ void dumpsprites(void); void countmonsters(void); int getpoints(int id); int isladder(int tid); +char *addcommas(char *buffer, int num); +void addscore(sprite_t *s, int amt); diff --git a/shared.c b/shared.c index 35707ed..29f7a07 100644 --- a/shared.c +++ b/shared.c @@ -293,13 +293,13 @@ int loadlevel(int wnum, int lnum) { fgets(buf, BUFLEN, f); } -printf("got %d monsters\n", numenemies); /* exitdir ? */ if (strstr(buf, "exitdir")) { p = strtok(buf, " "); // "exitdir" p = strtok(NULL, " "); level->exitdir = atoi(p); + /* printf("Exit direction is "); switch (level->exitdir) { case D_RIGHT: @@ -315,6 +315,7 @@ printf("got %d monsters\n", numenemies); printf("*INVALID*"); break; } + */ printf("\n"); fgets(buf, BUFLEN, f); } else { @@ -562,7 +563,7 @@ printf("got %d monsters\n", numenemies); if (!feof(f)) { int tid,xx,yy; - printf("found second layer\n"); + //printf("found second layer\n"); // second layer exists - read it fgets(buf, BUFLEN, f); while (!feof(f)) { @@ -722,7 +723,9 @@ void setdefaults(sprite_t *s) { } - s->score = getpoints(s->id); + if (s != player) { + s->score = getpoints(s->id); + } s->caughtby = NULL; s->caughtstate = 0; @@ -971,9 +974,11 @@ int loadtiletypes(char *filename) { int loadimagesets(void) { int p,i; SDL_Surface *tempimg; - SDL_Surface *reds; + head = IMG_Load("sprites/dwarfhead.png"); + headsmall = IMG_Load("sprites/dwarfhead-small.png"); + loadspriteimage(P_PLAYER,F_WALK1, "sprites/pdwarf.png"); loadspriteimage(P_PLAYER,F_JUMP, "sprites/pdwarfjump.png"); loadspriteimage(P_PLAYER,F_FALL, "sprites/pdwarffall.png"); @@ -1405,8 +1410,8 @@ void killsprite(sprite_t *s) { void flip(void) { #ifdef OPENGL - SDL_GL_SwapBuffers(); SDL_UpdateRect(screen,0,0,screen->w,screen->h); + SDL_GL_SwapBuffers(); #else SDL_Flip(screen); #endif diff --git a/sounds/bonus.au b/sounds/bonus.au deleted file mode 100644 index c7ad4bb..0000000 Binary files a/sounds/bonus.au and /dev/null differ diff --git a/sounds/die.au b/sounds/die.au deleted file mode 100644 index c741b19..0000000 Binary files a/sounds/die.au and /dev/null differ diff --git a/sounds/gameover.wav b/sounds/gameover.wav new file mode 100644 index 0000000..a5b9e51 Binary files /dev/null and b/sounds/gameover.wav differ diff --git a/sounds/kill.au b/sounds/kill.au deleted file mode 100644 index 71a4f05..0000000 Binary files a/sounds/kill.au and /dev/null differ diff --git a/sounds/life.wav b/sounds/life.wav new file mode 100644 index 0000000..99405e3 Binary files /dev/null and b/sounds/life.wav differ diff --git a/sounds/peace.au b/sounds/peace.au new file mode 100644 index 0000000..56bdf5e Binary files /dev/null and b/sounds/peace.au differ diff --git a/sounds/splash-old1.wav b/sounds/splash-old1.wav new file mode 100644 index 0000000..f0c5638 Binary files /dev/null and b/sounds/splash-old1.wav differ diff --git a/sounds/winlevel.au b/sounds/winlevel.au deleted file mode 100644 index 8a534bf..0000000 Binary files a/sounds/winlevel.au and /dev/null differ diff --git a/sprites/dwarfhead-small.png b/sprites/dwarfhead-small.png new file mode 100644 index 0000000..f7da02a Binary files /dev/null and b/sprites/dwarfhead-small.png differ diff --git a/sprites/dwarfhead.png b/sprites/dwarfhead.png new file mode 100644 index 0000000..14687ec Binary files /dev/null and b/sprites/dwarfhead.png differ