ratcatcher/shared.c

1412 lines
31 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 "defs.h"
#include "globals.h"
#include "shared.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;
int *ii;
mapping_t mapping[MAXMAPPINGS];
int nmappings = 0;
tiletype_t *lasttile;
int newversion;
int numanim = 0;
int tempanim[LEVELW*LEVELH];
if (!level) level = malloc(sizeof(level_t));
if (level->animtiles) free(level->animtiles);
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 tiletype linked list */
while (tiletype != NULL) {
int i;
tiletype_t *tt;
/* kill first tile */
for (i = 0; i < tiletype->numframes; i++) {
if (tiletype->img[i]) {
SDL_FreeSurface(tiletype->img[i]);
tiletype->img[i] = 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';
if ( level->tileset) free(level->tileset);
level->tileset = strdup(p);
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);
}
/* check whether we've got a new or old level version */
if (strstr(buf, ",")) {
/* new version */
newversion = B_TRUE;
printf("Level data is new version.\n");
} else {
/* old version */
newversion = B_FALSE;
printf("Level data is old version.\n");
}
x = 0;
y = 0;
while (!feof(f)) {
/* process a line of level data */
if (newversion) {
strncpy(buf2, buf, BUFLEN);
p = strtok(buf2, ",");
while (p) {
int numframes;
tileid = atoi(p);
/* validate it */
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;
}
/* all okay */
level->map[y*LEVELW+x] = tileid;
numframes = gettileframecount(tileid);
if (numframes == 1) {
// not animated
level->tileframe[y*LEVELW+x] = 0;
} else {
// animated
level->tileframe[y*LEVELW+x] = rand() % numframes;
tempanim[numanim] = y*LEVELW+x;
numanim++;
}
x++;
p = strtok(NULL, ",");
}
} else { /* old level data version */
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 == '|') {
tileid = T_WATERSPIKES;
} 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 newversion */
/* make sure enough data was found */
if (x < LEVELW+1) {
printf("Not enough tiles on line: y = %d\n",y);
fclose(f);
return B_TRUE;
}
/* go to next line */
y++;
x = 0;
fgets(buf, BUFLEN, f);
}
fclose(f);
// copy from our temp buffer into the real one
level->animtiles = malloc(sizeof(int) * (numanim+1));
memcpy(level->animtiles,tempanim,numanim*sizeof(int));
level->animtiles[numanim] = -1;
//level->animtiles = realloc(level->animtiles, (numanim+2) * sizeof(int)); // leave space for terminator
if ((numhelp > 0) && (curhelp != numhelp)) {
printf("WARNING: Unused help text. First unused is '%s'\n",help[curhelp]);
}
if (y < LEVELH) {
printf("Not enough lines in level: last 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;
printf("Loaded level. Animated tiles: ");
for (ii = level->animtiles ; ii && *ii != -1; ii++) {
printf("%d ",*ii);
}
printf(".\n");
return B_FALSE;
}
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;
case P_FLOWERRED:
s->score = 5;
break;
default:
s->score = 0;
break;
}
s->caughtby = NULL;
s->caughtstate = 0;
s->xs = -99;
s->ys = -99;
s->doomcount = 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->doomcount = 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]);
}
int loadtiletypes(char *filename) {
tiletype_t *t = NULL;
int i;
int state;
FILE *f;
char buf[BUFLEN];
char *p,*pp;
int uniq = 0 ;
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->animspeed = 0; // not animated
t->numframes = 1; // not animated
t->water = B_FALSE;
t->spikes = B_FALSE;
t->solid = B_TRUE;
for (i = 0; i < TILEW; i++) {
t->lowness[i] = 0;
}
for (i = 0; i < MAXTILEFRAMES; i++) {
t->img[i] = NULL;
}
t->next = NULL;
state = 1;
/* unique id */
t->uniqid = uniq;
uniq++;
}
} 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);
/* check */
state = 0;
} else if (strstr(buf, "id") == buf) {
p = strtok(buf, " ");
p = strtok(NULL, " ");
t->id = atoi(p);
} else if (strstr(buf, "animspeed") == buf) {
p = strtok(buf, " ");
p = strtok(NULL, " ");
t->animspeed = 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) {
int frame;
/* strip newline */
buf[strlen(buf)-1] = '\0';
p = strtok(buf, " ");
// read all images
frame = 0;
p = strtok(NULL, " ");
while (p) {
if (t->img[frame]) {
SDL_FreeSurface(t->img[frame]);
t->img[frame] = NULL;
}
t->img[frame] = IMG_Load(p);
if (!t->img[frame]) {
printf("cannot load tile image file: '%s'\n",p);
fclose(f);
return B_TRUE;
}
// black is transparent
SDL_SetColorKey(t->img[frame], SDL_SRCCOLORKEY, SDL_MapRGB(screen->format, 0, 0, 0));
// get next one
frame++;
p = strtok(NULL, " ");
}
t->numframes = frame;
// default animation speed
t->animspeed = 20;
}
}
fgets(buf, BUFLEN, f);
}
fclose(f);
return B_FALSE;
}
int loadimagesets(void) {
int p,i;
SDL_Surface *tempimg;
SDL_Surface *reds;
loadspriteimage(P_PLAYER,F_WALK1, "sprites/pdwarf.png");
loadspriteimage(P_PLAYER,F_JUMP, "sprites/pdwarfjump.png");
loadspriteimage(P_PLAYER,F_FALL, "sprites/pdwarffall.png");
loadspriteimage(P_PLAYER,F_CAUGHT, "sprites/pdwarf.png");
loadspriteimage(P_PLAYER,F_DEAD, "sprites/dwarfdie.png");
/* next 3 are auto generated */
loadspriteimage(P_PLAYER,F_CLIMB1, "sprites/dclimb1.png");
loadspriteimage(P_PLAYER,F_CLIMB2, "sprites/dclimb2.png");
imageset[P_PLAYER].numimages = 10;
loadspriteimage(P_SNAKE,F_WALK1, "sprites/snake.bmp");
loadspriteimage(P_SNAKE,F_JUMP, "sprites/snakejump.bmp");
loadspriteimage(P_SNAKE,F_FALL, "sprites/snakejump.bmp");
loadspriteimage(P_SNAKE,F_CAUGHT, "sprites/snakecaught.bmp");
loadspriteimage(P_SNAKE,F_DEAD, "sprites/snakedead.bmp");
/* next 3 are auto generated */
imageset[P_SNAKE].numimages = 8;
loadspriteimage(P_RAT,F_WALK1, "sprites/rat.bmp");
loadspriteimage(P_RAT,F_JUMP, "sprites/ratjump.bmp");
loadspriteimage(P_RAT,F_FALL, "sprites/ratjump.bmp");
loadspriteimage(P_RAT,F_CAUGHT, "sprites/ratcaught.bmp");
loadspriteimage(P_RAT,F_DEAD, "sprites/ratdead.bmp");
/* next 3 are auto generated */
imageset[P_RAT].numimages = 8;
loadspriteimage(P_BEE,F_WALK1, "sprites/bee.bmp");
loadspriteimage(P_BEE,F_JUMP, "sprites/beejump.bmp");
loadspriteimage(P_BEE,F_FALL, "sprites/beejump.bmp");
loadspriteimage(P_BEE,F_CAUGHT, "sprites/beecaught.bmp");
loadspriteimage(P_BEE,F_DEAD, "sprites/beedead.bmp");
/* next 3 are auto generated */
imageset[P_BEE].numimages = 8;
loadspriteimage(P_SPIDER,F_WALK1, "sprites/spider.bmp");
loadspriteimage(P_SPIDER,F_JUMP, "sprites/spiderjump.bmp");
loadspriteimage(P_SPIDER,F_FALL, "sprites/spiderfall.bmp");
loadspriteimage(P_SPIDER,F_CAUGHT, "sprites/spidercaught.bmp");
loadspriteimage(P_SPIDER,F_DEAD, "sprites/spiderdead.bmp");
/* next 3 are auto generated */
imageset[P_SPIDER].numimages = 8;
loadspriteimage(P_CLOUD,F_WALK1, "sprites/cloud.bmp");
loadspriteimage(P_CLOUD,F_JUMP, "sprites/cloud.bmp");
loadspriteimage(P_CLOUD,F_FALL, "sprites/cloud.bmp");
loadspriteimage(P_CLOUD,F_CAUGHT, "sprites/cloud.bmp");
loadspriteimage(P_CLOUD,F_DEAD, "sprites/cloud.bmp");
imageset[P_CLOUD].numimages = 2;
loadspriteimage(P_CHEESE,F_WALK1, "sprites/cheese.bmp");
imageset[P_CHEESE].numimages = 1;
loadspriteimage(P_ICECREAM,F_WALK1, "sprites/icecream.bmp");
imageset[P_ICECREAM].numimages = 1;
loadspriteimage(P_CHIPS,F_WALK1, "sprites/chips.bmp");
imageset[P_CHIPS].numimages = 1;
loadspriteimage(P_BURGER,F_WALK1, "sprites/burger.bmp");
imageset[P_BURGER].numimages = 1;
loadspriteimage(P_SPEED,F_WALK1, "sprites/speed.bmp");
imageset[P_SPEED].numimages = 1;
loadspriteimage(P_NUMNETS,F_WALK1, "sprites/numnets.bmp");
imageset[P_NUMNETS].numimages = 1;
loadspriteimage(P_BIGNET,F_WALK1, "sprites/bignet.bmp");
imageset[P_BIGNET].numimages = 1;
loadspriteimage(P_HELP,F_WALK1, "sprites/help.bmp");
imageset[P_HELP].numimages = 1;
loadspriteimage(P_FLOWERRED,F_WALK1, "sprites/flower-red.png");
imageset[P_FLOWERRED].numimages = 1;
/* bullets */
loadspriteimage(P_SPIT,F_WALK1, "sprites/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;
}
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 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 flip(void) {
#ifdef OPENGL
SDL_GL_SwapBuffers();
SDL_UpdateRect(screen,0,0,screen->w,screen->h);
#else
SDL_Flip(screen);
#endif
}
// returns 0 if tile isn't animated, else the number of frames
int gettileframecount(int tid) {
tiletype_t *tt;
tt = gettile(tid);
return tt->numframes;
}
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:
case P_FLOWERRED:
return B_TRUE;
}
return B_FALSE;
}
int isbullet(int id) {
if (id == P_SPIT) 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);
}
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;
}
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;
case '@': return P_FLOWERRED;
}
return -1;
}
char monstertochar(int id ) {
switch (id) {
case P_CLOUD: return 'c';
case P_RAT: return 'r';
case P_SNAKE: return 'S';
case P_BEE: return 'a';
case P_SPIDER: return 's';
case P_HELP: return '?';
case P_PLAYER: return '1';
case P_FLOWERRED: return '@';
}
return '\0';
}
tiletype_t *gettile(int tid) {
tiletype_t *t;
for (t = tiletype; t ; t = t->next) {
if (t->uniqid == tid) return t;
}
return &fakeblock;
}
void drawtile(SDL_Surface *where, int x, int y) {
SDL_Rect area;
tiletype_t *tt;
int frame;
int offset;
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[0], NULL, where, &area);
/* now draw real one */
offset = y*LEVELW+x;
tt = gettile(curlevel->map[offset]);
frame = curlevel->tileframe[offset];
if (tt->id != curlevel->bgtileid) {
SDL_BlitSurface(tt->img[frame], NULL, where, &area);
}
}
void initglobals(void) {
sprite = NULL;
level = NULL;
vidargs = 0;
/* timers */
gtime = 0;
timer = 0;
toggletimer = 0;
/* colours */
red.r = 255; red.g = 0; red.b = 0;
black.r = 0; black.g = 0; black.b = 0;
white.r = 255; white.g = 255; white.b = 255;
green.r = 0; green.g = 255; green.b = 0;
yellow.r = 255; yellow.g = 255; yellow.b = 0;
}
SDL_Surface *loadspriteimage(int spriteid, int frame, char *filename) {
imageset[spriteid].img[frame] = IMG_Load(filename);
if (imageset[spriteid].img[frame] == NULL) {
printf("Error loading image file: %s\n",filename);
exit(1);
}
return imageset[spriteid].img[frame];
}