#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "shared.h" #include "rc.h" FPSmanager manager; SDL_Surface *temps; SDL_Surface *screen; TTF_Font *font[MAXLETTERHEIGHT]; Mix_Music *curmusic = NULL; // pointer to currently playing music char tempm[BUFLEN]; tiletype_t fakeblock; /* the order in which fruit will appear */ int fruittypes[] = { P_CHEESE, P_ICECREAM, P_CHIPS, P_BURGER, -1 }; /* the order in which powerups will appear */ int poweruptypes[] = { P_SPEED, P_NUMNETS, P_BIGNET, P_NUMNETS, -1 }; int curfruittype = 0; int curpoweruptype = 0; int gtime = 0; int fpsticks = 0; int fpsstart = 0; int curworld = 1; int curlevelnum; level_t *curlevel; int levelcomplete = B_FALSE; int levelcompletetime = -1; sprite_t *sprite = NULL; /* main sprite list */ sprite_t *player; sprite_t *lastsprite; text_t *text, *lasttext; SDL_Color red = {255, 0, 0, 0}; SDL_Color black = {0, 0, 0, 0}; SDL_Color white = {255, 255, 255, 0}; SDL_Color green = {0, 255, 0, 0}; SDL_Color yellow = {255, 255, 0, 0}; int vidargs = 0; int timer = 0; int toggletimer = 0; int main (int argc, char **argv) { Uint8 *keys; sprite_t *s,*nextsprite; char filename[BUFLEN]; int i; int *animtile; curlevelnum = 1; musicplaying = B_FALSE; /* handle arguments */ if (argc >= 2) { for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-fs")) { printf("Fullscreen mode enabled.\n"); vidargs |= SDL_FULLSCREEN; } else if (!strcmp(argv[i], "-l")) { if (++i >= argc) { printf("Missing level number.\n"); usage(); exit(1); } curlevelnum = atoi(argv[i]); printf("Skipping to level %d.\n",curlevelnum); } else { usage(); exit(1); } } } if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE)==-1) { printf("SDL_Init: %s\n", SDL_GetError()); exit(1); } 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_DOUBLEBUFFER, 1); screen = SDL_SetVideoMode(640,480,16,SDL_OPENGLBLIT|vidargs); #else screen = SDL_SetVideoMode(640,480,16,SDL_SWSURFACE|SDL_DOUBLEBUF|vidargs); #endif if (loadimagesets()) { return 1; } fakeblock.id = T_LAND; strcpy(fakeblock.name,"Fake"); for (i = 0; i < TILEW; i++) { fakeblock.lowness[i] = 0; } fakeblock.solid = S_SOLID; fakeblock.img[0] = IMG_Load("land.bmp"); fakeblock.numframes = 1; fakeblock.next = NULL; fakeblock.prev = NULL; /* load fonts */ TTF_Init(); sprintf(filename, "verdana.ttf"); for (i = 1; i < MAXLETTERHEIGHT; i++) { font[i] = TTF_OpenFont(filename,i); if (!font[i]) { printf("Error opening font: %s\n", TTF_GetError()); return 1; } } /* calculate fps delay */ SDL_initFramerate(&manager); SDL_setFramerate(&manager, WANTFPS); /* init sound */ if (initsound()) { printf("sound error.\n"); return 1; } playmusic(normalmusic); if (loadlevel(curworld,curlevelnum)) { return 1; } drawlevel(); flip(); timer = 0; player->invuln = INVULNTIME; player->score = 0; while (1) { /* removetext(); for (s = sprite ; s ; s = s->next) { removesprite(s); } removenetting(player); */ removeall(); /* check for death & update movement status*/ for (s = sprite ; s ; s = nextsprite) { s->moved = B_FALSE; 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; } else { killsprite(s); } } } /* check for end of level */ if (levelcomplete == 1) { addtext(318,242,32,"Level Complete!",&black,LEVELDELAY); addtext(320,240,32,"Level Complete!",&yellow,LEVELDELAY); levelcomplete = 2; playfx(FX_WINLEVEL); } else if (levelcomplete == 2) { int mcount = 0; sprite_t *s2; /* when all monsters have become fruits */ for (s2 = sprite->next ; s2 ; s2 = s2->next) { if (ismonster(s2->id)) { if (s2->id != P_CLOUD) { mcount++; break; } } } if (mcount == 0) { levelcompletetime = gtime; levelcomplete = 3; } } /* check for keys */ SDL_PumpEvents(); keys = SDL_GetKeyState(NULL); if (keys[SDLK_q]) { gtime = curlevel->hurryuptime -1; } if (keys[SDLK_RETURN]) { if (toggletimer == 0) { SDL_WM_ToggleFullScreen(screen); toggletimer = 50; } } if (keys[SDLK_ESCAPE]) { return 1; } if ((!player->dead) && (!player->teleporting)) { if (keys[SDLK_RIGHT]) { if (canmove(player)) { movex(player, getspeed(player)); } if (canturn(player)) { player->dir = D_RIGHT; } } if (keys[SDLK_LEFT]) { if (canmove(player)) { movex(player, -getspeed(player)); } if (canturn(player)) { player->dir = D_LEFT; } } if (keys[SDLK_UP]) { if (isonladder(player) || isladderabove(player)) { player->y -= getspeed(player); player->jumping = 0; player->falling = 0; player->climbing = B_TRUE; } } if (keys[SDLK_DOWN]) { if (isonladder(player)) { player->y += getspeed(player); player->jumping = 0; player->falling = 0; player->climbing = B_TRUE; } } if (keys[SDLK_x]) { if (isinwater(player)) { player->jumping = B_FALSE; player->falling = B_FALSE; if (!isroofabove(player)) { player->y -= (getspeed(player)*3); } } else { if (!player->jumping) { if (!player->falling) { if (isonground(player) || isonladder(player)) { /* dropping through a bridge */ if (keys[SDLK_DOWN]) { if (isonbridge(player) && !player->falling) { /* drop down */ player->dropping = B_TRUE; player->dropx = player->x / TILEW; player->dropy = player->y / TILEH; } } else { int whichway; player->climbing = B_FALSE; if (keys[SDLK_RIGHT]) { whichway = 1; } else if (keys[SDLK_LEFT]) { whichway = -1; } else { whichway = 0; } playfx(FX_JUMP); jump(player, whichway); } } } } } } if (keys[SDLK_z]) { if ((!player->netting) && (!player->slamming)) { if (keys[SDLK_DOWN]) { /* slam */ if ((!player->slamming) && (isonground(player))) { playfx(FX_SLAM); player->slamming = B_TRUE; player->slamangle = 0; player->netxstart = player->x - (player->img->w/2)*player->dir; player->netystart = player->y; } } else { if (player->netcaught < player->netmax) { /* shoot net */ playfx(FX_SHOOT); player->netting = 1; if (player->netbig) { player->netspeed = NETSPEED+3; } else { player->netspeed = NETSPEED; } player->netlen = 0; player->netdir = player->dir; } } } } } // for each animated tile on the level... for (animtile = curlevel->animtiles; animtile && *animtile != -1; animtile++) { int offset,numframes; tiletype_t *tt; offset = *animtile; tt = gettile(curlevel->map[offset]); numframes = tt->numframes; // is it time to change frames? if ((timer % tt->animspeed) == 0) { // change its frame curlevel->tileframe[offset]++; if (curlevel->tileframe[offset] >= numframes) { curlevel->tileframe[offset] = 0; } // redraw it drawtile(temps, offset%LEVELW,offset/LEVELW); } } // move sprites for (s = sprite; s ; s = s->next) { movesprite(s); } movetext(); /* gravity */ for (s = sprite ; s ; s = s->next) { dogravity(s); } /* tile effects */ for (s = sprite ; s ; s = s->next) { dotileeffects(s); } /* check collisions */ //for (s = sprite ; s ; s = s->next) { // checkcollide(s); //} checkcollide(player); drawscore(); drawnetting(player); /* draw player */ for (s = sprite ; s ; s = s->next) { drawsprite(s); } /* draw text */ drawtext(); flip(); if (++timer == 100) timer = 0; if (toggletimer > 0) toggletimer--; tick(); } return 0; } void tick(void) { sprite_t *s; SDL_framerateDelay(&manager); fpsticks = SDL_GetTicks(); if (fpsstart == 0) { fpsstart = fpsticks; } else { /* once per second */ if (fpsticks - fpsstart >= 1000) { gtime++; /* */ if (gtime == curlevel->hurryuptime) { if (!levelcomplete) { for (s = sprite; s; s = s->next) { if ((s != player) && (!isfruit(s->id))) { s->angry = B_TRUE; } } addtext(320,240,TEXTSIZE_HURRY, "Hurry up!", &yellow,HURRYDELAY); stopmusic(); Mix_PlayChannel(CH_HURRYUP, sfx[FX_HURRYUP], 0); } } else if (gtime == curlevel->hurryuptime + 10) { if (!levelcomplete) { addsprite(P_CLOUD, 320,240,"cloud", B_FALSE); addtext(320,240,TEXTSIZE_HURRY, "Too slow!", &red,HURRYDELAY); playfx(FX_TOOSLOW); } } /* 5 seconds after level completion */ if (levelcomplete == 3) { if (gtime - levelcompletetime >= 5) { if (!player->dead) { nextlevel(); } } } fpsstart = fpsticks; } } } void nextlevel(void) { /* go to next level */ curlevelnum++; if (!musicplaying || (curmusic == fastmusic)) { playmusic(normalmusic); } loadlevel(curworld,curlevelnum); drawlevel(); levelcomplete = B_FALSE; levelcompletetime = -1; /* reset player stats */ player->netting = B_FALSE; player->slamming = B_FALSE; player->jumping = B_FALSE; } void jump(sprite_t *s, int dir) { if (s->jumping) return; if (s->jumptimer) return; if (isonground(s)) { if (ismonster(s->id)) { s->jumpdir = dir; if (s->jumpdir != 0) { s->dir = s->jumpdir; } s->jumptimer = 60; } else { s->jumpdir = dir; if (s->jumpdir != 0) { s->dir = s->jumpdir; } s->jumping = 1; s->jumpspeed = 5; } } } void die(sprite_t *s) { int mcount = 0; sprite_t *s2; /* clouds can't die like this */ if (s->id == P_CLOUD) return; /* if this is the player, hurryup time counter resets */ // We already do this in the cloud movement routine, but // this handles cases where the cloud hasn't appeared yet. if (s == player) { gtime = 0; if (curmusic == fastmusic) { playmusic(normalmusic); } // reset powerup types curpoweruptype = 0; } if (s == player) { /* play sound */ playfx(FX_DIE); } /* release anything we've caught */ for (s2 = sprite->next ; s2 ; s2 = s2->next) { if (s2->caughtby == s) { s2->caughtby = NULL; s2->angry = B_TRUE; } } /* set death attribute */ s->dead = D_INITIAL; s->netting = 0; s->slamming = 0; /* any monsters left? */ if (!levelcomplete) { for (s2 = sprite->next ; s2 ; s2 = s2->next) { if (ismonster(s2->id) && !s2->dead) { if (s2->id != P_CLOUD) { mcount++; break; } } } if (mcount == 0) { levelcomplete = 1; } } } void cleanup(void) { int i; Mix_HaltMusic(); Mix_CloseAudio(); for (i = 1; i < MAXLETTERHEIGHT; i++) { TTF_CloseFont(font[i]); } TTF_Quit(); SDL_Quit(); } void checkcollide(sprite_t *s) { sprite_t *s2; int collide; int xdiff,ydiff; for (s2 = sprite ; s2 ; s2 = s2->next) { collide = B_TRUE; if (s2 == s) collide = B_FALSE; else if (s->dead) collide = B_FALSE; else if (s2->dead) collide = B_FALSE; else if (s->caughtby) collide = B_FALSE; else if (s2->caughtby) collide = B_FALSE; if (collide) { /* check for colission with our net */ if ((s->netting) && (!s2->caughtby)) { if (s->netcaught < s->netmax) { if (ismonster(s2->id) && s2->id != P_CLOUD) { xdiff = (s->x + s->netlen*s->netdir) - s2->x; if (xdiff < 0) xdiff = -xdiff; ydiff = s->netystart - (s2->y - s2->img->h/2); if (ydiff < 0) ydiff = -ydiff; if ((xdiff <= s2->img->w/2) && (ydiff <= s2->img->h)) { s2->caughtby = s; s2->jumping = 0; s2->falling = 0; s2->caughtstate = C_NETTING; s->netcaught++; } } } } else { /* check for collision with 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; if ((xdiff <= s->img->w/2 + s2->img->w/2) && (ydiff <= s->img->h/2 + s2->img->h/2)) { /* COLLISION! */ if (isfruit(s2->id) && (s2->teleporting == 0)) { if (s == player) { int gotscore = s2->score; /* kill the fruit */ s2->dead = D_FINAL; /* give points to the player */ player->score = player->score + gotscore; /* handle fruit effects */ if (!dofruiteffect(s2)) { playfx(FX_FRUIT); sprintf(tempm, "%d", gotscore); addtext(s2->x,s2->y - s2->img->h/2, TEXTSIZE_POINTS, tempm, &white,POINTSDELAY); } } } if (ismonster(s2->id) || isbullet(s2->id)) { if ((s == player) && (!s->invuln)) { die(s); } } } } } } } // do death bouncing effect void bouncesprite(sprite_t *s) { s->x += s->xs; s->y += s->ys; if (s->x >= (640-TILEW-(s->img->w/2))) { // move back onto screen while (s->x >= (640-TILEW-(s->img->w/2))) { s->x--; } if (s->xs > 0) s->xs = -s->xs; // reverse direction s->bounces++; } else if (s->x <= TILEW+s->img->w/2) { // move back onto screen while (s->x <= TILEW+s->img->w/2) { s->x++; } if (s->xs < 0) s->xs = -s->xs; // reverse direction s->bounces++; } if (s->y >= (480-(s->img->h/2))) { while (s->y >= (480-(s->img->h/2))) { s->y--; } if (s->ys > 0) s->ys = -s->ys; // reverse direction s->bounces++; } else if (s->y <= s->img->h) { while (s->y <= s->img->h) { s->y++; } if (s->ys < 0) s->ys = -s->ys; // reverse direction s->bounces++; } } void movesprite(sprite_t *s) { int rv; tiletype_t *tt; /* timer */ if (s->doomcount) { s->doomcount--; if (s->doomcount == 0) { s->dead = D_FINAL; } } /* avoid edges of screen */ if (s->y < s->img->h) { if (!s->flies) { s->y = s->img->h; } } if (s->x > (640 - s->img->w/2)) { s->x = 640 - s->img->w/2; } if (s->x < (s->img->w/2)) { s->x = s->img->w/2; } if (s->invuln) { s->invuln--; } if (s->caughtby) { if (s->caughtby->slamming) { /* */ s->x = s->caughtby->netxstart; s->y = s->caughtby->netystart; } else { /* stay at position of net */ s->y = s->caughtby->y; if (s->caughtstate == C_NETTING) { s->x = s->caughtby->x + (s->caughtby->netlen*s->caughtby->netdir); } else { s->x = s->caughtby->x + (s->caughtby->img->w/2) * -(s->caughtby->dir); } } return; } else if (s->dead == D_INITIAL) { /* just set to dead */ // 0 through 5 s->xs = 0.5 + ((rand() % 50) / 10); // 0.5 through 5.5 if (rand() % 2) { // 50% change of going left s->xs = s->xs * -1; } s->ys = -1 * (4 + ((rand() % 30) / 10)); // -4 through -7 s->dead = D_BOUNCING; s->bounces = 0; if (s == player) { s->jumpspeed = 8; s->jumping = 1; } return; } else if (s->dead == D_BOUNCING) { /* dying */ if (s == player) { /* shoot up in the air, then fall */ s->y -= s->jumpspeed; s->jumping++; if (s->jumping % 5 == 0) { s->jumpspeed--; } /* if we've fallen off the bottom... */ if (s->y >= 480) { /* pause before respawning */ s->jumpspeed = 0; /* this is now a timer */ s->dead = D_LASTBOUNCE; } } else { /* bounch around the screen 3 times */ bouncesprite(s); if ((s->bounces >= 2) && (s->ys > 0)) { // make sure we're not on the ground if (!isonground(s)) { int tx,ty; tiletype_t *tt; tt = gettileat(s->x,s->y,&tx,&ty); printf("finished bouncing, sprite is at: %d, %d (tileid %d)\n",tx,ty,tt->id); s->dead = D_LASTBOUNCE; } } } return; } else if (s->dead == D_LASTBOUNCE) { /* final fall */ if (s == player) { /* just delay... */ s->jumpspeed++; if (s->jumpspeed == 50) { /* really die */ s->dead = D_FINAL; } } else { /* bounce around, stop when we hit the ground */ bouncesprite(s); /* OLD BOUNCE CODE if (s->x >= (640-TILEW- s->img->w/2)) { if (s->xs > 0) { s->xs = -s->xs; s->bounces++; } } else if (s->x <= TILEW + s->img->w/2) { if (s->xs < 0) { s->xs = -s->xs; s->bounces++; } } if (s->y >= (480-(s->img->h/2))) { if (s->ys > 0) { s->ys = -s->ys; s->bounces++; } } else if (s->y <= s->img->h) { if (s->ys < 0) { s->ys = -s->ys; s->bounces++; } } */ if ((s->ys > 0) && (s->y >= TILEH)) { if (isonground(s)) { int x,y,ty; s->dead = D_FINAL; /* change into a fruit */ x = s->x; gettileat(s->x,s->y-1,NULL,&ty); //y = ty*TILEH + TILEH - 2; y = ty*TILEH - 2; /* make sure it's within the screen */ if (x > (640-TILEW)) x = 640-TILEW; if (x < (TILEW)) x = TILEW; //addsprite(s->willbecome, x, y, "Fruit", B_FALSE); puffin(s->willbecome, x, y, 0); //ss = addsprite(P_PUFF, x, y, "Fruit", B_FALSE); //ss->timer3 = s->willbecome; } } } return; } else if (s->teleporting > 0) { SDL_Surface *ts; if (timer % 2 == 0) { /* shrink */ if (s->teleporting == TP_SHRINKING) { ts = rotozoomSurfaceXY(s->img,0, 0.9 , 0.9 ,0); s->img = ts; } else { ts = rotozoomSurfaceXY(s->img,0, 0.9 , 0.9 ,0); SDL_FreeSurface(s->img); s->img = ts; } if ((s->img->w <= 2) || (s->img->h <= 2)) { /* go to tele dest */ int x,y; /* find destination */ for (y = 0; y < LEVELH; y++) { for (x = 0; x < LEVELW; x++) { tt = gettile(curlevel->map[y*LEVELW+x]); if (tt->id == T_TELEPORTDEST) { /* teleport there */ s->x = (x * TILEW) + (TILEW/2); s->y = (y * TILEH) + TILEH-2; } } } s->teleporting = -1; } else s->teleporting++; } } else if (s->teleporting < 0) { double size; if (timer % 2 == 0) { /* grow */ size = (double)-s->teleporting / 10; SDL_FreeSurface(s->img); if (size >= 1) { s->teleporting = 0; s->img = imageset[s->id].img[F_WALK1]; } else { s->img = rotozoomSurfaceXY(imageset[s->id].img[F_WALK1],0,size,size,0); s->teleporting--; } } } else if (s->jumping) { movex(s, s->jumpdir*getspeed(s)); return; } if (!iseffect(s->id)) { if (isonground(s)) { if ((!s->falling) && (!s->jumping)) { if (!s->climbing && !s->dropping) { adjustheight(s); } } } } /* sprite is about to jump */ if (s->jumptimer) { s->jumptimer--; if (s->jumptimer == 0) { s->jumping = 1; s->jumpspeed = 5; if (s->jumpdir != 0) s->dir = s->jumpdir; return; } else if (s->jumptimer % 20 == 0) { s->dir = -s->dir; } } else if (s->id == P_PUFF) { /* SUMMARY: timer1: indicates current frame. if < 0, don't draw. if >= PUFFFRAMES, use last frame. when timer1 gets to PUFFAPPEAR, create a gem of type s-> timer2: loops from 0 to 9. at intervals of PUFFSPEED, increment timer1. */ // still delaying if (s->timer1 < 0) { // increment "frame" s->timer1++; } else { // increment frame at a slower pace if (++s->timer2 >= 10) { s->timer2 = 0; } if (timer % PUFFSPEED == 0) { s->timer1++; // finished animating if (s->timer1 == PUFFAPPEAR) { // create a gem/fruit/etc addsprite(s->timer3, s->x,s->y,"gem", B_FALSE); } else if (s->timer1 >= PUFFFRAMES) { s->dead = D_FINAL; } } } } else if (s->id == P_RAT) { if (!s->falling) { int move = B_FALSE; int xdiff, absxdiff; /* distance to player */ xdiff = player->x - s->x; if (xdiff < 0) absxdiff = -xdiff; else absxdiff = xdiff; tt = gettileat(s->x + s->dir+getspeed(s),s->y,NULL,NULL); /* if there's a hole in front of us */ if (tt->solid == S_NOTSOLID) { if ((player->y > s->y) && (s->angry)) { /* if player is below, fall off */ if (xdiff <= (TILEW*8)) { move = B_TRUE; } } else if (player->y == s->y) { if (s->angry) { /* if player is at same level and close, jump */ if ((s->dir == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) { jump(s,D_RIGHT); } else if ((s->dir == D_LEFT) && (xdiff < 0) && (xdiff >= -(TILEW*7))) { jump(s,D_LEFT); } } } } else { move = B_TRUE; } /* either move or turn around */ if (move) { rv = movex(s, s->dir*getspeed(s)); if (rv) { /* if we couldn't move (hit a wall), turn */ s->dir = -s->dir; } } else { s->dir = -s->dir; } if (s->angry) { if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) { /* if player is above us, jump */ if (player->y < s->y) { if ((xdiff >= (TILEW*2)) && (xdiff <= (TILEW*3))) { /* jump right */ jump(s, 1); } else if ((xdiff <= -(TILEW*2)) && (xdiff >= -(TILEW*3))) { /* jump left */ jump(s, -1); } else if (s->y - player->y <= (TILEH*6)) { if ((xdiff >= 0) && (xdiff < (TILEW*2))) { /* jump up */ jump(s, 0); } else if ((xdiff <= 0) && (xdiff > -(TILEW*2))) { /* jump up */ jump(s, 0); } } else { /* jump whichever way we're facing */ /* s->jumpdir = s->dir; s->jumping = 1; s->jumpspeed = 5; */ } } } } } } else if (s->id == P_COKE) { if (!s->falling) { int move = B_FALSE; int xdiff, absxdiff; /* distance to player */ xdiff = player->x - s->x; if (xdiff < 0) absxdiff = -xdiff; else absxdiff = xdiff; tt = gettileat(s->x + s->dir+getspeed(s),s->y,NULL,NULL); /* if there's a hole in front of us */ if (tt->solid == S_NOTSOLID) { if (player->y > s->y ) { /* if player is below and nearby, fall off */ if (xdiff <= (TILEW*16)) { move = B_TRUE; } } else if (player->y == s->y) { /* if player is at same level and close, jump */ if ((s->dir == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) { jump(s,D_RIGHT); } else if ((s->dir == D_LEFT) && (xdiff < 0) && (xdiff >= -(TILEW*7))) { jump(s,D_LEFT); } } } else { move = B_TRUE; } /* either move or turn around */ if (move) { rv = movex(s, s->dir*getspeed(s)); if (rv) { /* if we couldn't move (hit a wall), turn */ s->dir = -s->dir; } } else { s->dir = -s->dir; } /* moves like an angry rat all the time */ if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) { /* if player is above us...*/ if (player->y < s->y) { if ((xdiff >= (TILEW*2)) && (xdiff <= (TILEW*3))) { // if 2-3 tiles right /* jump right */ jump(s, D_RIGHT); } else if ((xdiff <= -(TILEW*2)) && (xdiff >= -(TILEW*3))) { // if 2-3 tiles left /* jump left */ jump(s, D_LEFT); } else if (s->y - player->y <= (TILEH*6)) { // player less than 6 tiles above if ((xdiff >= 0) && (xdiff < (TILEW*4))) { // ... and within 4 tiles /* jump up */ jump(s, 0); } else if ((xdiff <= 0) && (xdiff > -(TILEW*4))) { // ... and within 4 tiles /* jump up */ jump(s, 0); } } } } } } else if (s->id == P_SNAKE) { /* timer1 loopsfrom 0 - 19 if timer2 is 0, we can shoot. if it is 1, we can't. */ // inc shooting timer if (s->timer1) { s->timer1--; if (s->timer1 == 0) { printf("can shoot again\n"); } } if (!s->falling) { int move = B_FALSE; int xdiff, absxdiff,ydiff; /* distance to player */ xdiff = player->x - s->x; if (xdiff < 0) absxdiff = -xdiff; else absxdiff = xdiff; tt = gettileat(s->x + s->dir+getspeed(s),s->y,NULL,NULL); /* if there's a hole in front of us */ if (tt->solid == S_NOTSOLID) { if ((player->y > s->y) && (s->angry)) { /* if player is below, fall off */ if (xdiff <= (TILEW*8)) { move = B_TRUE; } } else if (player->y == s->y) { if (s->angry) { /* if player is at same level and close, jump */ if ((s->dir == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) { jump(s,D_RIGHT); } else if ((s->dir == D_LEFT) && (xdiff < 0) && (xdiff >= -(TILEW*7))) { jump(s,D_LEFT); } } } } else { move = B_TRUE; } /* shoot */ ydiff = player->y - s->y; if (ydiff < 0) ydiff =-ydiff; if (ydiff <= (TILEH*4)) { sprite_t *ss; int shoot = B_FALSE; if (s->bullet == NULL) { // if we don't already have a bullet // if we are facing the player if ( (player->x < s->x) && (s->dir == D_LEFT) ) { shoot = B_TRUE; } else if ( (player->x > s->x) && (s->dir == D_RIGHT) ) { shoot = B_TRUE; } } if (shoot) { // if our shooting timer is okay if (s->timer1 == 0) { ss = addsprite(P_SPIT,s->x,s->y - s->img->h/2,"spit", B_FALSE); ss->ys = 0; ss->xs = s->dir * (getspeed(s)*2); ss->dir = s->dir; ss->owner = s; s->bullet = ss; // start timer for shooting again s->timer1 = 200; } } } /* either move or turn around */ if (move) { rv = movex(s, s->dir*getspeed(s)); if (rv) { /* if we couldn't move (hit a wall), turn */ s->dir = -s->dir; } } else { s->dir = -s->dir; } if (s->angry) { if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) { /* if player is above us, jump */ if (player->y < s->y) { if ((xdiff >= (TILEW*2)) && (xdiff <= (TILEW*3))) { /* jump right */ jump(s, 1); } else if ((xdiff <= -(TILEW*2)) && (xdiff >= -(TILEW*3))) { /* jump left */ jump(s, -1); } else if (s->y - player->y <= (TILEH*6)) { if ((xdiff >= 0) && (xdiff < (TILEW*2))) { /* jump up */ jump(s, 0); } else if ((xdiff <= 0) && (xdiff > -(TILEW*2))) { /* jump up */ jump(s, 0); } } else { /* jump whichever way we're facing */ /* s->jumpdir = s->dir; s->jumping = 1; s->jumpspeed = 5; */ } } } } } } else if (s->id == P_BEE) { double absxs,absys; if ((s->xs == -99) || (s->ys == -99)) { s->xs = getspeed(s); s->ys = getspeed(s); } if (s->xs > 0) absxs = 1; else absxs = -1; if (s->ys > 0) absys = 1; else absys = -1; /* this will fix the speed if ANGRY is set */ s->xs = absxs*getspeed(s); s->ys = absys*getspeed(s); /* can we move? */ tt = gettileat(s->x + absxs*((s->img->w/2)+8), s->y-(s->img->h/2),NULL,NULL); if ((tt->solid) || (tt->spikes )) { /* turn */ s->xs = -s->xs; } tt = gettileat(s->x, s->y-(s->img->h/2) + absys*((s->img->h/2)+8),NULL,NULL); if ((tt->solid) || (tt->spikes)) { /* turn */ s->ys = -s->ys; } /* move */ s->x += s->xs; s->y += s->ys; s->dir = absxs; s->moved = B_TRUE; } else if (s->id == P_SPIDER) { /* if on ground, go up */ if (isonground(s) && !s->flies) { s->flies = B_TRUE; s->falling = B_FALSE; s->ys = -getspeed(s); } else if (s->falling) { /* if we are about to hit spikes, go back up */ tt = gettileat(s->x,s->y + 8,NULL,NULL); if (tt->spikes) { /* go back up */ s->flies = B_TRUE; s->falling = B_FALSE; s->ys = -getspeed(s); } } else { if (s->ys != -99) { /* if roof above us */ tt = gettileat(s->x,s->y - s->img->h,NULL,NULL); if (tt->solid) { int tiley; /* start walking again */ tiley = (int) (s->y / TILEH); s->y = tiley*TILEH; s->ys = -99; s->flies = B_TRUE; } else { s->y += s->ys; s->flies = B_TRUE; } } else { int move = B_FALSE; int xdiff; /* walk back and forwards */ /* drop if player is close */ xdiff = player->x - s->x; if (xdiff < 0) xdiff =-xdiff; if ((player->y > s->y) && (xdiff <= (TILEW*2))) { s->flies = B_FALSE; s->falling = B_TRUE; s->fallspeed = 8; } else { s->flies = B_TRUE; /* if there's a hole in front of us */ tt = gettileat(s->x + s->dir*((s->img->w/2)+2),s->y - s->img->h - 2,NULL,NULL); if (tt->solid == S_NOTSOLID) { move = B_FALSE; } else { move = B_TRUE; } /* either move or turn around */ if (move) { rv = movex(s, s->dir*getspeed(s)); if (rv) { /* if we couldn't move (hit a wall), turn */ s->dir = -s->dir; } } else { s->dir = -s->dir; } } } } } else if (s->id == P_SPIT) { if (movex(s, s->xs)) { s->dead = D_FINAL; } } else if (s->id == P_CLOUD) { if ((player->dead) || (levelcomplete)) { if ((s->img->h <= 3) || (s->img->w <= 3)) { s->dead = D_FINAL; /* reset hurryup timer */ gtime = 0; } else { SDL_Surface *ts; /* get smaller */ ts = rotozoomSurfaceXY(s->img,0, 0.9 , 0.9 ,0); SDL_FreeSurface(s->img); s->img = ts; s->y--; } } else { if ((s->xs == -99) || (s->ys == -99)) { s->ys = 0.5; s->xs = 1; } s->x += s->xs; s->y += s->ys; if (s->x >= (640 - s->img->w/2 - 5)) { s->xs = -s->xs; s->x = 640 - s->img->w/2 - 6; } if (s->x <= (s->img->w/2 + 5)) { s->xs = -s->xs; s->x = s->img->w/2 + 6; } if (s->y >= (480 - s->img->h/2 - 5)) { s->ys = -s->ys; s->y = 480 - s->img->h/2 - 6; } if (s->y <= (s->img->h/2 + 5)) { s->ys = -s->ys; s->y = s->img->h/2 + 6; } if (timer % 50 == 0) { int w,h; SDL_Surface *ts; /* get bigger */ w = s->img->w; h = s->img->h; ts = rotozoomSurfaceXY(s->img,0, 1.1 , 1.1 ,0); SDL_FreeSurface(s->img); s->img = ts; s->y += 2; } } } } void dotileeffects(sprite_t *s) { tiletype_t *tt; int finished = B_FALSE; int state = 0; if (s->jumping || s->dead || s->caughtby) { return; } /* check where we are */ tt = gettileat(s->x,s->y-2,NULL,NULL); if ((tt->id == T_TELEPORT) || (tt->id == T_TELEPORT2)) { if (s->id == P_PLAYER || ismonster(s->id)) { if (s->id != P_CLOUD) { s->teleporting = 1; } } } /* check under us */ tt = gettileat(s->x,s->y+3,NULL,NULL); while (!finished) { if (tt->id == T_RIGHT) { if (!ismonster(s->id) && !isfruit(s->id)) { movex(s, 1.5); } finished = B_TRUE; } else if (tt->id == T_LEFT) { if (!ismonster(s->id) && !isfruit(s->id)) { movex(s, -1.5); } finished = B_TRUE; } else if (tt->spikes) { if (!isfruit(s->id)) { if (!s->invuln) { if (s->id != P_CLOUD) { die(s); } } } finished = B_TRUE; } else { if (state == 0) { /* check tile to our right */ tt = gettileat(s->x + s->img->w/2,s->y+3,NULL,NULL); state = 1; } else if (state == 1) { /* check tile to our left */ tt = gettileat(s->x - s->img->w/2,s->y+3,NULL,NULL); state = 2; } else { finished = B_TRUE; } } } } void drawlevel(void) { int x,y; SDL_Rect area; int speed = 16; if (temps) { SDL_FreeSurface(temps); temps = NULL; } temps = SDL_CreateRGBSurface(SDL_SWSURFACE, 640, 480, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); for (x = 0; x < LEVELW; x++) { for (y = 0; y < LEVELH; y++) { drawtile(temps,x,y); } } for (x = 0; x < 640; x += speed) { area.x = 0; area.y = 0; if (x > 639) { area.w = 639; } else area.w = x; area.h = 480; SDL_BlitSurface(temps, &area, screen, &area); SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); } } double getspeed(sprite_t *s ) { int id = s->id; double speed = 1; if (id == P_PLAYER) { speed = s->speed; } else if (id == P_RAT) { if (s->angry) speed = 1.5; else speed = 1; } else if (id == P_SNAKE) { if (s->angry) speed = 1.5; else speed = 1; } else if (id == P_BEE) { if (s->angry) speed = 2; else speed = 1; } else if (id == P_SPIDER) { if (s->angry) speed = 1.5; else speed = 2; } else if (id == P_CHEESE) { speed = 0; } if (isinwater(s)) speed /= 2; return speed; } int addtext(int x, int y, int size, char *string, SDL_Color *c, int delay) { text_t *t; if (text == NULL) { text = malloc(sizeof(text_t)); t = text; t->prev = NULL; } else { t = lasttext; t->next = malloc(sizeof(text_t)); t->next->prev = t; t = t->next; } t->bg = SDL_CreateRGBSurface(SDL_SWSURFACE, 300, 110, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); t->c = c; t->x = x; t->y = y; t->maxsize = size; t->size = 3; strcpy(t->txt, string); t->state = 0; t->delay = delay; t->img = TTF_RenderText_Solid(font[t->size], t->txt, *t->c); t->next = NULL; lasttext = t; return B_FALSE; } /* copy background buffer (ie. tiles) to screen, erasing sprites */ void removeall(void) { SDL_BlitSurface(temps, NULL, screen, NULL); } void removetext(void) { SDL_Rect sarea; text_t *t; for (t = text ; t ; t = t->next) { sarea.x = 0; sarea.y = 0; sarea.w = t->bgarea.w; sarea.h = t->bgarea.h; SDL_BlitSurface(t->bg, &sarea, screen, &t->bgarea); } } void movetext(void) { text_t *t,*nextt; for (t = text ; t ; t = nextt) { nextt = t->next; if (t->state == 0) { t->size += TEXTSPEED; if (t->size >= t->maxsize) { t->state = 1; } } else if (t->state == t->delay) { t->size -= TEXTSPEED; if (t->size <= 3) { killtext(t); } } else { t->state++; } } } void drawscore(void) { SDL_Surface *score; SDL_Rect area; sprintf(tempm, "%d",player->score); /* shadow */ score = TTF_RenderText_Solid(font[14], tempm, black); area.x = 18; area.y = 7; area.w = 0; area.h = 0; SDL_BlitSurface(score, NULL, screen, &area); SDL_FreeSurface(score); /* score */ score = TTF_RenderText_Solid(font[14], tempm, green); area.x = 20; area.y = 5; area.w = 0; area.h = 0; SDL_BlitSurface(score, NULL, screen, &area); SDL_FreeSurface(score); } void drawtext(void) { text_t *t; SDL_Rect area; for (t = text ; t ; t = t->next) { /* create text */ if (t->img) { SDL_FreeSurface(t->img); t->img = NULL; } t->img = TTF_RenderText_Solid(font[t->size], t->txt, *t->c); /* get bg */ t->bgarea.x = t->x - t->img->w/2; t->bgarea.y = t->y - t->img->h/2; t->bgarea.w = t->img->w; t->bgarea.h = t->img->h; SDL_BlitSurface(screen, &t->bgarea, t->bg, NULL); /* draw text */ area.x = t->x - t->img->w/2; area.y = t->y - t->img->h/2; area.w = t->img->w; area.h = t->img->h; SDL_BlitSurface(t->img,NULL, screen, &area); } } void killtext(text_t *t) { text_t *nextone, *lastone; if (t->bg) { SDL_FreeSurface(t->bg); t->bg = NULL; } if (t->img) { SDL_FreeSurface(t->img); t->img = NULL; } nextone = t->next; if (nextone != NULL) { nextone->prev = t->prev; } else { /*last text */ lasttext = t->prev; } if (t->prev == NULL) { /* first text */ nextone = text->next; free(text); text = nextone; } else { lastone = t->prev; free (lastone->next ); lastone->next = nextone; } } void drawnetting(sprite_t *s) { int sx; SDL_Rect area; if (s->netting) { int y,yy; int dis; int netsleft; sx = s->x; s->nety = s->y - (s->img->h/2) + 2; s->netxstart = s->x; s->netystart = s->nety - 3; if (s->netdir == 1) { area.x = s->netxstart + TILEW/2; } else { area.x = s->netxstart - TILEW/2 - s->netlen; } //area.y = s->netystart; area.y = s->y - s->img->h-2 + 2; area.w = s->netlen; area.h = s->img->h+2; SDL_BlitSurface(screen, &area,s->netbg, NULL); netsleft = s->netmax - s->netcaught; if (netsleft < 1) netsleft = 1; dis = (int)s->img->h / (int)(netsleft+1) + 1; for (y = dis; y < s->img->h; y += dis) { yy = s->y - s->img->h; yy += y; drawline16(screen,sx,s->nety,s->x + s->netdir*s->netlen,yy,white); } //drawline16(screen,sx,s->nety,s->x + s->netdir*s->netlen,s->nety-3,white); //drawline16(screen,sx,s->nety,s->x + s->netdir*s->netlen,s->nety,white); //drawline16(screen,sx,s->nety,s->x + s->netdir*s->netlen,s->nety+3,white); } else if (s->slamming) { double dist; int x,y; 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 */ 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); /* right line */ 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); } } void removenetting(sprite_t *s) { SDL_Rect area,sarea; if (s->netting) { sarea.x = 0; sarea.y = 0; sarea.w = s->netlen; sarea.h = s->img->h+2; if (s->netdir == 1) { area.x = s->netxstart + TILEW/2; } else { area.x = s->netxstart - TILEW/2 - s->netlen; } //area.y = s->netystart; area.y = s->y - s->img->h-2; area.w = s->netlen; area.h = s->img->h+2; if (s->netbg != NULL) { SDL_BlitSurface(s->netbg, &sarea, screen, &area); } } } void removesprite(sprite_t *s) { int startx,starty,endx,endy; int x,y; /* find topleft-most tile */ gettileat(s->x - s->img->w, s->y - s->img->h,&startx,&starty); /* find bottomright-most tile */ gettileat(s->x + s->img->w, s->y + s->img->h,&endx,&endy); if (s->slamming) { if (s->dir == D_LEFT) { startx -= 5; endx += 1; } else { startx -= 1; endx += 5; } starty -= 2; endy += 1; } /* draw the tiles */ for (y = starty; y <= endy; y++) { for (x = startx; x <= endx; x++) { drawtile(screen,x,y); } } } int isonbridge(sprite_t *s) { tiletype_t *tthere; tthere = gettileat(s->x,s->y, NULL,NULL); if (tthere->id == T_BRIDGE) { return B_TRUE; } return B_FALSE; } int isonladder(sprite_t *s) { tiletype_t *tthere; tthere = gettileat(s->x,s->y, NULL,NULL); if ((tthere->id == T_LADDER) || (tthere->id == T_LADDERTOP)) { return B_TRUE; } return B_FALSE; } int isladderabove(sprite_t *s) { tiletype_t *tthere; tthere = gettileat(s->x,s->y-TILEH, NULL,NULL); if (tthere->id == T_LADDER) { return B_TRUE; } return B_FALSE; } int isinwater(sprite_t *s) { tiletype_t *tt; tt = gettileat(s->x, s->y - s->img->h/2, NULL, NULL); if (tt->water) { return B_TRUE; } return B_FALSE; } int isroofabove(sprite_t *s) { tiletype_t *tt; /* get tile above sprite's head */ tt = gettileat(s->x, s->y - s->img->h,NULL,NULL); if (tt->solid) return B_TRUE; tt = gettileat(s->x + s->img->w/2, s->y - s->img->h,NULL,NULL); if (tt->solid) return B_TRUE; tt = gettileat(s->x - s->img->w/2, s->y - s->img->h,NULL,NULL); if (tt->solid) return B_TRUE; return B_FALSE; } /* is there a roof n tiles above us. If howfar is 1, this is the same as the regular isroofabove() */ int isroofnabove(sprite_t *s, int howfar) { tiletype_t *tt; int ypos; ypos = s->y - s->img->h - TILEH*(howfar-1); /* get tile above sprite's head */ tt = gettileat(s->x, ypos,NULL,NULL); if (tt->solid) return B_TRUE; tt = gettileat(s->x + (s->img->w/2 - 2), ypos,NULL,NULL); if (tt->solid) return B_TRUE; tt = gettileat(s->x - (s->img->w/2 - 2), ypos,NULL,NULL); if (tt->solid) return B_TRUE; return B_FALSE; } int isonground(sprite_t *s) { /* get tile below sprite's feet */ if (isongroundpoint(s, s->x, s->y)) { return B_TRUE; } if ((s->dead) || (!s->falling && !s->dropping)) { if (isongroundpoint(s, s->x + s->img->w/2, s->y)) { return B_TRUE; } if (isongroundpoint(s, s->x - s->img->w/2, s->y)) { return B_TRUE; } } return B_FALSE; } int isongroundpoint(sprite_t *s, int x,int y) { tiletype_t *tt; int tilex,tiley; int xoff; int groundy; tt = gettileat(x,y, &tilex, &tiley); // slope etc doesn't matter if you're dead if (s->dead && tt->solid) { return B_TRUE; } // when dropping, the tile you dropped from doesn't count // as "ground". if (s->dropping && (tilex == s->dropx) && (tiley == s->dropy)) { return B_FALSE; } /* get offset */ xoff = x - (tilex*TILEW); /* if it's not solid... */ if (tt->solid == 0) { return B_FALSE; } else { /* check height of tile at that position */ groundy = tiley*TILEH + tt->lowness[xoff]; /* above ground level */ if (y < groundy) { return B_FALSE; } else if (y > groundy + 3) { /* below ground level */ if (s->jumping) { return B_FALSE; } } else if (s->falling) { tiletype_t *abovetile; /* falling, on a tile, but with tiles above you */ // ie. you've jumped up through a single tile (can't // jump through two or more tiles abovetile = gettileat(x,y-TILEH, NULL, NULL); if (abovetile->solid) { return B_FALSE; } // } else if (s->dropping) { // tiletype_t *abovetile; /* if the tile we're on is solid but not the one above, then we've "dropped" and are still travelling through the tile we dropped from. */ // abovetile = gettileat(x,y-TILEH, NULL, NULL); // if (!abovetile->solid) { // return B_FALSE; // } } } return B_TRUE; } void dogravity(sprite_t *s) { sprite_t *s2; if (s->dead) return; if (s->flies) return; if (iseffect(s->id)) return; if (isbullet(s->id)) return; if (isonladder(s) && !s->falling && !s->jumping) { s->falling = B_FALSE; return; } // handle jumps if (s->jumping) { s->falling = B_FALSE; s->y -= s->jumpspeed; s->jumping++; if (s->jumping % 5 == 0) { if (s->jumpspeed > 0) s->jumpspeed--; else { s->jumping = 0; s->falling = B_TRUE; s->fallspeed = 0; } } /* have we hit a roof ? */ /* can jump through one tile, but not two or more */ if (isroofabove(s) && isroofnabove(s,2)) { /* stop jumping */ s->jumping = 0; s->falling = B_TRUE; s->fallspeed = 0; } } else { if (isonground(s) ) { s->dropping = B_FALSE; s->falling = B_FALSE; s->climbing = B_FALSE; } else { if (s->falling == B_FALSE) { s->fallspeed = 1; } s->falling = B_TRUE; if (isinwater(s)) { s->y += (s->fallspeed/2); } else { s->y += s->fallspeed; } if ((timer % 10 == 0) && (s->fallspeed < FALLSPEED)) { s->fallspeed++; } } } if (s->netting) { s->netlen += s->netspeed; s->netting++; if (s->netting % 2 == 0) { if (s->netspeed > -NETSPEED) s->netspeed--; else { s->netting = 0; for (s2 = sprite ; s2 ; s2 = s2->next) { if ((s2->caughtby == s) && (s2->caughtstate == C_NETTING)) { s2->caughtstate = C_NETTED; } } } } } if (s->slamming) { s->slamangle += (10 * (M_PI/180)); if (s->slamangle >= (180 * (M_PI/180))) { /* finished slamming */ int xdiff,ydiff,xnet = 0,ynet = 0; int pointsinc = 250; int psize = 6; int gotsomething = B_FALSE; s->slamming = 0; /* reset fruit type counter */ curfruittype = 0; /* kill anything we've caught */ for (s2 = sprite; s2 ; s2 = s2->next) { /* kill anything we have caught */ if (s2->caughtby == s) { tiletype_t *tt; tt = gettileat(s2->x,s2->y+2,NULL,NULL); /* if on ground, monster dies */ if ((tt == NULL) || (tt->solid)) { /* will become a fruit when it finishes dying */ s2->willbecome = fruittypes[curfruittype]; /* increment fruit type */ if (fruittypes[++curfruittype] == -1) { curfruittype = 0; } die(s2); pointsinc *= 2; psize += 10; xnet = s2->x; ynet = s2->y - s2->img->h/2; gotsomething++; } else { /* otherwise it gets angry */ s2->angry = B_TRUE; } } } /* kill anything we hit */ for (s2 = sprite; s2 ; s2 = s2->next) { if ((s2->caughtby != s) && (!s2->dead) && (ismonster(s2->id))) { xdiff = s2->x - xnet; if (xdiff < 0) xdiff =-xdiff; ydiff = (s2->y - s2->img->h/2) - ynet; if (ydiff < 0) ydiff =-ydiff; if ((xdiff <= s2->img->w) && (ydiff <= s2->img->h)) { if (s2->id != P_CLOUD) { /* dies and becomes a powerup */ s2->willbecome = poweruptypes[curpoweruptype]; if (poweruptypes[++curpoweruptype] == -1) { curpoweruptype = 0; } die(s2); pointsinc *= 2; psize += 10; gotsomething++; } } } } if (gotsomething >= 1) { playfx(FX_KILL); } if (gotsomething > 1) { playfx(FX_MULTIKILL); } gotsomething = B_FALSE; /* release anything we've caught */ for (s2 = sprite; s2 ; s2 = s2->next) { if (s2->caughtby == s) { /* release it */ s2->caughtby = NULL; } } s->netcaught = 0; /* show points */ if (psize >= MAXLETTERHEIGHT) { psize = MAXLETTERHEIGHT-1; } if (pointsinc > 250) { sprintf(tempm, "%d",pointsinc); addtext(xnet,ynet-TILEH, psize, tempm, &white,POINTSDELAY); /* give points to player */ s->score += pointsinc; } } } } int movex(sprite_t *s,double amt) { double newx,newy; double curx,cury; int tilex,tiley; tiletype_t *tt,*tt2; int newxoff,newgroundy; int newtilex,newtiley; double amtdir; tt = gettileat(s->x, s->y, &tilex,&tiley); if (amt > 0) amtdir = 1; else (amtdir = -1); curx = s->x; cury = s->y; /* check for blockage in front of us */ //newx = s->x + (amtdir*(s->img->w/2)); newx = s->x + (amtdir*TILEW/2); newy = cury-TILEH; tt2 = gettileat(newx,newy,&newtilex,&newtiley); if (tt2->solid == S_SOLID) { return B_TRUE; } if (tt2->solid == S_SLOPE && (!candoslopes(s->id))) { return B_TRUE; } /* get new position */ newx = curx + amt; newy = cury-2; tt2 = gettileat(newx,newy,&newtilex,&newtiley); newxoff = newx - (newtilex*TILEW); newgroundy = newtiley*TILEH + tt2->lowness[newxoff]; /* new block is at least partially solid */ if (tt2->solid == S_SOLID) { return B_TRUE; } else if ((tt2->solid == S_SLOPE) && candoslopes(s->id)) { /* we can move, but need to adjust our height */ s->x += amt; } else { /* new block is empty */ s->x += amt; } s->moved = B_TRUE; return B_FALSE; } void adjustheight(sprite_t *s) { tiletype_t *tt; int xoff,groundy; int tilex,tiley; if ((s->flies) || isbullet(s->id)) { return; } tt = gettileat(s->x,s->y-1,&tilex,&tiley); if (!tt) return; if (tt->solid == S_SLOPE) { xoff = s->x - (tilex*TILEW); groundy = tiley*TILEH + tt->lowness[xoff]; s->y = groundy; } else if (tt->solid == S_SOLID) { while (tt->solid == S_SOLID) { s->y--; tt = gettileat(s->x,s->y-1,&tilex,&tiley); } } } int dofruiteffect(sprite_t *s) { if (s->id == P_SPEED) { playfx(FX_POWERUP); player->speed = 2; addtext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, "Speed up!", &white,POINTSDELAY); return B_TRUE; } else if (s->id == P_NUMNETS) { playfx(FX_POWERUP); if (player->netmax < 4) { player->netmax++; } sprintf(tempm, "%d nets!",player->netmax); addtext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,POINTSDELAY); return B_TRUE; } else if (s->id == P_BIGNET) { playfx(FX_POWERUP); player->netbig = B_TRUE; sprintf(tempm, "Big net!"); addtext(s->x,s->y - s->img->h/2, TEXTSIZE_POINTS, tempm,&white,POINTSDELAY); return B_TRUE; } else if (s->id == P_HELP) { playfx(FX_POWERUP); addtext(320,240,TEXTSIZE_HELP, s->name, &white,HELPDELAY); return B_TRUE; } else if (isflower(s->id)) { int xx; sprite_t *ss; tiletype_t *tt; int found = B_FALSE; /* was this the last fruit of its kind on the level? */ for (ss = sprite; ss; ss = ss->next) { if ((ss != s) && (ss->id == s->id)) { found = B_TRUE; } } /* if so, create a left/right stream of flowers */ if (!found) { int howmany = STREAMWID + 1; int puffdelay; // RIGHT puffdelay = 0; for (xx = s->x+TILEW; xx < s->x + (TILEW*howmany); xx += TILEW) { // if on a wall, exit tt = gettileat(xx,s->y-TILEH,NULL,NULL); if (tt->solid) { break; } /* create a flower */ puffin(flowertogem(s->id), xx, s->y, puffdelay); //ss = addsprite(P_PUFF, xx,s->y,"puff", B_FALSE); //ss->timer1 = -puffdelay; //ss->timer3 = flowertogem(s->id); puffdelay += 1; } // LEFT puffdelay = 0; for (xx = s->x+TILEW; xx > s->x - (TILEW*howmany); xx -= TILEW) { // if on a wall, exit tt = gettileat(xx,s->y-TILEH,NULL,NULL); if (tt->solid) { break; } puffin(flowertogem(s->id), xx, s->y, puffdelay); //ss = addsprite(P_PUFF, xx,s->y,"puff", B_FALSE); //ss->timer1 = -puffdelay; //ss->timer3 = flowertogem(s->id); puffdelay += 1; } playfx(FX_BONUS); sprintf(tempm, "BONUS!"); addtext(s->x,s->y - s->img->h/2, TEXTSIZE_BONUS, tempm,&white,BONUSDELAY); return B_TRUE; } } return B_FALSE; } int ismonster(int id) { if (id == P_RAT) return B_TRUE; if (id == P_BEE) return B_TRUE; if (id == P_SPIDER) return B_TRUE; if (id == P_SNAKE) return B_TRUE; if (id == P_CLOUD) return B_TRUE; if (id == P_COKE) return B_TRUE; return B_FALSE; } void usage(void) { printf("usage: rc [-fs] [-l xx]\n"); printf(" -fs Start in full-screen mode.\n"); printf(" -l xx Skip to level xx.\n"); printf("\n"); } // returns B_TRUE if the given player is able to walk/fall left/right int canmove(sprite_t *pl) { if (!pl->jumping && !pl->slamming ) { if (!pl->netting) { if (!isonladder(pl) || pl->falling || isonground(pl)) { return B_TRUE; } } else if (pl->netting && pl->falling) { // netting and falling return B_TRUE; } } return B_FALSE; } // returns B_TRUE if the given player is able to change which direction they're facing int canturn(sprite_t *pl) { if (!pl->slamming && !pl->netting) { return B_TRUE; } return B_FALSE; } int loadfx(int sid , char *filename) { char tempname[BUFLEN]; sprintf(tempname, "sounds/"); strncat(tempname, filename, BUFLEN); sfx[sid] = Mix_LoadWAV(tempname); if (!sfx[sid]) { printf("error loading %s\n",tempname); return B_TRUE; } return B_FALSE; } int initsound(void) { int i; /* init */ if (Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 1024) < 0) { printf("Error initialising sound: %s.\n",Mix_GetError()); return B_TRUE; } Mix_AllocateChannels(CH_LASTCHANNEL); loadfx(FX_SHOOT, "shoot.wav"); loadfx(FX_SLAM, "slam.wav"); loadfx(FX_KILL, "kill.wav"); loadfx(FX_MULTIKILL, "multikill.wav"); loadfx(FX_JUMP, "jump.wav"); loadfx(FX_FRUIT, "fruit.wav"); loadfx(FX_POWERUP, "powerup.wav"); loadfx(FX_DIE, "die.wav"); loadfx(FX_WINLEVEL, "winlevel.wav"); loadfx(FX_HURRYUP, "hurryup.wav"); loadfx(FX_TOOSLOW, "tooslow.wav"); loadfx(FX_BONUS, "bonus.wav"); // load sound effects for (i = 0; i < MAXFX; i++) { if (!sfx[i]) { return B_TRUE; } } // set up callback Mix_ChannelFinished(channeldone); // load music normalmusic = Mix_LoadMUS("music/main.mod"); if (!normalmusic) { printf("can't load music\n"); return B_TRUE; } fastmusic = Mix_LoadMUS("music/mainfast.mod"); if (!fastmusic) { printf("can't load fast music\n"); return B_TRUE; } return B_FALSE; } void playfx(int num) { Mix_PlayChannel(-1, sfx[num], 0); } void playmusic(Mix_Music *toplay) { /* stop music */ if (musicplaying) { Mix_HaltMusic(); } /* start music */ //music = toplay; Mix_PlayMusic(toplay, -1); curmusic = toplay; musicplaying = B_TRUE; } void stopmusic(void) { /* stop music */ if (musicplaying) { Mix_HaltMusic(); } musicplaying = B_FALSE; curmusic = NULL; } // callback for sound effects finishing void channeldone(int channel) { if (channel == CH_HURRYUP) { // start fast music playmusic(fastmusic); } } void puffin(int willbecome, int x, int y, int delay) { sprite_t *ss; ss = addsprite(P_PUFF, x, y, "puff", B_FALSE); ss->timer3 = willbecome; ss->timer1 = -delay; }