ratcatcher/rc.c

3161 lines
67 KiB
C

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <math.h>
#include <SDL.h>
#include <SDL_keysym.h>
#include <SDL_rotozoom.h>
#include <SDL_ttf.h>
#include <SDL_framerate.h>
#include "rc.h"
FPSmanager manager;
SDL_Surface *temps;
SDL_Surface *screen;
TTF_Font *font[MAXLETTERHEIGHT];
char tempm[BUFLEN];
tiletype_t fakeblock;
/* 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;
sprite_t *s,*nextsprite;
char filename[BUFLEN];
int i;
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(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 = 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;
}
}
/* calculate fps delay */
SDL_initFramerate(&manager);
SDL_setFramerate(&manager, WANTFPS);
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 == 4) {
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;
} 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 ((!player->jumping) && (!player->slamming)) {
if (!isonladder(player) || player->falling || isonground(player)) {
movex(player, getspeed(player));
}
}
player->dir = 1;
}
if (keys[SDLK_LEFT]) {
if ((!player->jumping) && (!player->slamming)) {
if (!isonladder(player) || player->falling || isonground(player)) {
movex(player, -getspeed(player));
}
}
player->dir = -1;
}
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)) {
int whichway;
player->climbing = B_FALSE;
if (keys[SDLK_RIGHT]) {
whichway = 1;
} else if (keys[SDLK_LEFT]) {
whichway = -1;
} else {
whichway = 0;
}
jump(player, whichway);
}
}
}
}
}
if (keys[SDLK_z]) {
if ((!player->netting) && (!player->slamming)) {
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 {
if (player->netcaught < player->netmax) {
/* shoot net */
player->netting = 1;
if (player->netbig) {
player->netspeed = NETSPEED+3;
} else {
player->netspeed = NETSPEED;
}
player->netlen = 0;
player->netdir = player->dir;
}
}
}
}
}
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);
/* draw text */
drawtext();
drawscore();
drawnetting(player);
/* draw player */
for (s = sprite ; s ; s = s->next) {
drawsprite(s);
}
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) {
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;
/* give points to the player */
player->score = player->score + gotscore;
/* handle fruit effects */
if (!dofruiteffect(s2)) {
sprintf(tempm, "%d", gotscore);
addtext(s2->x,s2->y - s2->img->h/2, 16, tempm, &white,POINTSDELAY);
}
}
}
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;
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);
}
}
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;
}
// assign score
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:
s->score = 0;
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 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");
}