#include #include #include #include #include #include #include #include #include #include #include #include #include "rc.h" SDL_Surface *screen; int curlevelnum = 1; level_t *curlevel; sprite_t *sprite = NULL; /* main sprite list */ sprite_t *player; sprite_t *lastsprite; SDL_Color red = {255, 0, 0, 0}; SDL_Color white = {255, 255, 255, 0}; int timer = 0; int toggletimer = 0; int main (int argc, char **argv) { Uint8 *keys; sprite_t *s,*nextsprite; if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE)==-1) { printf("SDL_Init: %s\n", SDL_GetError()); exit(1); } atexit(cleanup); screen = SDL_SetVideoMode(640,480,16,SDL_HWSURFACE|SDL_DOUBLEBUF); if (loadimagesets()) { return 1; } if (loadlevel(curlevelnum)) { return 1; } drawlevel(); SDL_Flip(screen); timer = 0; printf("player y is %0.1f\n",player->y); fflush(stdout); while (1) { /* remove player */ for (s = sprite ; s ; s = s->next) { removesprite(s); } removenetting(player); /* check for death & update movement status*/ for (s = sprite ; s ; s = nextsprite) { s->moved = B_FALSE; nextsprite = s->next; if (s->dead == 4) { killsprite(s); } } /* check for keys */ SDL_PumpEvents(); keys = SDL_GetKeyState(NULL); if (keys[SDLK_RETURN]) { if (toggletimer == 0) { SDL_WM_ToggleFullScreen(screen); toggletimer = 50; } } if (keys[SDLK_ESCAPE]) { return 1; } if (keys[SDLK_RIGHT]) { if (!player->jumping) { if (!isonladder(player) || player->falling || isonground(player)) { movex(player, player->speed); } } player->dir = 1; } if (keys[SDLK_LEFT]) { if (!player->jumping) { if (!isonladder(player) || player->falling || isonground(player)) { movex(player, -player->speed); } } player->dir = -1; } if (keys[SDLK_UP]) { if (isonladder(player) || isladderabove(player)) { player->y -= player->speed; } } if (keys[SDLK_x]) { if (!player->jumping) { if (!player->falling) { if (isonground(player) || isonladder(player)) { player->jumping = 1; if (keys[SDLK_RIGHT]) { player->jumpdir = 1; } else if (keys[SDLK_LEFT]) { player->jumpdir = -1; } else { player->jumpdir = 0; } player->jumpspeed = 5; } } } } if (keys[SDLK_z]) { if (!player->netting) { if (keys[SDLK_DOWN]) { /* slam */ if ((!player->slamming) && (isonground(player))) { player->slamming = B_TRUE; player->slamangle = 0; player->netxstart = player->x - (player->img->w/2)*player->dir; player->netystart = player->y; } } else { /* shoot net */ player->netting = 1; player->netspeed = NETSPEED; player->netlen = 0; player->netdir = player->dir; } } } for (s = sprite; s ; s = s->next) { movesprite(s); } /* 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); } drawnetting(player); /* draw player */ for (s = sprite ; s ; s = s->next) { drawsprite(s); } SDL_Flip(screen); if (++timer == 100) timer = 0; if (toggletimer > 0) toggletimer--; } return 0; } void cleanup(void) { 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 (s2->dead) collide = B_FALSE; if (collide) { /* check for colission with our net */ if ((s->netting) && (!s2->caughtby)) { xdiff = (s->x + s->netlen*s->netdir) - s2->x; if (xdiff < 0) xdiff = -xdiff; ydiff = s->netystart - s2->y; if (ydiff < 0) ydiff = -ydiff; if ((xdiff <= s2->img->w) && (ydiff <= s2->img->h)) { s2->caughtby = s; s2->caughtstate = 1; } } else { /* check for collision with us */ xdiff = s->x - s2->x; if (xdiff < 0) xdiff = -xdiff; ydiff = s->y - s2->y; 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) { /* kill the fruit */ s2->dead = 4; /* give points to the player */ } } if (ismonster(s2->id)) { /* TODO: kill player */ } } } } } } tiletype_t *gettile(int tid) { tiletype_t *t; for (t = tiletype; t ; t = t->next) { if (t->id == tid) return t; } return NULL; } void movesprite(sprite_t *s) { int rv; /* avoid edges of screen */ if (s->y < s->img->h) { s->y = s->img->h; } if (s->jumping) { movex(s, s->jumpdir*s->speed); return; } else 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->ys = ((rand() % 3) + 2) * -1; s->dead = 2; s->bounces = 0; return; } else if (s->dead == 2) { /* dying */ s->x += s->xs; s->y += s->ys; if (s->x >= (640-(s->img->w/2))) { if (s->xs > 0) { s->xs = -s->xs; s->bounces++; } } else if (s->x <= 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 */ s->x += s->xs; s->y += s->ys; if (s->x >= (640-(s->img->w/2))) { if (s->xs > 0) { s->xs = -s->xs; s->bounces++; } } else if (s->x <= 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; addsprite(P_CHEESE, x, y, "Cheese"); } } return; } if (isonground(s)) { if ((!s->falling) && (!s->jumping)) { adjustheight(s); } } if (s->id == P_RAT) { if (!s->falling) { tiletype_t *tt; /* if there's not a hole in front of us, move */ tt = gettileat(s->x + s->dir+s->speed,s->y,NULL,NULL); if (tt->solid == S_NOTSOLID) { s->dir = -s->dir; } else { rv = movex(s, s->dir*s->speed); if (rv) { s->dir = -s->dir; } } } } } void dotileeffects(sprite_t *s) { tiletype_t *tt; if (s->jumping || s->dead || s->caughtby) { return; } tt = gettileat(s->x,s->y+3,NULL,NULL); if (tt->id == T_RIGHT) { movex(s, 1.5); } if (tt->id == T_LEFT) { movex(s, -1.5); } } void drawtile(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, screen, &area); tt = gettile(curlevel->map[y*LEVELW+x]); if (tt->id != curlevel->bgtileid) { SDL_BlitSurface(tt->img, NULL, screen, &area); } } void drawlevel(void) { int x,y; for (x = 0; x < LEVELW; x++) { for (y = 0; y < LEVELH; y++) { drawtile(x,y); } } } int loadlevel(int lnum) { FILE *f; int x,y; char buf[BUFLEN]; char filename[BUFLEN]; char *p; int tileid; int i; level = malloc(sizeof(level_t)); level->id = 0; sprintf(level->name, "Level %d",lnum); level->prev = NULL; level->next = NULL; /* default */ level->p1x = 0; level->p1y = 0; sprintf(filename, "level%d.dat",lnum); f = fopen(filename,"rt"); if (!f) { printf("can't open level file\n"); return B_TRUE; } /* 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; } } /* TODO: clear player linked list */ /* read tileset */ fgets(buf, BUFLEN, f); if (strstr(buf, "tileset") == buf) { p = strtok(buf, " "); p = strtok(NULL, " "); /* strip newline */ p[strlen(p)-1] = '\0'; 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; } x = 0; y = 0; level->nummonsters = 0; fgets(buf, BUFLEN, f); while (!feof(f)) { for (p = buf; *p; p++) { if (*p == '~') { tileid = T_LAND; } else if (*p == '=') { tileid = T_LADDER; } else if (*p == '-') { tileid = T_LADDERTOP; } else if (*p == '>') { tileid = T_RIGHT; } else if (*p == '<') { tileid = T_LEFT; } else if (*p == '^') { tileid = T_SPIKES; } else if (*p == 'r') { 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 == '*') { tileid = T_FULL; } else if (*p == '/') { tileid = T_SLOPEUP; } else if (*p == '\\') { tileid = T_SLOPEDOWN; } else if (*p == '1') { tileid = level->bgtileid; 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) || (y > LEVELH)) { printf("Level position out of range: %d,%d\n",x,y); fclose(f); return B_TRUE; } level->map[y*LEVELW+x] = 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 (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; } /* set current level pointer */ curlevel = level; /* add player */ addsprite(P_PLAYER, (curlevel->p1x * TILEW) + (TILEW/2), (curlevel->p1y * TILEH) + TILEH-2 , "Player" ); player = lastsprite; /* add monsters */ for (i = 0; i < level->nummonsters; i++) { addsprite(level->initm[i].id, level->initm[i].startx, level->initm[i].starty, "Monster"); } 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->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, "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; 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("pdwarf.png"); /* next 3 are auto generated */ imageset[P_PLAYER].numimages = 8; imageset[P_RAT].img[F_WALK1] = IMG_Load("rat.bmp"); imageset[P_RAT].img[F_JUMP] = IMG_Load("rat.bmp"); imageset[P_RAT].img[F_FALL] = IMG_Load("rat.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_CHEESE].img[F_WALK1] = IMG_Load("cheese.bmp"); imageset[P_CHEESE].numimages = 1; /* generate rotated/flipped images */ for (p = 0; p < MAXPTYPES; p++) { imageset[p].img[F_DEAD2] = rotozoomSurface(imageset[p].img[F_DEAD],90,1,0); imageset[p].img[F_DEAD3] = rotozoomSurface(imageset[p].img[F_DEAD],180,1,0); imageset[p].img[F_DEAD4] = rotozoomSurface(imageset[p].img[F_DEAD],270,1,0); for (i = 0; i < imageset[p].numimages; i++) { SDL_SetColorKey(imageset[p].img[i], SDL_SRCCOLORKEY, SDL_MapRGB(screen->format, 0, 0, 0)); imageset[p].img[MAXFRAMES+i] = rotozoomSurfaceXY(imageset[p].img[i], 0, -1,1,0); } } return B_FALSE; } double getspeed(int id) { if (id == P_PLAYER) return 1; else if (id == P_RAT) return 1.5; else if (id == P_CHEESE) return 0; return 1; } int addsprite(int id, int x, int y, char *name ) { 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; 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_HWSURFACE, 200, 10, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask,screen->format->Bmask, screen->format->Amask); } else { s->netbg = NULL; } s->speed = getspeed(id); s->jumping = 0; s->jumpdir = 1; s->netting = 0; s->falling = 0; s->fallspeed = 0; s->dir = 1; s->slamming = 0; s->dead = 0; s->caughtby = NULL; s->caughtstate = 0; s->next = NULL; lastsprite = s; return B_FALSE; } int loadsprites(void) { addsprite(P_PLAYER, 100, 400, "Player 1"); player = lastsprite; addsprite(P_RAT, 200, 200, "Rat"); addsprite(P_RAT, 400, 200, "Rat"); return B_FALSE; } 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) { 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.w = s->netlen; area.h = 7; SDL_BlitSurface(screen, &area,s->netbg, NULL); 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 drawsprite(sprite_t *s) { SDL_Rect area; int frame; /* select frame */ if (isfruit(s->id)) { frame = F_WALK1; } else if (s->dead) { frame = F_DEAD + ((timer/2) % 4); } else if (s->caughtby) { frame = F_CAUGHT; } else if (s->jumping) { frame = F_JUMP; } else if (s->falling) { frame = F_FALL; } else { if (s->moved) { if ((timer/6) % 2 == 0) { frame = F_WALK1; } else { frame = F_JUMP; } } else { frame = F_WALK1; } } /* x-flip if required */ if (s->dir == -1) { frame += MAXFRAMES; } s->img = imageset[s->id].img[frame]; area.x = s->x - (s->img->w/2); area.y = s->y - (s->img->h); area.w = 0; area.h = 0; SDL_BlitSurface(s->img, NULL, screen, &area); /* 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 = 7; if (s->netdir == 1) { area.x = s->netxstart + TILEW/2; } else { area.x = s->netxstart - TILEW/2 - s->netlen; } area.y = s->netystart; area.w = s->netlen; area.h = 7; if (s->netbg != NULL) { SDL_BlitSurface(s->netbg, &sarea, screen, &area); } } } void killsprite(sprite_t *s) { sprite_t *nextone, *lastone; 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(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 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 */ 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 (isonladder(s) && !s->falling && !s->jumping) { s->falling = B_FALSE; return; } 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; } } } else { if (isonground(s)) { s->falling = B_FALSE; } else { s->falling = B_TRUE; 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 >= (190 * (M_PI/180))) { /* if we hit the ground, kill anything we've caught */ s->slamming = 0; for (s2 = sprite; s2 ; s2 = s2->next) { if (s2->caughtby == s) { if (isongroundpoint(s2,s2->x,s->y)) { s2->dead = 1; } s2->caughtby = NULL; } } } } } 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)); 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; adjustheight(s); } 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; tt = gettileat(s->x,s->y-1,&tilex,&tiley); 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 isfruit(int id) { if (id == P_CHEESE) return B_TRUE; return B_FALSE; } int ismonster(int id) { if (id == P_RAT) return B_TRUE; return B_FALSE; } 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); }