- Turned off double buffering to increase speed

- Implemented lives - displayed underneath score
- Extra life at every 100,000 points
- Game over after you lose all your lives (with sound effect)
- Added commas to score display
- Increased time after hurryup from 10 secs to 15 secs
This commit is contained in:
Rob Pearce 2008-10-01 12:42:59 +00:00
parent 388f50ccfc
commit 81c812cf3c
16 changed files with 209 additions and 63 deletions

33
defs.h
View File

@ -4,7 +4,7 @@
#include <SDL_mixer.h>
/* 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;

View File

@ -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

View File

@ -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

217
rc.c
View File

@ -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);
}
}
}

2
rc.h
View File

@ -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);

View File

@ -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

Binary file not shown.

Binary file not shown.

BIN
sounds/gameover.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
sounds/life.wav Normal file

Binary file not shown.

BIN
sounds/peace.au Normal file

Binary file not shown.

BIN
sounds/splash-old1.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
sprites/dwarfhead-small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

BIN
sprites/dwarfhead.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB