#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rc.h" FPSmanager manager; SDL_Surface *temps; SDL_Surface *screen; TTF_Font *font[MAXLETTERHEIGHT]; char tempm[BUFLEN]; tiletype_t fakeblock; tiletype_t *seltile = NULL; int selsprite = -1; /* the order in which fruit will appear */ int fruittypes[] = { 2, 9, 10, 11, -1 }; /* the order in which powerups will appear */ int poweruptypes[] = { 3, 4, 5, 4, -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; char filename[BUFLEN]; int i; int mb,mx,my; curlevelnum = 1; /* 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(EDITORW,EDITORH,16,SDL_OPENGLBLIT|vidargs); #else screen = SDL_SetVideoMode(EDITORW,EDITORH,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 = IMG_Load("land.bmp"); 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; } } if (loadlevel(curworld,curlevelnum)) { return 1; } seltile = tiletype; drawlevel(); drawpalette(); drawsprites(); flip(); timer = 0; player->invuln = INVULNTIME; player->score = 0; while (1) { /* check for mouse actions */ mb = SDL_GetMouseState(&mx,&my); if (mb & SDL_BUTTON(1)) { // lmb if ((mx >= PALX) && (my < SPALY)) { // over tile palette tiletype_t *tt; int x = PALX,y = PALY; seltile = NULL; /* get tile number */ for (tt = tiletype; tt != NULL; tt = tt->next) { // is mouse over this one? if ((mx >= x) && (my >= y) && (mx <= x+TILEW-1) && (my <= y+TILEH-1)) { seltile = tt; selsprite = -1; break; } else { // check next one x += TILEW; if (x >= EDITORW) { x = PALX; y += TILEH; } } } // redraw palette with new selection drawpalette(); } else if ((mx >= PALX) && (my > SPALY)) { // over sprite palette int p; int x = SPALX, y = SPALY; int maxh = 0; /* get sprite id */ selsprite = -1; for (p = 0; p < MAXPTYPES; p++) { SDL_Surface *firstimg; int w,h; /* select images */ firstimg = imageset[p].img[F_WALK1]; w = firstimg->w; h = firstimg->h; if (h > maxh) maxh = h; // is mouse over it? if ((mx >= x) && (my >= y) && (mx <= x+w-1) && (my <= y+h-1)) { selsprite = p; seltile = NULL; break; } else { // check next one x += w; if (x >= EDITORW) { x = SPALX; y += maxh; maxh = 0; } } } // redraw palette with new selection drawpalette(); } else if (mx < PALX) { // over map int x,y; if (seltile != NULL) { /* place selected tile at mouse pos */ x = (mx / TILEW); y = (my / TILEH); curlevel->map[y*LEVELW+x] = seltile->id; // redraw tile and sprites drawtile(screen,x,y); drawsprites(); } else if (selsprite >= 0) { int placed = B_FALSE; x = (mx / TILEW); y = (my / TILEH); /* checks */ // can only have one player start pos if (selsprite == P_PLAYER) { /* does a player start pos already exist? */ sprite_t *s; for (s = sprite ; s ; s = s->next) { if (s->id == P_PLAYER) { // if so, just move it s->x = x*TILEW+(TILEW/2); s->y = y*TILEH+TILEH; placed = B_TRUE; // get rid of old sprite drawlevel(); } } } if (!placed) { /* place selected sprite at mouse position (locked to a til) */ addsprite(selsprite, x*TILEW+(TILEW/2),y*TILEH+TILEH,"something", B_TRUE); } drawsprites(); } } } /* 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; } flip(); if (++timer == 100) timer = 0; if (toggletimer > 0) toggletimer--; } 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) { s->angry = B_TRUE; } } addtext(320,240,TEXTSIZE_HURRY, "Hurry up!", &yellow,HURRYDELAY); } } if (gtime == curlevel->hurryuptime + 10) { if (!levelcomplete) { addsprite(P_CLOUD, 320,240,"cloud", B_FALSE); addtext(320,240,TEXTSIZE_HURRY, "Too slow!", &red,HURRYDELAY); } } /* 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++; loadlevel(curworld,curlevelnum); drawlevel(); levelcomplete = B_FALSE; levelcompletetime = -1; } 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; /* 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 = 1; 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; 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 = 1; 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)) { if (s == player) { int gotscore = s2->score; /* kill the fruit */ s2->dead = 4; /* handle fruit effects */ if (!dofruiteffect(s2)) { sprintf(tempm, "%d", gotscore); addtext(s2->x,s2->y - s2->img->h/2, 16, tempm, &white,POINTSDELAY); } /* give points to the player */ s->score += gotscore; } } if (ismonster(s2->id) || isbullet(s2->id)) { if ((s == player) && (!s->invuln)) { die(s); } } } } } } } tiletype_t *gettile(int tid) { tiletype_t *t; for (t = tiletype; t ; t = t->next) { if (t->id == tid) return t; } return &fakeblock; } void movesprite(sprite_t *s) { int rv; tiletype_t *tt; /* timer */ if (s->timer) { s->timer--; if (s->timer == 0) { s->dead = 4; } } /* 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 == 1) { 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 == 1) { /* just set to dead */ //s->xs = ((rand() % 7)) - 3; s->xs = ((rand() % 14) / 2) - 3; s->ys = ((rand() % 3) + 3) * -1; s->dead = 2; s->bounces = 0; if (s == player) { s->jumpspeed = 8; s->jumping = 1; } return; } else if (s->dead == 2) { /* 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 = 3; } } else { /* bounch around the screen 3 times */ s->x += s->xs; s->y += s->ys; 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->bounces >= 2) && (s->ys > 0)) { s->dead = 3; } } return; } else if (s->dead == 3) { /* final fall */ if (s == player) { /* just delay... */ s->jumpspeed++; if (s->jumpspeed == 50) { /* really die */ s->dead = 4; } } else { /* bounce around, stop when we hit the ground */ s->x += s->xs; s->y += s->ys; 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 = 4; /* change into a fruit */ x = s->x; gettileat(s->x,s->y-1,NULL,&ty); y = ty*TILEH + 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); } } } return; } else if (s->teleporting > 0) { SDL_Surface *ts; if (timer % 2 == 0) { /* shrink */ if (s->teleporting == 1) { 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 (isonground(s)) { if ((!s->falling) && (!s->jumping)) { if (!s->climbing) { 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_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 == 1) && (xdiff > 0) && (xdiff <= (TILEW*7))) { jump(s,1); } else if ((s->dir == -1) && (xdiff < 0) && (xdiff >= -(TILEW*7))) { jump(s,-1); } } } } 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_SNAKE) { 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 == 1) && (xdiff > 0) && (xdiff <= (TILEW*7))) { jump(s,1); } else if ((s->dir == -1) && (xdiff < 0) && (xdiff >= -(TILEW*7))) { jump(s,-1); } } } } 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 ( (player->x < s->x) && (s->dir == -1) ) { shoot = B_TRUE; } else if ( (player->x < s->x) && (s->dir == -1) ) { shoot = B_TRUE; } } if (shoot) { 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; } } /* 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 = 4; } } else if (s->id == P_CLOUD) { if ((player->dead) || (levelcomplete)) { if ((s->img->h <= 3) || (s->img->w <= 3)) { s->dead = 4; /* 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)) { 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)) { movex(s, 1.5); } finished = B_TRUE; } else if (tt->id == T_LEFT) { if (!ismonster(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 drawtile(SDL_Surface *where, int x, int y) { SDL_Rect area; tiletype_t *tt; if ((x < 0) || (y < 0) || (x >= LEVELW) || (y >= LEVELH)) { return; } area.x = x * TILEW; area.y = y * TILEH; area.w = 0; area.h = 0; /* draw blank tile first */ tt = gettile(curlevel->bgtileid); SDL_BlitSurface(tt->img, NULL, where, &area); tt = gettile(curlevel->map[y*LEVELW+x]); if (tt->id != curlevel->bgtileid) { SDL_BlitSurface(tt->img, NULL, where, &area); } } void drawlevel(void) { int x,y; 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(screen,x,y); } } SDL_UpdateRect(screen, 0, 0, EDITORW, EDITORH); } int loadlevel(int wnum, int lnum) { FILE *f; int x,y; char buf[BUFLEN]; char buf2[BUFLEN]; char filename[BUFLEN]; char *help[MAXHELP]; int numhelp = 0; int curhelp; char *p; int tileid; int i; mapping_t mapping[MAXMAPPINGS]; int nmappings = 0; tiletype_t *lasttile; level = malloc(sizeof(level_t)); level->id = 0; sprintf(level->name, "Level %d-%d",wnum,lnum); level->prev = NULL; level->next = NULL; /* default */ level->hurryuptime = 30; level->p1x = 0; level->p1y = 0; sprintf(filename, "world%d/level%d.dat",wnum,lnum); f = fopen(filename,"rt"); if (!f) { printf("can't open level file\n"); return B_TRUE; } /* clear text */ while (text) { killtext(text); } /* clear tiletype linked list */ while (tiletype != NULL) { tiletype_t *tt; /* kill first tile */ if (tiletype->img) { SDL_FreeSurface(tiletype->img); tiletype->img = NULL; tt = tiletype->next; free(tiletype); tiletype = tt; } } /* clear player linked list */ if (sprite != NULL) { while (sprite->next) { killsprite(sprite->next); } } /* read tileset */ fgets(buf, BUFLEN, f); if (strstr(buf, "tileset") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); /* strip newline */ p[strlen(p)-1] = '\0'; strcat(p, ".tiles"); if (loadtiletypes(p)) { printf("Cannot load tileset file: %s\n", p); return B_TRUE; } } else { printf("invalid tileset file in line: '%s'\n",buf); return B_TRUE; } /* read background tile */ fgets(buf, BUFLEN, f); if (strstr(buf, "bg") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); level->bgtileid = atoi(p); if (!gettile(level->bgtileid)) { printf("invalid background tile id: %d\n",level->bgtileid); return B_TRUE; } //printf("Background tile id is %d (%s)\n",level->bgtileid,(gettile(level->bgtileid)->name)); } else { printf("invalid background tile id line: '%s'\n",buf); return B_TRUE; } /* read hurryup time tile */ fgets(buf, BUFLEN, f); if (strstr(buf, "hurryup") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); level->hurryuptime = atoi(p); //printf("Hurryup time is %d\n",level->hurryuptime); } else { printf("invalid hurryup time line: '%s'\n",buf); return B_TRUE; } level->nummonsters = 0; /* read tile defs */ nmappings = 0; fgets(buf, BUFLEN, f); while (!strstr(buf, "endmaps")) { strncpy(buf2,buf,BUFLEN); p = strtok(buf2, ","); if (p == NULL) { printf("invalid char->tile mapping: '%s'\n",buf); return B_TRUE; } mapping[nmappings].ch = p[0]; p = strtok(NULL, ","); if (p == NULL) { printf("invalid char->tile mapping: '%s'\n",buf); return B_TRUE; } mapping[nmappings].tnum = atoi(p); printf("got mapping: '%c' to %d\n",mapping[nmappings].ch,mapping[nmappings].tnum); nmappings++; fgets(buf, BUFLEN, f); } fgets(buf, BUFLEN, f); /* read help messages if present */ if (strstr(buf, "help")) { curhelp = 0; // used later numhelp = 0; fgets(buf, BUFLEN, f); while (!strstr(buf, "endhelp")) { // strip newline buf[strlen(buf)-1] = '\0'; help[numhelp] = strdup(buf); numhelp++; fgets(buf, BUFLEN, f); } /* this reads the first line of the level */ fgets(buf, BUFLEN, f); } /* read monster definitions if present */ if (strstr(buf, "monsters")) { fgets(buf, BUFLEN, f); while (!strstr(buf, "endmonsters")) { char ch; int monid; int x,y; // strip newline buf[strlen(buf)-1] = '\0'; strncpy(buf2,buf,BUFLEN); p = strtok(buf2, " "); if (p == NULL) { printf("invalid monster definition (missing type): '%s'\n",buf); return B_TRUE; } ch = p[0]; // type of monster monid = chartomonster(ch); if (monid < 0) { printf("invalid monster definition (invalid type): '%s'\n",buf); return B_TRUE; } p = strtok(NULL, " "); if (p == NULL) { printf("invalid monster definition (missing x): '%s'\n",buf); return B_TRUE; } x = atoi(p); // monster x pos p = strtok(NULL, " "); if (p == NULL) { printf("invalid monster definition (missing y): '%s'\n",buf); return B_TRUE; } y = atoi(p); // monster y pos if (monid == P_PLAYER) { level->p1x = x; level->p1y = y; } else { /* place the monster */ level->initm[level->nummonsters].startx = x*TILEW+(TILEW/2); level->initm[level->nummonsters].starty = y*TILEH+(TILEH-2); level->initm[level->nummonsters].id = monid; if (monid == P_HELP) { if (curhelp >= numhelp) { printf("Error in level - more help icons than help texts.\n"); exit(1); } else { level->initm[level->nummonsters].help = strdup(help[curhelp]); curhelp++; } } level->nummonsters++; } fgets(buf, BUFLEN, f); } /* this reads the first line of the level */ fgets(buf, BUFLEN, f); } x = 0; y = 0; while (!feof(f)) { for (p = buf; *p; p++) { int n,found = 0; /* search mappings */ for (n = 0; n < nmappings; n++) { if (mapping[n].ch == *p) { tileid = mapping[n].tnum; found = B_TRUE; break; } } if (!found) { if (*p == '~') { tileid = T_LAND; } else if (*p == '=') { tileid = T_LADDER; } else if (*p == '-') { tileid = T_LADDERTOP; } else if (*p == '{') { tileid = T_WATERTOP; } else if (*p == '}') { tileid = T_WATER; } else if (*p == '>') { tileid = T_RIGHT; } else if (*p == '<') { tileid = T_LEFT; } else if (*p == '^') { tileid = T_SPIKES; } else if (*p == 'c') { tileid = level->bgtileid; level->initm[level->nummonsters].startx = x*TILEW+(TILEW/2); level->initm[level->nummonsters].starty = y*TILEH+(TILEH-2); level->initm[level->nummonsters].id = P_CLOUD; level->nummonsters++; } else if (*p == 'r') { /* figure out background type */ if (lasttile->solid) { tileid = level->map[(y-1)*LEVELW+x]; } else { tileid = lasttile->id; } // tileid = level->bgtileid; level->initm[level->nummonsters].startx = x*TILEW+(TILEW/2); level->initm[level->nummonsters].starty = y*TILEH+(TILEH-2); level->initm[level->nummonsters].id = P_RAT; level->nummonsters++; } else if (*p == 'S') { /* figure out background type */ if (lasttile->solid) { tileid = level->map[(y-1)*LEVELW+x]; } else { tileid = lasttile->id; } // tileid = level->bgtileid; level->initm[level->nummonsters].startx = x*TILEW+(TILEW/2); level->initm[level->nummonsters].starty = y*TILEH+(TILEH-2); level->initm[level->nummonsters].id = P_SNAKE; level->nummonsters++; } else if (*p == 'a') { /* figure out background type */ if (lasttile->solid) { tileid = level->map[(y-1)*LEVELW+x]; } else { tileid = lasttile->id; } level->initm[level->nummonsters].startx = x*TILEW+(TILEW/2); level->initm[level->nummonsters].starty = y*TILEH+(TILEH-2); level->initm[level->nummonsters].id = P_BEE; level->nummonsters++; } else if (*p == 's') { /* figure out background type */ if (lasttile->solid) { tileid = level->map[(y-1)*LEVELW+x]; } else { tileid = lasttile->id; } level->initm[level->nummonsters].startx = x*TILEW+(TILEW/2); level->initm[level->nummonsters].starty = y*TILEH+TILEH; level->initm[level->nummonsters].id = P_SPIDER; level->nummonsters++; } else if (*p == '?') { /* figure out background type */ if (lasttile->solid) { tileid = level->map[(y-1)*LEVELW+x]; } else { tileid = lasttile->id; } // tileid = level->bgtileid; level->initm[level->nummonsters].startx = x*TILEW+(TILEW/2); level->initm[level->nummonsters].starty = y*TILEH+(TILEH-2); level->initm[level->nummonsters].id = P_HELP; if (curhelp >= numhelp) { printf("Error in level - more help icons than help texts.\n"); exit(1); } else { level->initm[level->nummonsters].help = strdup(help[curhelp]); curhelp++; } level->nummonsters++; } else if (*p == '*') { tileid = T_FULL; } else if (*p == ';') { tileid = T_TELEPORT; } else if (*p == ':') { tileid = T_TELEPORT2; } else if (*p == '.') { tileid = T_TELEPORTDEST; } else if (*p == '/') { tileid = T_SLOPEUP; } else if (*p == '\\') { tileid = T_SLOPEDOWN; } else if (*p == '1') { /* figure out background type */ if (lasttile->solid) { tileid = level->map[(y-1)*LEVELW+x]; } else { tileid = lasttile->id; } level->p1x = x; level->p1y = y; } else { tileid = level->bgtileid; } } if (!gettile(tileid)) { printf("invalid tileid: %d\n",tileid); fclose(f); return B_TRUE; } if (x > LEVELW) { printf("Too many tiles on line %d: %d,%d\n",y,x,y); fclose(f); return B_TRUE; } if (y >= LEVELH) { printf("Too many lines at line %d: %d,%d\n",y,x,y); fclose(f); return B_TRUE; } level->map[y*LEVELW+x] = tileid; lasttile = gettile(tileid); x++; } if (x < LEVELW+1) { printf("Not enough tiles on line: y = %d\n",y); fclose(f); return B_TRUE; } y++; x = 0; fgets(buf, BUFLEN, f); } fclose(f); if ((numhelp > 0) && (curhelp != numhelp)) { printf("WARNING: Unused help text. First unused is '%s'\n",help[curhelp]); } if (y < LEVELH) { printf("Incomplete level: y=%d, should be %d.\n", y,LEVELH); return B_TRUE; } if ((level->p1x == 0) || (level->p1y == 0)) { printf("Level is missing player 1 start position.\n"); return B_TRUE; } /* free help texts */ for (i = 0; i < numhelp; i++) { free(help[i]); } /* set current level pointer */ curlevel = level; /* add player */ if (player == NULL) { addsprite(P_PLAYER, (curlevel->p1x * TILEW) + (TILEW/2), (curlevel->p1y * TILEH) + TILEH-2 , "Player" , B_TRUE); } else { player->x = (curlevel->p1x * TILEW) + (TILEW/2); player->y = (curlevel->p1y * TILEH) + TILEH-2; } player = lastsprite; /* add monsters */ for (i = 0; i < level->nummonsters; i++) { char name[MIDBUFLEN]; if (level->initm[i].id == P_HELP) { strncpy(name, level->initm[i].help, MIDBUFLEN); } else { strcpy(name, "Monster"); } addsprite(level->initm[i].id, level->initm[i].startx, level->initm[i].starty, name, B_TRUE); } gtime = 0; return B_FALSE; } int loadtiletypes(char *filename) { tiletype_t *t = NULL; int i; int state; FILE *f; char buf[BUFLEN]; char *p,*pp; state = 0; f = fopen(filename,"rt"); if (!f) { printf("can't open tiles file\n"); return B_TRUE; } fgets(buf, BUFLEN, f); while (!feof(f)) { if (state == 0) { if (strstr(buf, "tile") == buf) { if (t == NULL) { tiletype = malloc(sizeof(tiletype_t)); t = tiletype; t->prev = NULL; } else { t->next = malloc(sizeof(tiletype_t)); t->next->prev = t; t = t->next; } p = strtok(buf, " "); p = strtok(NULL, " "); /* strip newline */ p[strlen(p)-1] = '\0'; strcpy(t->name, p); /* defaults */ t->id = 0; t->water = B_FALSE; t->spikes = B_FALSE; t->solid = B_TRUE; for (i = 0; i < TILEW; i++) { t->lowness[i] = 0; } t->img = NULL; t->next = NULL; state = 1; } } else if (state == 1) { /* inside a definition */ if (strstr(buf, "end") == buf) { //printf("got tile %d: %s (solid=%d)\n",t->id,t->name,t->solid); state = 0; } else if (strstr(buf, "id") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); t->id = atoi(p); } else if (strstr(buf, "lowness") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); pp = strtok(p, ","); for (i = 0;i < TILEW; i++) { t->lowness[i] = atoi(pp); pp = strtok(NULL, ","); } } else if (strstr(buf, "solid") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); t->solid = atoi(p); } else if (strstr(buf, "spikes") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); t->spikes = atoi(p); } else if (strstr(buf, "water") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); t->water = atoi(p); } else if (strstr(buf, "file") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); if (t->img) { SDL_FreeSurface(t->img); t->img = NULL; } /* strip newline */ p[strlen(p)-1] = '\0'; t->img = IMG_Load(p); if (!t->img) { printf("cannot load tile image file: '%s'\n",p); fclose(f); return B_TRUE; } SDL_SetColorKey(t->img, SDL_SRCCOLORKEY, SDL_MapRGB(screen->format, 0, 0, 0)); } } fgets(buf, BUFLEN, f); } fclose(f); return B_FALSE; } int loadimagesets(void) { int p,i; SDL_Surface *tempimg; SDL_Surface *reds; imageset[P_PLAYER].img[F_WALK1] = IMG_Load("pdwarf.png"); imageset[P_PLAYER].img[F_JUMP] = IMG_Load("pdwarfjump.png"); imageset[P_PLAYER].img[F_FALL] = IMG_Load("pdwarffall.png"); imageset[P_PLAYER].img[F_CAUGHT] = IMG_Load("pdwarf.png"); imageset[P_PLAYER].img[F_DEAD] = IMG_Load("dwarfdie.png"); /* next 3 are auto generated */ imageset[P_PLAYER].img[F_CLIMB1] = IMG_Load("dclimb1.png"); imageset[P_PLAYER].img[F_CLIMB2] = IMG_Load("dclimb2.png"); imageset[P_PLAYER].numimages = 10; imageset[P_SNAKE].img[F_WALK1] = IMG_Load("snake.bmp"); imageset[P_SNAKE].img[F_JUMP] = IMG_Load("snakejump.bmp"); imageset[P_SNAKE].img[F_FALL] = IMG_Load("snakejump.bmp"); imageset[P_SNAKE].img[F_CAUGHT] = IMG_Load("snakecaught.bmp"); imageset[P_SNAKE].img[F_DEAD] = IMG_Load("snakedead.bmp"); /* next 3 are auto generated */ imageset[P_SNAKE].numimages = 8; imageset[P_RAT].img[F_WALK1] = IMG_Load("rat.bmp"); imageset[P_RAT].img[F_JUMP] = IMG_Load("ratjump.bmp"); imageset[P_RAT].img[F_FALL] = IMG_Load("ratjump.bmp"); imageset[P_RAT].img[F_CAUGHT] = IMG_Load("ratcaught.bmp"); imageset[P_RAT].img[F_DEAD] = IMG_Load("ratdead.bmp"); /* next 3 are auto generated */ imageset[P_RAT].numimages = 8; imageset[P_BEE].img[F_WALK1] = IMG_Load("bee.bmp"); imageset[P_BEE].img[F_JUMP] = IMG_Load("beejump.bmp"); imageset[P_BEE].img[F_FALL] = IMG_Load("beejump.bmp"); imageset[P_BEE].img[F_CAUGHT] = IMG_Load("beecaught.bmp"); imageset[P_BEE].img[F_DEAD] = IMG_Load("beedead.bmp"); /* next 3 are auto generated */ imageset[P_BEE].numimages = 8; imageset[P_SPIDER].img[F_WALK1] = IMG_Load("spider.bmp"); imageset[P_SPIDER].img[F_JUMP] = IMG_Load("spiderjump.bmp"); imageset[P_SPIDER].img[F_FALL] = IMG_Load("spiderfall.bmp"); imageset[P_SPIDER].img[F_CAUGHT] = IMG_Load("spidercaught.bmp"); imageset[P_SPIDER].img[F_DEAD] = IMG_Load("spiderdead.bmp"); /* next 3 are auto generated */ imageset[P_SPIDER].numimages = 8; imageset[P_CLOUD].img[F_WALK1] = IMG_Load("cloud.bmp"); imageset[P_CLOUD].img[F_JUMP] = IMG_Load("cloud.bmp"); imageset[P_CLOUD].img[F_FALL] = IMG_Load("cloud.bmp"); imageset[P_CLOUD].img[F_CAUGHT] = IMG_Load("cloud.bmp"); imageset[P_CLOUD].img[F_DEAD] = IMG_Load("cloud.bmp"); imageset[P_CLOUD].numimages = 2; imageset[P_CHEESE].img[F_WALK1] = IMG_Load("cheese.bmp"); imageset[P_CHEESE].numimages = 1; imageset[P_ICECREAM].img[F_WALK1] = IMG_Load("icecream.bmp"); imageset[P_ICECREAM].numimages = 1; imageset[P_CHIPS].img[F_WALK1] = IMG_Load("chips.bmp"); imageset[P_CHIPS].numimages = 1; imageset[P_BURGER].img[F_WALK1] = IMG_Load("burger.bmp"); imageset[P_BURGER].numimages = 1; imageset[P_SPEED].img[F_WALK1] = IMG_Load("speed.bmp"); imageset[P_SPEED].numimages = 1; imageset[P_NUMNETS].img[F_WALK1] = IMG_Load("numnets.bmp"); imageset[P_NUMNETS].numimages = 1; imageset[P_BIGNET].img[F_WALK1] = IMG_Load("bignet.bmp"); imageset[P_BIGNET].numimages = 1; imageset[P_HELP].img[F_WALK1] = IMG_Load("help.bmp"); imageset[P_HELP].numimages = 1; /* bullets */ imageset[P_SPIT].img[F_WALK1] = IMG_Load("spit.bmp"); imageset[P_SPIT].numimages = 1; /* generate rotated/flipped images */ for (p = 0; p < MAXPTYPES; p++) { if (!isfruit(p) && !isbullet(p)) { tempimg = rotozoomSurface(imageset[p].img[F_DEAD],90,1,0); imageset[p].img[F_DEAD2] = SDL_DisplayFormat(tempimg); tempimg = rotozoomSurface(imageset[p].img[F_DEAD],180,1,0); imageset[p].img[F_DEAD3] = SDL_DisplayFormat(tempimg); tempimg = rotozoomSurface(imageset[p].img[F_DEAD],270,1,0); imageset[p].img[F_DEAD4] = SDL_DisplayFormat(tempimg); } for (i = 0; i < imageset[p].numimages; i++) { SDL_Surface *origi; SDL_SetColorKey(imageset[p].img[i], SDL_SRCCOLORKEY, SDL_MapRGB(screen->format, 0, 0, 0)); origi = imageset[p].img[i]; /* flipped image */ imageset[p].img[MAXFRAMES+i] = rotozoomSurfaceXY(imageset[p].img[i], 0, -1,1,0); SDL_SetColorKey(imageset[p].img[MAXFRAMES+i], SDL_SRCCOLORKEY, SDL_MapRGB(screen->format, 0, 0, 0)); /* angry image */ reds = SDL_CreateRGBSurface(SDL_SWSURFACE, origi->w, origi->h, origi->format->BitsPerPixel, origi->format->Rmask, origi->format->Gmask,origi->format->Bmask, 0); SDL_FillRect(reds, NULL, SDL_MapRGB(reds->format, 255, 0, 0)); SDL_SetAlpha(reds, SDL_SRCALPHA,100); imageset[p].img[MAXFRAMES*2+i] = rotozoomSurfaceXY(origi, 0, 1,1,0); SDL_BlitSurface(reds, NULL, imageset[p].img[MAXFRAMES*2+i], NULL); SDL_FreeSurface(reds); temps = SDL_DisplayFormat(imageset[p].img[MAXFRAMES*2+i]); SDL_FreeSurface(imageset[p].img[MAXFRAMES*2+i]); imageset[p].img[MAXFRAMES*2+i] = temps; SDL_SetColorKey(imageset[p].img[MAXFRAMES*2+i], SDL_SRCCOLORKEY, SDL_MapRGB(imageset[p].img[MAXFRAMES*2+i]->format, 101, 0, 0)); /* flipped angry image */ reds = SDL_CreateRGBSurface(SDL_SWSURFACE, origi->w, origi->h, origi->format->BitsPerPixel, origi->format->Rmask, origi->format->Gmask,origi->format->Bmask, 0); SDL_FillRect(reds, NULL, SDL_MapRGB(reds->format, 255, 0, 0)); SDL_SetAlpha(reds, SDL_SRCALPHA,100); imageset[p].img[MAXFRAMES*3+i] = rotozoomSurfaceXY(origi, 0, -1,1,0); SDL_BlitSurface(reds, NULL, imageset[p].img[MAXFRAMES*3+i], NULL); SDL_FreeSurface(reds); temps = SDL_DisplayFormat(imageset[p].img[MAXFRAMES*3+i]); SDL_FreeSurface(imageset[p].img[MAXFRAMES*3+i]); imageset[p].img[MAXFRAMES*3+i] = temps; SDL_SetColorKey(imageset[p].img[MAXFRAMES*3+i], SDL_SRCCOLORKEY, SDL_MapRGB(imageset[p].img[MAXFRAMES*3+i]->format, 101, 0, 0)); } } return B_FALSE; } 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; } 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 setdefaults(sprite_t *s) { s->speed = 1; s->teleporting = 0; s->climbing = 0; s->jumping = 0; s->jumpspeed = 0; s->jumpdir = 1; s->netting = 0; s->netmax = 1; s->netcaught = 0; s->netbig = 0; s->falling = 0; s->fallspeed = 0; s->dir = 1; s->slamming = 0; s->dead = 0; s->angry = 0; s->invuln = 0; s->jumptimer = 0; s->bullet = NULL; s->owner = NULL; s->willbecome = P_CHEESE; switch (s->id) { case P_BEE: case P_CLOUD: s->flies = B_TRUE; break; default: s->flies = B_FALSE; break; } switch (s->id) { case P_CHEESE: s->score = 500; break; case P_ICECREAM: s->score = 1000; break; case P_CHIPS: s->score = 2000; break; case P_BURGER: s->score = 4000; break; default: break; } s->caughtby = NULL; s->caughtstate = 0; s->xs = -99; s->ys = -99; s->timer = 0; } /* initial is TRUE if we are populating the level for the first time */ sprite_t *addsprite(int id, int x, int y, char *name , int initial) { sprite_t *s; if (sprite == NULL) { sprite = malloc(sizeof(sprite_t)); s = sprite; s->prev = NULL; } else { s = lastsprite; s->next = malloc(sizeof(sprite_t)); s->next->prev = s; s = s->next; } s->id = id; s->x = x; s->y = y; if (s->id == P_CLOUD) { s->img = rotozoomSurfaceXY(imageset[id].img[F_WALK1],0,1,1,0); } else { s->img = imageset[id].img[F_WALK1]; } if (s->y > (480 - TILEH-1)) { s->y = 480 - TILEH-1; } strcpy(s->name, name); if (s == sprite) { s->netbg = SDL_CreateRGBSurface(SDL_SWSURFACE, 200, 64, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); } else { s->netbg = NULL; } setdefaults(s); if (!initial) { if (isfruit(s->id)) { if (s->id != P_HELP) { // help icons don't time out s->timer = 500; } } } s->next = NULL; lastsprite = s; return s; } tiletype_t *gettileat(int pixx,int pixy, int *tilex,int *tiley) { int tx,ty; tx = pixx / TILEW; ty = pixy / TILEH; if (tilex != NULL) { *tilex = tx; } if (tiley != NULL) { *tiley = ty; } return gettile(curlevel->map[ty*LEVELW+tx]); } 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); 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; 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 drawsprites(void) { sprite_t *s; for (s = sprite; s != NULL; s = s->next) { drawsprite(s); } } void drawsprite(sprite_t *s) { SDL_Rect area; int frame; /* select frame */ if (isfruit(s->id)) { frame = F_WALK1; } else if (isbullet(s->id)) { frame = F_WALK1; } else if (s->dead) { if (s == player) { frame = F_DEAD; } else { frame = F_DEAD + ((timer/2) % 4); } } else if (s->caughtby) { frame = F_CAUGHT; } else if (s->climbing) { frame = F_CLIMB1 + ((timer/12) % 2); } else if (s->jumping) { frame = F_JUMP; } else if (s->falling) { frame = F_FALL; } else if (!s->teleporting) { if ((s->id == P_SPIDER) && (s->ys != -99)) { frame = F_FALL; } else { if (s->moved) { if ((timer/12) % 2 == 0) { frame = F_WALK1; } else { frame = F_JUMP; } } else { frame = F_WALK1; } } } /* x-flip if required */ if (s->dir == -1) { frame += MAXFRAMES; } /* make red if required */ if (s->angry) { frame += (MAXFRAMES*2); } if ((s->id != P_CLOUD) && (!s->teleporting)) { s->img = imageset[s->id].img[frame]; } /* spider's climbing web */ if ((s->id == P_SPIDER) && ((s->ys != -99) || s->falling) && (!s->dead) && (!s->caughtby)) { tiletype_t *tt; int x = s->x; int y = s->y - s->img->h/2; int tx=0,ty = 0; int done = B_FALSE; for (y = s->y ; !done ; y-= TILEH) { tt = gettileat(x,y,&tx,&ty); if ((tt == NULL) || (tt->solid)) { done = B_TRUE; } } drawline16(screen,s->x,s->y - (s->img->h/2),s->x,ty*TILEH+TILEH-1,white); } area.x = s->x - (s->img->w/2); area.y = s->y - (s->img->h); area.w = 0; area.h = 0; if (area.y < (480-s->img->h)) { if (s->invuln) { if (timer % 2 == 0) { SDL_BlitSurface(s->img, NULL, screen, &area); } } else { SDL_BlitSurface(s->img, NULL, screen, &area); /* for opengl */ //SDL_UpdateRect(screen, area.x, area.y, area.w, area.h); } } /* caughtby lines */ if ((s->caughtby) && (s->caughtstate == 2)){ drawline16(screen, s->x,s->y - s->img->h, s->caughtby->x,s->caughtby->y-(s->caughtby->img->h/2), white); drawline16(screen, s->x,s->y - (s->img->h/2), s->caughtby->x,s->caughtby->y-(s->caughtby->img->h/2), white); drawline16(screen, s->x,s->y, s->caughtby->x,s->caughtby->y-(s->caughtby->img->h/2), 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 killsprite(sprite_t *s) { sprite_t *nextone, *lastone; sprite_t *s2; /* remove references to this sprite before removing it */ for (s2 = sprite ; s2 ; s2 = s2->next) { if (s2->owner == s) { s2->owner = NULL; } if (s2->bullet == s) { s2->bullet = NULL; } } nextone = s->next; if (nextone != NULL) { nextone->prev = s->prev; } else { /*last sprite */ lastsprite = s->prev; } if (s->prev == NULL) { /* first sprite */ nextone = sprite->next; free(sprite); sprite = nextone; } else { lastone = s->prev; free (lastone->next ); lastone->next = nextone; } } 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 == -1) { 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 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, ypos,NULL,NULL); if (tt->solid) return B_TRUE; tt = gettileat(s->x - s->img->w/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->falling) { 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); /* 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 */ 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 (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->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 == 1)) { s2->caughtstate = 2; } } } } } if (s->slamming) { s->slamangle += (10 * (M_PI/180)); if (s->slamangle >= (180 * (M_PI/180))) { int xdiff,ydiff,xnet = 0,ynet = 0; int pointsinc = 250; int psize = 6; 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)) { /* becomes a fruit */ 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; } 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) { /* becomes a powerup */ s2->willbecome = poweruptypes[curpoweruptype]; if (poweruptypes[++curpoweruptype] == -1) { curpoweruptype = 0; } die(s2); pointsinc *= 2; psize += 10; } } } } /* 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; } } } } void flip(void) { #ifdef OPENGL SDL_GL_SwapBuffers(); SDL_UpdateRect(screen,0,0,screen->w,screen->h); #else SDL_Flip(screen); #endif } 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; } /* 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) { /* 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) { 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) { 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) { 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) { 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) { addtext(320,240,TEXTSIZE_HELP, s->name, &white,HELPDELAY); return B_TRUE; } return B_FALSE; } int isfruit(int id) { switch (id) { case P_CHEESE: case P_ICECREAM: case P_CHIPS: case P_BURGER: case P_SPEED: case P_NUMNETS: case P_BIGNET: case P_HELP: return B_TRUE; } return B_FALSE; } int isbullet(int id) { if (id == P_SPIT) 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; return B_FALSE; } /* inline void drawpixel32(SDL_Surface *screen, int x, int y, SDL_Color c) { Uint32 *bufp; // check x/y if (x >= screen->w) return; if (y >= screen->h) return; if (x < 0) return; if (y < 0) return; bufp = (Uint32 *)screen->pixels + (y*screen->pitch / 2) + x; *bufp = SDL_MapRGB(screen->format, c.r, c.g, c.b); } */ inline void drawpixel16(SDL_Surface *screen, int x, int y, SDL_Color c) { Uint16 *bufp; /* check x/y */ if (x >= screen->w) return; if (y >= screen->h) return; if (x < 0) return; if (y < 0) return; bufp = (Uint16 *)screen->pixels + (y*screen->pitch / 2) + x; *bufp = SDL_MapRGB(screen->format, c.r, c.g, c.b); } void drawline16(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color c) { 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++) { drawpixel16(screen,x,y,c); if (d < 0) { d += dinc1; x += xinc1; y += yinc1; } else { d += dinc2; x += xinc2; y += yinc2; } } } void drawbox16(SDL_Surface *screen, int x1, int y1, int x2, int y2, SDL_Color *c, SDL_Color *fc) { if (fc != NULL) { /* fill */ if (((x2 - x1) >= 2) && ((y2 - y1) >= 2)) { int y; for (y = (y1+1) ; y <= (y2-1); y++) { drawline16(screen, x1+1, y, x2-1,y,*fc); } } } drawline16(screen,x1,y1,x2,y1,*c); drawline16(screen,x1,y1,x1,y2,*c); drawline16(screen,x1,y2,x2,y2,*c); drawline16(screen,x2,y1,x2,y2,*c); } int getcolor(SDL_Surface *dest, int x, int y, SDL_Color *col) { Uint32 pixel; int bpp = dest->format->BytesPerPixel; char *ppos; unsigned char r,g,b,a; ppos = (char *) dest->pixels; /* offset y */ ppos += (dest->pitch * y); /* offset x */ ppos += (bpp * x); memcpy(&pixel, ppos, bpp); if (dest->format->BitsPerPixel == 32) { SDL_GetRGBA(pixel, dest->format, &r,&g,&b, &a); col->r = r; col->g = g; col->b = b; col->unused = a; } else if (dest->format->BitsPerPixel == 16) { SDL_GetRGB(pixel, dest->format, &r,&g,&b); col->r = r; col->g = g; col->b = b; } else if (dest->format->BitsPerPixel == 8) { *col = dest->format->palette->colors[(Uint8)pixel]; } return 0; /* bpp = dest->format->BytesPerPixel; if (bpp != 2) { printf("bpp isnt 2!!!\n"); fflush(stdout); } //pixel = (Uint32 *) (dest->pixels + (y * dest->w) + x) ; pixel = (Uint32 *) (dest->pixels + y * dest->pitch + x * bpp); SDL_GetRGB(*pixel,dest->format, &col->r, &col->g, &col->b ); return 0; */ } int chartomonster(char ch) { switch (ch) { case 'c': return P_CLOUD; case 'r': return P_RAT; case 'S': return P_SNAKE; case 'a': return P_BEE; case 's': return P_SPIDER; case '?': return P_HELP; case '1': return P_PLAYER; } return -1; } 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"); } void drawpalette(void) { tiletype_t *tt; SDL_Rect area; tiletype_t *bg = gettile(curlevel->bgtileid); int p; int maxheight; /* draw all tiles */ area.x = PALX; area.y = PALY; area.w = TILEW; area.h = TILEH; for (tt = tiletype; tt != NULL; tt = tt->next) { /* draw background */ SDL_BlitSurface(bg->img, NULL, screen, &area); /* draw tile */ SDL_BlitSurface(tt->img, NULL, screen, &area); /* draw selector box */ if (seltile == tt) { drawbox16(screen,area.x,area.y,area.x+area.w-1,area.y+area.h-1,&red,NULL); drawbox16(screen,area.x+1,area.y+1,area.x+area.w-2,area.y+area.h-2,&red,NULL); } /* move on to next position */ area.x += TILEW; if (area.x >= EDITORW) { area.x = PALX; area.y += TILEH; } } SDL_UpdateRect(screen, PALX,PALY,PALW,PALH); /* draw all sprites */ maxheight = 0; area.x = SPALX; area.y = SPALY; for (p = 0; p < MAXPTYPES; p++) { SDL_Surface *firstimg; /* select images */ firstimg = imageset[p].img[F_WALK1]; area.w = firstimg->w; area.h = firstimg->h; if (area.h > maxheight) maxheight = area.h; /* clear bg */ drawbox16(screen,area.x,area.y,area.x+area.w,area.y+area.h,&black,&black); /* draw sprite */ SDL_BlitSurface(firstimg, NULL, screen, &area); /* draw selector box */ if (selsprite == p) { drawbox16(screen,area.x,area.y, area.x+area.w-1,area.y+area.h-1,&red,NULL); drawbox16(screen,area.x+1,area.y+1, area.x+area.w-2,area.y+area.h-2,&red,NULL); } /* move to next position */ area.x += area.w; if (area.x >= EDITORW) { area.x = SPALX; area.y += maxheight; maxheight = 0; } } SDL_UpdateRect(screen, SPALX,SPALY,SPALW,SPALH); }