2199 lines
46 KiB
C
2199 lines
46 KiB
C
#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 <SDL_mixer.h>
|
|
|
|
#include "shared.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;
|
|
int *animtile;
|
|
|
|
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[0] = IMG_Load("land.bmp");
|
|
fakeblock.numframes = 1;
|
|
fakeblock.next = NULL;
|
|
fakeblock.prev = NULL;
|
|
|
|
|
|
/* load fonts */
|
|
TTF_Init();
|
|
sprintf(filename, "verdana.ttf");
|
|
for (i = 1; i < MAXLETTERHEIGHT; i++) {
|
|
font[i] = TTF_OpenFont(filename,i);
|
|
if (!font[i]) {
|
|
printf("Error opening font: %s\n", TTF_GetError());
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/* calculate fps delay */
|
|
SDL_initFramerate(&manager);
|
|
SDL_setFramerate(&manager, WANTFPS);
|
|
|
|
|
|
if (loadlevel(curworld,curlevelnum)) {
|
|
return 1;
|
|
}
|
|
|
|
/* init sound */
|
|
if (initsound()) {
|
|
printf("sound error.\n");
|
|
return 1;
|
|
}
|
|
|
|
/* start music */
|
|
Mix_PlayMusic(music, -1);
|
|
|
|
|
|
drawlevel();
|
|
flip();
|
|
|
|
timer = 0;
|
|
|
|
player->invuln = INVULNTIME;
|
|
player->score = 0;
|
|
|
|
while (1) {
|
|
/*
|
|
removetext();
|
|
for (s = sprite ; s ; s = s->next) {
|
|
removesprite(s);
|
|
}
|
|
removenetting(player);
|
|
*/
|
|
removeall();
|
|
|
|
/* check for death & update movement status*/
|
|
for (s = sprite ; s ; s = nextsprite) {
|
|
s->moved = B_FALSE;
|
|
nextsprite = s->next;
|
|
if (s->dead == D_FINAL) {
|
|
if (s == player) {
|
|
/* TODO: lose a life */
|
|
/* if we have lives left, go back to start position */
|
|
setdefaults(s);
|
|
s->x = (curlevel->p1x * TILEW) + (TILEW/2);
|
|
s->y = (curlevel->p1y * TILEH) + (TILEH/2);
|
|
s->invuln = INVULNTIME;
|
|
} else {
|
|
killsprite(s);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* check for end of level */
|
|
if (levelcomplete == 1) {
|
|
addtext(318,242,32,"Level Complete!",&black,LEVELDELAY);
|
|
addtext(320,240,32,"Level Complete!",&yellow,LEVELDELAY);
|
|
levelcomplete = 2;
|
|
playfx(FX_WINLEVEL);
|
|
} else if (levelcomplete == 2) {
|
|
int mcount = 0;
|
|
sprite_t *s2;
|
|
|
|
/* when all monsters have become fruits */
|
|
for (s2 = sprite->next ; s2 ; s2 = s2->next) {
|
|
if (ismonster(s2->id)) {
|
|
if (s2->id != P_CLOUD) {
|
|
mcount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (mcount == 0) {
|
|
levelcompletetime = gtime;
|
|
levelcomplete = 3;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* check for keys */
|
|
SDL_PumpEvents();
|
|
keys = SDL_GetKeyState(NULL);
|
|
|
|
|
|
|
|
if (keys[SDLK_q]) {
|
|
gtime = curlevel->hurryuptime -1;
|
|
}
|
|
if (keys[SDLK_RETURN]) {
|
|
if (toggletimer == 0) {
|
|
SDL_WM_ToggleFullScreen(screen);
|
|
toggletimer = 50;
|
|
}
|
|
}
|
|
if (keys[SDLK_ESCAPE]) {
|
|
return 1;
|
|
}
|
|
|
|
if ((!player->dead) && (!player->teleporting)) {
|
|
if (keys[SDLK_RIGHT]) {
|
|
if (canmove(player)) {
|
|
movex(player, getspeed(player));
|
|
}
|
|
if (canturn(player)) {
|
|
player->dir = D_RIGHT;
|
|
}
|
|
}
|
|
if (keys[SDLK_LEFT]) {
|
|
if (canmove(player)) {
|
|
movex(player, -getspeed(player));
|
|
}
|
|
if (canturn(player)) {
|
|
player->dir = D_LEFT;
|
|
}
|
|
}
|
|
if (keys[SDLK_UP]) {
|
|
if (isonladder(player) || isladderabove(player)) {
|
|
player->y -= getspeed(player);
|
|
player->jumping = 0;
|
|
player->falling = 0;
|
|
player->climbing = B_TRUE;
|
|
}
|
|
}
|
|
if (keys[SDLK_DOWN]) {
|
|
if (isonladder(player)) {
|
|
player->y += getspeed(player);
|
|
player->jumping = 0;
|
|
player->falling = 0;
|
|
player->climbing = B_TRUE;
|
|
}
|
|
}
|
|
if (keys[SDLK_x]) {
|
|
if (isinwater(player)) {
|
|
player->jumping = B_FALSE;
|
|
player->falling = B_FALSE;
|
|
if (!isroofabove(player)) {
|
|
player->y -= (getspeed(player)*3);
|
|
}
|
|
} else {
|
|
if (!player->jumping) {
|
|
if (!player->falling) {
|
|
if (isonground(player) || isonladder(player)) {
|
|
/* dropping through a bridge */
|
|
if (keys[SDLK_DOWN]) {
|
|
if (isonbridge(player) && !player->falling) {
|
|
/* drop down */
|
|
player->dropping = B_TRUE;
|
|
player->dropx = player->x / TILEW;
|
|
player->dropy = player->y / TILEH;
|
|
}
|
|
} else {
|
|
int whichway;
|
|
player->climbing = B_FALSE;
|
|
if (keys[SDLK_RIGHT]) {
|
|
whichway = 1;
|
|
} else if (keys[SDLK_LEFT]) {
|
|
whichway = -1;
|
|
} else {
|
|
whichway = 0;
|
|
}
|
|
playfx(FX_JUMP);
|
|
jump(player, whichway);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (keys[SDLK_z]) {
|
|
if ((!player->netting) && (!player->slamming)) {
|
|
if (keys[SDLK_DOWN]) {
|
|
/* slam */
|
|
if ((!player->slamming) && (isonground(player))) {
|
|
playfx(FX_SLAM);
|
|
player->slamming = B_TRUE;
|
|
player->slamangle = 0;
|
|
player->netxstart = player->x - (player->img->w/2)*player->dir;
|
|
player->netystart = player->y;
|
|
}
|
|
} else {
|
|
if (player->netcaught < player->netmax) {
|
|
/* shoot net */
|
|
playfx(FX_SHOOT);
|
|
player->netting = 1;
|
|
if (player->netbig) {
|
|
player->netspeed = NETSPEED+3;
|
|
} else {
|
|
player->netspeed = NETSPEED;
|
|
}
|
|
player->netlen = 0;
|
|
player->netdir = player->dir;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// for each animated tile on the level...
|
|
for (animtile = curlevel->animtiles; animtile && *animtile != -1; animtile++) {
|
|
int offset,numframes;
|
|
tiletype_t *tt;
|
|
|
|
offset = *animtile;
|
|
|
|
tt = gettile(curlevel->map[offset]);
|
|
|
|
numframes = tt->numframes;
|
|
|
|
// is it time to change frames?
|
|
if ((timer % tt->animspeed) == 0) {
|
|
// change its frame
|
|
curlevel->tileframe[offset]++;
|
|
if (curlevel->tileframe[offset] >= numframes) {
|
|
curlevel->tileframe[offset] = 0;
|
|
}
|
|
// redraw it
|
|
drawtile(temps, offset%LEVELW,offset/LEVELW);
|
|
}
|
|
|
|
}
|
|
|
|
// move sprites
|
|
for (s = sprite; s ; s = s->next) {
|
|
movesprite(s);
|
|
}
|
|
movetext();
|
|
|
|
|
|
/* gravity */
|
|
for (s = sprite ; s ; s = s->next) {
|
|
dogravity(s);
|
|
}
|
|
|
|
/* tile effects */
|
|
for (s = sprite ; s ; s = s->next) {
|
|
dotileeffects(s);
|
|
}
|
|
|
|
/* check collisions */
|
|
//for (s = sprite ; s ; s = s->next) {
|
|
// checkcollide(s);
|
|
//}
|
|
checkcollide(player);
|
|
|
|
/* 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) && (!isfruit(s->id))) {
|
|
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;
|
|
|
|
/* reset player stats */
|
|
player->netting = B_FALSE;
|
|
player->slamming = B_FALSE;
|
|
player->jumping = B_FALSE;
|
|
}
|
|
|
|
void jump(sprite_t *s, int dir) {
|
|
if (s->jumping) return;
|
|
if (s->jumptimer) return;
|
|
|
|
if (isonground(s)) {
|
|
if (ismonster(s->id)) {
|
|
s->jumpdir = dir;
|
|
if (s->jumpdir != 0) {
|
|
s->dir = s->jumpdir;
|
|
}
|
|
s->jumptimer = 60;
|
|
} else {
|
|
s->jumpdir = dir;
|
|
if (s->jumpdir != 0) {
|
|
s->dir = s->jumpdir;
|
|
}
|
|
s->jumping = 1;
|
|
s->jumpspeed = 5;
|
|
}
|
|
}
|
|
}
|
|
|
|
void die(sprite_t *s) {
|
|
int mcount = 0;
|
|
sprite_t *s2;
|
|
/* clouds can't die like this */
|
|
if (s->id == P_CLOUD) return;
|
|
|
|
/* if this is the player, hurryup time counter resets */
|
|
// We already do this in the cloud movement routine, but
|
|
// this handles cases where the cloud hasn't appeared yet.
|
|
if (s == player) {
|
|
gtime = 0;
|
|
}
|
|
|
|
if (s == player) {
|
|
/* play sound */
|
|
playfx(FX_DIE);
|
|
}
|
|
|
|
/* release anything we've caught */
|
|
for (s2 = sprite->next ; s2 ; s2 = s2->next) {
|
|
if (s2->caughtby == s) {
|
|
s2->caughtby = NULL;
|
|
s2->angry = B_TRUE;
|
|
}
|
|
}
|
|
/* set death attribute */
|
|
s->dead = D_INITIAL;
|
|
s->netting = 0;
|
|
s->slamming = 0;
|
|
|
|
/* any monsters left? */
|
|
if (!levelcomplete) {
|
|
for (s2 = sprite->next ; s2 ; s2 = s2->next) {
|
|
if (ismonster(s2->id) && !s2->dead) {
|
|
if (s2->id != P_CLOUD) {
|
|
mcount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mcount == 0) {
|
|
levelcomplete = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void cleanup(void) {
|
|
int i;
|
|
Mix_HaltMusic();
|
|
Mix_CloseAudio();
|
|
for (i = 1; i < MAXLETTERHEIGHT; i++) {
|
|
TTF_CloseFont(font[i]);
|
|
}
|
|
TTF_Quit();
|
|
SDL_Quit();
|
|
}
|
|
|
|
void checkcollide(sprite_t *s) {
|
|
sprite_t *s2;
|
|
int collide;
|
|
int xdiff,ydiff;
|
|
|
|
for (s2 = sprite ; s2 ; s2 = s2->next) {
|
|
collide = B_TRUE;
|
|
if (s2 == s) collide = B_FALSE;
|
|
else if (s->dead) collide = B_FALSE;
|
|
else if (s2->dead) collide = B_FALSE;
|
|
else if (s->caughtby) collide = B_FALSE;
|
|
else if (s2->caughtby) collide = B_FALSE;
|
|
|
|
if (collide) {
|
|
/* check for colission with our net */
|
|
if ((s->netting) && (!s2->caughtby)) {
|
|
if (s->netcaught < s->netmax) {
|
|
if (ismonster(s2->id) && s2->id != P_CLOUD) {
|
|
xdiff = (s->x + s->netlen*s->netdir) - s2->x;
|
|
if (xdiff < 0) xdiff = -xdiff;
|
|
ydiff = s->netystart - (s2->y - s2->img->h/2);
|
|
if (ydiff < 0) ydiff = -ydiff;
|
|
|
|
if ((xdiff <= s2->img->w/2) && (ydiff <= s2->img->h)) {
|
|
s2->caughtby = s;
|
|
s2->jumping = 0;
|
|
s2->falling = 0;
|
|
s2->caughtstate = C_NETTING;
|
|
s->netcaught++;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* check for collision with us */
|
|
xdiff = s->x - s2->x;
|
|
if (xdiff < 0) xdiff = -xdiff;
|
|
ydiff = (s->y-(s->img->h/2)) - (s2->y-(s2->img->h/2));
|
|
if (ydiff < 0) ydiff = -ydiff;
|
|
|
|
if ((xdiff <= s->img->w/2 + s2->img->w/2) &&
|
|
(ydiff <= s->img->h/2 + s2->img->h/2)) {
|
|
/* COLLISION! */
|
|
if (isfruit(s2->id)) {
|
|
if (s == player) {
|
|
int gotscore = s2->score;
|
|
|
|
/* kill the fruit */
|
|
s2->dead = D_FINAL;
|
|
/* give points to the player */
|
|
player->score = player->score + gotscore;
|
|
/* handle fruit effects */
|
|
if (dofruiteffect(s2)) {
|
|
playfx(FX_POWERUP);
|
|
} else {
|
|
playfx(FX_FRUIT);
|
|
sprintf(tempm, "%d", gotscore);
|
|
addtext(s2->x,s2->y - s2->img->h/2, TEXTSIZE_POINTS, tempm, &white,POINTSDELAY);
|
|
}
|
|
}
|
|
}
|
|
if (ismonster(s2->id) || isbullet(s2->id)) {
|
|
if ((s == player) && (!s->invuln)) {
|
|
die(s);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void movesprite(sprite_t *s) {
|
|
int rv;
|
|
tiletype_t *tt;
|
|
|
|
/* timer */
|
|
if (s->doomcount) {
|
|
s->doomcount--;
|
|
if (s->doomcount == 0) {
|
|
s->dead = D_FINAL;
|
|
}
|
|
}
|
|
|
|
/* avoid edges of screen */
|
|
if (s->y < s->img->h) {
|
|
if (!s->flies) {
|
|
s->y = s->img->h;
|
|
}
|
|
}
|
|
if (s->x > (640 - s->img->w/2)) {
|
|
s->x = 640 - s->img->w/2;
|
|
}
|
|
if (s->x < (s->img->w/2)) {
|
|
s->x = s->img->w/2;
|
|
}
|
|
|
|
if (s->invuln) {
|
|
s->invuln--;
|
|
}
|
|
|
|
|
|
if (s->caughtby) {
|
|
if (s->caughtby->slamming) {
|
|
|
|
/* */
|
|
|
|
s->x = s->caughtby->netxstart;
|
|
s->y = s->caughtby->netystart;
|
|
} else {
|
|
/* stay at position of net */
|
|
s->y = s->caughtby->y;
|
|
if (s->caughtstate == C_NETTING) {
|
|
s->x = s->caughtby->x + (s->caughtby->netlen*s->caughtby->netdir);
|
|
} else {
|
|
s->x = s->caughtby->x + (s->caughtby->img->w/2) * -(s->caughtby->dir);
|
|
}
|
|
}
|
|
return;
|
|
} else if (s->dead == D_INITIAL) { /* just set to dead */
|
|
//s->xs = ((rand() % 7)) - 3;
|
|
// TODO: avoid straight up, also make this able
|
|
// to be a float
|
|
s->xs = ((rand() % 14) / 2) - 3;
|
|
s->ys = ((rand() % 3) + 3) * -1;
|
|
s->dead = D_BOUNCING;
|
|
s->bounces = 0;
|
|
if (s == player) {
|
|
s->jumpspeed = 8;
|
|
s->jumping = 1;
|
|
}
|
|
return;
|
|
} else if (s->dead == D_BOUNCING) { /* dying */
|
|
if (s == player) {
|
|
/* shoot up in the air, then fall */
|
|
s->y -= s->jumpspeed;
|
|
|
|
s->jumping++;
|
|
if (s->jumping % 5 == 0) {
|
|
s->jumpspeed--;
|
|
}
|
|
|
|
/* if we've fallen off the bottom... */
|
|
if (s->y >= 480) {
|
|
/* pause before respawning */
|
|
s->jumpspeed = 0; /* this is now a timer */
|
|
s->dead = D_LASTBOUNCE;
|
|
}
|
|
} else {
|
|
/* bounch around the screen 3 times */
|
|
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 = D_LASTBOUNCE;
|
|
}
|
|
}
|
|
return;
|
|
} else if (s->dead == D_LASTBOUNCE) { /* final fall */
|
|
if (s == player) {
|
|
/* just delay... */
|
|
s->jumpspeed++;
|
|
if (s->jumpspeed == 50) {
|
|
/* really die */
|
|
s->dead = D_FINAL;
|
|
}
|
|
} else { /* bounce around, stop when we hit the ground */
|
|
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 = D_FINAL;
|
|
/* 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 == TP_SHRINKING) {
|
|
ts = rotozoomSurfaceXY(s->img,0, 0.9 , 0.9 ,0);
|
|
s->img = ts;
|
|
} else {
|
|
ts = rotozoomSurfaceXY(s->img,0, 0.9 , 0.9 ,0);
|
|
SDL_FreeSurface(s->img);
|
|
s->img = ts;
|
|
}
|
|
|
|
if ((s->img->w <= 2) || (s->img->h <= 2)) {
|
|
/* go to tele dest */
|
|
int x,y;
|
|
/* find destination */
|
|
for (y = 0; y < LEVELH; y++) {
|
|
for (x = 0; x < LEVELW; x++) {
|
|
tt = gettile(curlevel->map[y*LEVELW+x]);
|
|
if (tt->id == T_TELEPORTDEST) {
|
|
/* teleport there */
|
|
s->x = (x * TILEW) + (TILEW/2);
|
|
s->y = (y * TILEH) + TILEH-2;
|
|
}
|
|
}
|
|
}
|
|
s->teleporting = -1;
|
|
} else s->teleporting++;
|
|
}
|
|
} else if (s->teleporting < 0) {
|
|
double size;
|
|
if (timer % 2 == 0) {
|
|
/* grow */
|
|
size = (double)-s->teleporting / 10;
|
|
|
|
SDL_FreeSurface(s->img);
|
|
if (size >= 1) {
|
|
s->teleporting = 0;
|
|
s->img = imageset[s->id].img[F_WALK1];
|
|
} else {
|
|
s->img = rotozoomSurfaceXY(imageset[s->id].img[F_WALK1],0,size,size,0);
|
|
s->teleporting--;
|
|
}
|
|
}
|
|
} else if (s->jumping) {
|
|
movex(s, s->jumpdir*getspeed(s));
|
|
return;
|
|
}
|
|
|
|
if (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 == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) {
|
|
jump(s,D_RIGHT);
|
|
} else if ((s->dir == D_LEFT) && (xdiff < 0) && (xdiff >= -(TILEW*7))) {
|
|
jump(s,D_LEFT);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
move = B_TRUE;
|
|
}
|
|
|
|
/* either move or turn around */
|
|
if (move) {
|
|
rv = movex(s, s->dir*getspeed(s));
|
|
if (rv) {
|
|
/* if we couldn't move (hit a wall), turn */
|
|
s->dir = -s->dir;
|
|
}
|
|
} else {
|
|
s->dir = -s->dir;
|
|
}
|
|
|
|
if (s->angry) {
|
|
if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) {
|
|
/* if player is above us, jump */
|
|
if (player->y < s->y) {
|
|
if ((xdiff >= (TILEW*2)) && (xdiff <= (TILEW*3))) {
|
|
/* jump right */
|
|
jump(s, 1);
|
|
} else if ((xdiff <= -(TILEW*2)) && (xdiff >= -(TILEW*3))) {
|
|
/* jump left */
|
|
jump(s, -1);
|
|
} else if (s->y - player->y <= (TILEH*6)) {
|
|
if ((xdiff >= 0) && (xdiff < (TILEW*2))) {
|
|
/* jump up */
|
|
jump(s, 0);
|
|
} else if ((xdiff <= 0) && (xdiff > -(TILEW*2))) {
|
|
/* jump up */
|
|
jump(s, 0);
|
|
}
|
|
} else {
|
|
/* jump whichever way we're facing */
|
|
/*
|
|
s->jumpdir = s->dir;
|
|
s->jumping = 1;
|
|
s->jumpspeed = 5;
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (s->id == P_COKE) {
|
|
|
|
if (!s->falling) {
|
|
int move = B_FALSE;
|
|
int xdiff, absxdiff;
|
|
|
|
|
|
/* distance to player */
|
|
xdiff = player->x - s->x;
|
|
if (xdiff < 0) absxdiff = -xdiff;
|
|
else absxdiff = xdiff;
|
|
|
|
tt = gettileat(s->x + s->dir+getspeed(s),s->y,NULL,NULL);
|
|
/* if there's a hole in front of us */
|
|
if (tt->solid == S_NOTSOLID) {
|
|
if (player->y > s->y ) {
|
|
/* if player is below, fall off */
|
|
if (xdiff <= (TILEW*12)) {
|
|
move = B_TRUE;
|
|
}
|
|
} else if (player->y == s->y) {
|
|
/* if player is at same level and close, jump */
|
|
if ((s->dir == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) {
|
|
jump(s,D_RIGHT);
|
|
} else if ((s->dir == D_LEFT) && (xdiff < 0) && (xdiff >= -(TILEW*7))) {
|
|
jump(s,D_LEFT);
|
|
}
|
|
}
|
|
} else {
|
|
move = B_TRUE;
|
|
}
|
|
|
|
/* either move or turn around */
|
|
if (move) {
|
|
rv = movex(s, s->dir*getspeed(s));
|
|
if (rv) {
|
|
/* if we couldn't move (hit a wall), turn */
|
|
s->dir = -s->dir;
|
|
}
|
|
} else {
|
|
s->dir = -s->dir;
|
|
}
|
|
|
|
|
|
|
|
/* moves like an angry rat all the time */
|
|
if ((player->dead == 0) && (!s->jumping) && (!s->jumptimer)) {
|
|
/* if player is above us, jump */
|
|
if (player->y < s->y) {
|
|
if ((xdiff >= (TILEW*2)) && (xdiff <= (TILEW*3))) {
|
|
/* jump right */
|
|
jump(s, D_RIGHT);
|
|
} else if ((xdiff <= -(TILEW*2)) && (xdiff >= -(TILEW*3))) {
|
|
/* jump left */
|
|
jump(s, D_LEFT);
|
|
} 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 == D_RIGHT) && (xdiff > 0) && (xdiff <= (TILEW*7))) {
|
|
jump(s,D_RIGHT);
|
|
} else if ((s->dir == D_LEFT) && (xdiff < 0) && (xdiff >= -(TILEW*7))) {
|
|
jump(s,D_LEFT);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
move = B_TRUE;
|
|
}
|
|
|
|
/* shoot */
|
|
ydiff = player->y - s->y;
|
|
if (ydiff < 0) ydiff =-ydiff;
|
|
|
|
if (ydiff <= (TILEH*4)) {
|
|
sprite_t *ss;
|
|
int shoot = B_FALSE;
|
|
if (s->bullet == NULL) {
|
|
if ( (player->x < s->x) && (s->dir == D_LEFT) ) {
|
|
shoot = B_TRUE;
|
|
} else if ( (player->x > s->x) && (s->dir == D_RIGHT) ) {
|
|
shoot = B_TRUE;
|
|
}
|
|
}
|
|
if (shoot) {
|
|
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 = D_FINAL;
|
|
}
|
|
} else if (s->id == P_CLOUD) {
|
|
if ((player->dead) || (levelcomplete)) {
|
|
if ((s->img->h <= 3) || (s->img->w <= 3)) {
|
|
s->dead = D_FINAL;
|
|
/* reset hurryup timer */
|
|
gtime = 0;
|
|
} else {
|
|
SDL_Surface *ts;
|
|
/* get smaller */
|
|
ts = rotozoomSurfaceXY(s->img,0, 0.9 , 0.9 ,0);
|
|
SDL_FreeSurface(s->img);
|
|
s->img = ts;
|
|
s->y--;
|
|
}
|
|
} else {
|
|
if ((s->xs == -99) || (s->ys == -99)) {
|
|
s->ys = 0.5;
|
|
s->xs = 1;
|
|
}
|
|
|
|
s->x += s->xs;
|
|
s->y += s->ys;
|
|
|
|
if (s->x >= (640 - s->img->w/2 - 5)) {
|
|
s->xs = -s->xs;
|
|
s->x = 640 - s->img->w/2 - 6;
|
|
}
|
|
if (s->x <= (s->img->w/2 + 5)) {
|
|
s->xs = -s->xs;
|
|
s->x = s->img->w/2 + 6;
|
|
}
|
|
if (s->y >= (480 - s->img->h/2 - 5)) {
|
|
s->ys = -s->ys;
|
|
s->y = 480 - s->img->h/2 - 6;
|
|
}
|
|
if (s->y <= (s->img->h/2 + 5)) {
|
|
s->ys = -s->ys;
|
|
s->y = s->img->h/2 + 6;
|
|
}
|
|
|
|
|
|
if (timer % 50 == 0) {
|
|
int w,h;
|
|
SDL_Surface *ts;
|
|
/* get bigger */
|
|
w = s->img->w;
|
|
h = s->img->h;
|
|
ts = rotozoomSurfaceXY(s->img,0, 1.1 , 1.1 ,0);
|
|
SDL_FreeSurface(s->img);
|
|
s->img = ts;
|
|
|
|
s->y += 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void dotileeffects(sprite_t *s) {
|
|
tiletype_t *tt;
|
|
int finished = B_FALSE;
|
|
int state = 0;
|
|
|
|
if (s->jumping || s->dead || s->caughtby) {
|
|
return;
|
|
}
|
|
|
|
/* check where we are */
|
|
tt = gettileat(s->x,s->y-2,NULL,NULL);
|
|
if ((tt->id == T_TELEPORT) || (tt->id == T_TELEPORT2)) {
|
|
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 drawlevel(void) {
|
|
int x,y;
|
|
SDL_Rect area;
|
|
int speed = 16;
|
|
|
|
if (temps) {
|
|
SDL_FreeSurface(temps);
|
|
temps = NULL;
|
|
}
|
|
temps = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
|
640, 480,
|
|
screen->format->BitsPerPixel, screen->format->Rmask,
|
|
screen->format->Gmask,screen->format->Bmask,
|
|
screen->format->Amask);
|
|
|
|
for (x = 0; x < LEVELW; x++) {
|
|
for (y = 0; y < LEVELH; y++) {
|
|
drawtile(temps,x,y);
|
|
}
|
|
}
|
|
|
|
|
|
for (x = 0; x < 640; x += speed) {
|
|
area.x = 0;
|
|
area.y = 0;
|
|
if (x > 639) {
|
|
area.w = 639;
|
|
} else area.w = x;
|
|
area.h = 480;
|
|
SDL_BlitSurface(temps, &area, screen, &area);
|
|
SDL_UpdateRect(screen, area.x, area.y, area.w, area.h);
|
|
}
|
|
}
|
|
|
|
|
|
double getspeed(sprite_t *s ) {
|
|
int id = s->id;
|
|
double speed = 1;
|
|
|
|
if (id == P_PLAYER) {
|
|
speed = s->speed;
|
|
} else if (id == P_RAT) {
|
|
if (s->angry) speed = 1.5;
|
|
else speed = 1;
|
|
} else if (id == P_SNAKE) {
|
|
if (s->angry) speed = 1.5;
|
|
else speed = 1;
|
|
} else if (id == P_BEE) {
|
|
if (s->angry) speed = 2;
|
|
else speed = 1;
|
|
} else if (id == P_SPIDER) {
|
|
if (s->angry) speed = 1.5;
|
|
else speed = 2;
|
|
} else if (id == P_CHEESE) {
|
|
speed = 0;
|
|
}
|
|
|
|
if (isinwater(s)) speed /= 2;
|
|
|
|
return speed;
|
|
}
|
|
|
|
|
|
int addtext(int x, int y, int size, char *string, SDL_Color *c, int delay) {
|
|
text_t *t;
|
|
|
|
if (text == NULL) {
|
|
text = malloc(sizeof(text_t));
|
|
t = text;
|
|
t->prev = NULL;
|
|
} else {
|
|
t = lasttext;
|
|
t->next = malloc(sizeof(text_t));
|
|
t->next->prev = t;
|
|
|
|
t = t->next;
|
|
}
|
|
|
|
t->bg = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
|
300, 110,
|
|
screen->format->BitsPerPixel, screen->format->Rmask,
|
|
screen->format->Gmask,screen->format->Bmask,
|
|
screen->format->Amask);
|
|
|
|
t->c = c;
|
|
t->x = x;
|
|
t->y = y;
|
|
t->maxsize = size;
|
|
t->size = 3;
|
|
strcpy(t->txt, string);
|
|
t->state = 0;
|
|
t->delay = delay;
|
|
|
|
t->img = TTF_RenderText_Solid(font[t->size], t->txt, *t->c);
|
|
|
|
|
|
t->next = NULL;
|
|
lasttext = t;
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
/* copy background buffer (ie. tiles) to screen, erasing sprites */
|
|
void removeall(void) {
|
|
SDL_BlitSurface(temps, NULL, screen, NULL);
|
|
}
|
|
|
|
void removetext(void) {
|
|
SDL_Rect sarea;
|
|
text_t *t;
|
|
|
|
for (t = text ; t ; t = t->next) {
|
|
sarea.x = 0;
|
|
sarea.y = 0;
|
|
sarea.w = t->bgarea.w;
|
|
sarea.h = t->bgarea.h;
|
|
|
|
SDL_BlitSurface(t->bg, &sarea, screen, &t->bgarea);
|
|
}
|
|
}
|
|
|
|
void movetext(void) {
|
|
text_t *t,*nextt;
|
|
for (t = text ; t ; t = nextt) {
|
|
nextt = t->next;
|
|
if (t->state == 0) {
|
|
t->size += TEXTSPEED;
|
|
if (t->size >= t->maxsize) {
|
|
t->state = 1;
|
|
}
|
|
} else if (t->state == t->delay) {
|
|
t->size -= TEXTSPEED;
|
|
if (t->size <= 3) {
|
|
killtext(t);
|
|
}
|
|
|
|
} else {
|
|
t->state++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawscore(void) {
|
|
SDL_Surface *score;
|
|
SDL_Rect area;
|
|
|
|
sprintf(tempm, "%d",player->score);
|
|
|
|
/* shadow */
|
|
score = TTF_RenderText_Solid(font[14], tempm, black);
|
|
area.x = 18;
|
|
area.y = 7;
|
|
area.w = 0;
|
|
area.h = 0;
|
|
SDL_BlitSurface(score, NULL, screen, &area);
|
|
SDL_FreeSurface(score);
|
|
/* score */
|
|
score = TTF_RenderText_Solid(font[14], tempm, green);
|
|
area.x = 20;
|
|
area.y = 5;
|
|
area.w = 0;
|
|
area.h = 0;
|
|
SDL_BlitSurface(score, NULL, screen, &area);
|
|
SDL_FreeSurface(score);
|
|
}
|
|
|
|
void drawtext(void) {
|
|
text_t *t;
|
|
SDL_Rect area;
|
|
|
|
for (t = text ; t ; t = t->next) {
|
|
|
|
/* create text */
|
|
if (t->img) {
|
|
SDL_FreeSurface(t->img);
|
|
t->img = NULL;
|
|
}
|
|
t->img = TTF_RenderText_Solid(font[t->size], t->txt, *t->c);
|
|
|
|
/* get bg */
|
|
t->bgarea.x = t->x - t->img->w/2;
|
|
t->bgarea.y = t->y - t->img->h/2;
|
|
t->bgarea.w = t->img->w;
|
|
t->bgarea.h = t->img->h;
|
|
SDL_BlitSurface(screen, &t->bgarea, t->bg, NULL);
|
|
|
|
/* draw text */
|
|
area.x = t->x - t->img->w/2;
|
|
area.y = t->y - t->img->h/2;
|
|
area.w = t->img->w;
|
|
area.h = t->img->h;
|
|
SDL_BlitSurface(t->img,NULL, screen, &area);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void killtext(text_t *t) {
|
|
text_t *nextone, *lastone;
|
|
|
|
|
|
if (t->bg) {
|
|
SDL_FreeSurface(t->bg);
|
|
t->bg = NULL;
|
|
}
|
|
if (t->img) {
|
|
SDL_FreeSurface(t->img);
|
|
t->img = NULL;
|
|
}
|
|
|
|
nextone = t->next;
|
|
if (nextone != NULL) {
|
|
nextone->prev = t->prev;
|
|
} else { /*last text */
|
|
lasttext = t->prev;
|
|
}
|
|
|
|
if (t->prev == NULL) {
|
|
/* first text */
|
|
nextone = text->next;
|
|
free(text);
|
|
text = nextone;
|
|
} else {
|
|
lastone = t->prev;
|
|
free (lastone->next );
|
|
lastone->next = nextone;
|
|
}
|
|
}
|
|
|
|
|
|
void drawnetting(sprite_t *s) {
|
|
int sx;
|
|
SDL_Rect area;
|
|
|
|
if (s->netting) {
|
|
int y,yy;
|
|
int dis;
|
|
int netsleft;
|
|
|
|
sx = s->x;
|
|
s->nety = s->y - (s->img->h/2) + 2;
|
|
|
|
s->netxstart = s->x;
|
|
s->netystart = s->nety - 3;
|
|
|
|
if (s->netdir == 1) {
|
|
area.x = s->netxstart + TILEW/2;
|
|
} else {
|
|
area.x = s->netxstart - TILEW/2 - s->netlen;
|
|
}
|
|
//area.y = s->netystart;
|
|
area.y = s->y - s->img->h-2 + 2;
|
|
area.w = s->netlen;
|
|
area.h = s->img->h+2;
|
|
SDL_BlitSurface(screen, &area,s->netbg, NULL);
|
|
|
|
netsleft = s->netmax - s->netcaught;
|
|
if (netsleft < 1) netsleft = 1;
|
|
dis = (int)s->img->h / (int)(netsleft+1) + 1;
|
|
|
|
|
|
for (y = dis; y < s->img->h; y += dis) {
|
|
yy = s->y - s->img->h;
|
|
yy += y;
|
|
drawline16(screen,sx,s->nety,s->x + s->netdir*s->netlen,yy,white);
|
|
}
|
|
|
|
//drawline16(screen,sx,s->nety,s->x + s->netdir*s->netlen,s->nety-3,white);
|
|
//drawline16(screen,sx,s->nety,s->x + s->netdir*s->netlen,s->nety,white);
|
|
//drawline16(screen,sx,s->nety,s->x + s->netdir*s->netlen,s->nety+3,white);
|
|
} else if (s->slamming) {
|
|
double dist;
|
|
int x,y;
|
|
dist = (s->slamangle * (180/M_PI))/2;
|
|
|
|
s->netxstart = s->x + cos(s->slamangle-(180*(M_PI/180)))*dist*s->dir;
|
|
s->netystart = s->y + sin(s->slamangle-(180*(M_PI/180)))*dist;
|
|
|
|
/* middle line */
|
|
drawline16(screen,s->x,s->y - s->img->h/2,
|
|
s->netxstart,s->netystart,white);
|
|
/* left line */
|
|
x = s->x + cos(s->slamangle-(5*(M_PI/180))-(180*(M_PI/180)))*dist*s->dir;
|
|
y = s->y + sin(s->slamangle-(5*(M_PI/180))-(180*(M_PI/180)))*dist;
|
|
drawline16(screen,s->x,s->y - s->img->h/2,x, y, white);
|
|
/* right line */
|
|
x = s->x + cos(s->slamangle+(5*(M_PI/180))-(180*(M_PI/180)))*dist*s->dir;
|
|
y = s->y + sin(s->slamangle+(5*(M_PI/180))-(180*(M_PI/180)))*dist;
|
|
drawline16(screen,s->x,s->y - s->img->h/2,x, y, white);
|
|
}
|
|
|
|
}
|
|
|
|
void removenetting(sprite_t *s) {
|
|
SDL_Rect area,sarea;
|
|
|
|
if (s->netting) {
|
|
sarea.x = 0;
|
|
sarea.y = 0;
|
|
sarea.w = s->netlen;
|
|
sarea.h = s->img->h+2;
|
|
|
|
if (s->netdir == 1) {
|
|
area.x = s->netxstart + TILEW/2;
|
|
} else {
|
|
area.x = s->netxstart - TILEW/2 - s->netlen;
|
|
}
|
|
//area.y = s->netystart;
|
|
area.y = s->y - s->img->h-2;
|
|
area.w = s->netlen;
|
|
area.h = s->img->h+2;
|
|
|
|
if (s->netbg != NULL) {
|
|
SDL_BlitSurface(s->netbg, &sarea, screen, &area);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void removesprite(sprite_t *s) {
|
|
int startx,starty,endx,endy;
|
|
int x,y;
|
|
|
|
|
|
/* find topleft-most tile */
|
|
gettileat(s->x - s->img->w, s->y - s->img->h,&startx,&starty);
|
|
/* find bottomright-most tile */
|
|
gettileat(s->x + s->img->w, s->y + s->img->h,&endx,&endy);
|
|
|
|
if (s->slamming) {
|
|
if (s->dir == D_LEFT) {
|
|
startx -= 5;
|
|
endx += 1;
|
|
} else {
|
|
startx -= 1;
|
|
endx += 5;
|
|
}
|
|
starty -= 2;
|
|
endy += 1;
|
|
}
|
|
|
|
/* draw the tiles */
|
|
for (y = starty; y <= endy; y++) {
|
|
for (x = startx; x <= endx; x++) {
|
|
drawtile(screen,x,y);
|
|
}
|
|
}
|
|
}
|
|
|
|
int isonbridge(sprite_t *s) {
|
|
tiletype_t *tthere;
|
|
tthere = gettileat(s->x,s->y, NULL,NULL);
|
|
if (tthere->id == T_BRIDGE) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
int isonladder(sprite_t *s) {
|
|
tiletype_t *tthere;
|
|
tthere = gettileat(s->x,s->y, NULL,NULL);
|
|
if ((tthere->id == T_LADDER) || (tthere->id == T_LADDERTOP)) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isladderabove(sprite_t *s) {
|
|
tiletype_t *tthere;
|
|
tthere = gettileat(s->x,s->y-TILEH, NULL,NULL);
|
|
if (tthere->id == T_LADDER) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isinwater(sprite_t *s) {
|
|
tiletype_t *tt;
|
|
tt = gettileat(s->x, s->y - s->img->h/2, NULL, NULL);
|
|
if (tt->water) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isroofabove(sprite_t *s) {
|
|
tiletype_t *tt;
|
|
|
|
/* get tile above sprite's head */
|
|
tt = gettileat(s->x, s->y - s->img->h,NULL,NULL);
|
|
if (tt->solid) return B_TRUE;
|
|
tt = gettileat(s->x + s->img->w/2, s->y - s->img->h,NULL,NULL);
|
|
if (tt->solid) return B_TRUE;
|
|
tt = gettileat(s->x - s->img->w/2, s->y - s->img->h,NULL,NULL);
|
|
if (tt->solid) return B_TRUE;
|
|
|
|
return B_FALSE;
|
|
}
|
|
/* is there a roof n tiles above us. If howfar is 1, this is the same
|
|
as the regular isroofabove() */
|
|
int isroofnabove(sprite_t *s, int howfar) {
|
|
tiletype_t *tt;
|
|
int ypos;
|
|
|
|
ypos = s->y - s->img->h - TILEH*(howfar-1);
|
|
|
|
/* get tile above sprite's head */
|
|
tt = gettileat(s->x, ypos,NULL,NULL);
|
|
if (tt->solid) return B_TRUE;
|
|
tt = gettileat(s->x + s->img->w/2, 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 && !s->dropping) {
|
|
if (isongroundpoint(s, s->x + s->img->w/2, s->y)) {
|
|
return B_TRUE;
|
|
}
|
|
if (isongroundpoint(s, s->x - s->img->w/2, s->y)) {
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isongroundpoint(sprite_t *s, int x,int y) {
|
|
tiletype_t *tt;
|
|
int tilex,tiley;
|
|
int xoff;
|
|
int groundy;
|
|
|
|
tt = gettileat(x,y, &tilex, &tiley);
|
|
|
|
|
|
// when dropping, the tile you dropped from doesn't count
|
|
// as "ground".
|
|
if (s->dropping && (tilex == s->dropx) && (tiley == s->dropy)) {
|
|
return B_FALSE;
|
|
}
|
|
|
|
/* get offset */
|
|
xoff = x - (tilex*TILEW);
|
|
|
|
/* if it's not solid... */
|
|
if (tt->solid == 0) {
|
|
return B_FALSE;
|
|
} else {
|
|
/* check height of tile at that position */
|
|
groundy = tiley*TILEH + tt->lowness[xoff];
|
|
|
|
/* above ground level */
|
|
if (y < groundy) {
|
|
return B_FALSE;
|
|
} else if (y > groundy + 3) {
|
|
/* below ground level */
|
|
if (s->jumping) {
|
|
return B_FALSE;
|
|
}
|
|
} else if (s->falling) {
|
|
tiletype_t *abovetile;
|
|
/* falling, on a tile, but with tiles above you */
|
|
// ie. you've jumped up through a single tile (can't
|
|
// jump through two or more tiles
|
|
abovetile = gettileat(x,y-TILEH, NULL, NULL);
|
|
if (abovetile->solid) {
|
|
return B_FALSE;
|
|
}
|
|
// } else if (s->dropping) {
|
|
// tiletype_t *abovetile;
|
|
/* if the tile we're on is solid but not the one
|
|
above, then we've "dropped" and are still
|
|
travelling through the tile we dropped from. */
|
|
// abovetile = gettileat(x,y-TILEH, NULL, NULL);
|
|
// if (!abovetile->solid) {
|
|
// return B_FALSE;
|
|
// }
|
|
}
|
|
|
|
}
|
|
|
|
return B_TRUE;
|
|
}
|
|
|
|
void dogravity(sprite_t *s) {
|
|
sprite_t *s2;
|
|
|
|
if (s->dead) return;
|
|
if (s->flies) return;
|
|
|
|
if (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 == C_NETTING)) {
|
|
s2->caughtstate = C_NETTED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (s->slamming) {
|
|
s->slamangle += (10 * (M_PI/180));
|
|
if (s->slamangle >= (180 * (M_PI/180))) {
|
|
/* finished slamming */
|
|
int xdiff,ydiff,xnet = 0,ynet = 0;
|
|
int pointsinc = 250;
|
|
int psize = 6;
|
|
int gotsomething = B_FALSE;
|
|
|
|
s->slamming = 0;
|
|
|
|
/* reset fruit type counter */
|
|
curfruittype = 0;
|
|
|
|
/* kill anything we've caught */
|
|
for (s2 = sprite; s2 ; s2 = s2->next) {
|
|
/* kill anything we have caught */
|
|
if (s2->caughtby == s) {
|
|
tiletype_t *tt;
|
|
tt = gettileat(s2->x,s2->y+2,NULL,NULL);
|
|
/* if on ground, monster dies */
|
|
if ((tt == NULL) || (tt->solid)) {
|
|
/* will become a fruit when it finishes dying */
|
|
s2->willbecome = fruittypes[curfruittype];
|
|
/* increment fruit type */
|
|
if (fruittypes[++curfruittype] == -1) {
|
|
curfruittype = 0;
|
|
}
|
|
die(s2);
|
|
pointsinc *= 2;
|
|
psize += 10;
|
|
xnet = s2->x;
|
|
ynet = s2->y - s2->img->h/2;
|
|
|
|
gotsomething = B_TRUE;
|
|
} else {
|
|
/* otherwise it gets angry */
|
|
s2->angry = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (gotsomething) {
|
|
playfx(FX_KILL);
|
|
}
|
|
|
|
gotsomething = B_FALSE;
|
|
|
|
/* 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;
|
|
|
|
gotsomething = B_TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
if (gotsomething) {
|
|
playfx(FX_MULTIKILL);
|
|
}
|
|
|
|
/* release anything we've caught */
|
|
for (s2 = sprite; s2 ; s2 = s2->next) {
|
|
if (s2->caughtby == s) {
|
|
/* release it */
|
|
s2->caughtby = NULL;
|
|
}
|
|
}
|
|
|
|
s->netcaught = 0;
|
|
|
|
/* show points */
|
|
if (psize >= MAXLETTERHEIGHT) {
|
|
psize = MAXLETTERHEIGHT-1;
|
|
}
|
|
if (pointsinc > 250) {
|
|
sprintf(tempm, "%d",pointsinc);
|
|
addtext(xnet,ynet-TILEH, psize, tempm, &white,POINTSDELAY);
|
|
/* give points to player */
|
|
s->score += pointsinc;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int movex(sprite_t *s,double amt) {
|
|
double newx,newy;
|
|
double curx,cury;
|
|
int tilex,tiley;
|
|
tiletype_t *tt,*tt2;
|
|
int newxoff,newgroundy;
|
|
int newtilex,newtiley;
|
|
|
|
double amtdir;
|
|
|
|
tt = gettileat(s->x, s->y, &tilex,&tiley);
|
|
|
|
|
|
if (amt > 0) amtdir = 1;
|
|
else (amtdir = -1);
|
|
|
|
|
|
curx = s->x;
|
|
cury = s->y;
|
|
|
|
/* check for blockage in front of us */
|
|
//newx = s->x + (amtdir*(s->img->w/2));
|
|
newx = s->x + (amtdir*TILEW/2);
|
|
newy = cury-TILEH;
|
|
tt2 = gettileat(newx,newy,&newtilex,&newtiley);
|
|
if (tt2->solid == S_SOLID) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
/* 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 ismonster(int id) {
|
|
if (id == P_RAT) return B_TRUE;
|
|
if (id == P_BEE) return B_TRUE;
|
|
if (id == P_SPIDER) return B_TRUE;
|
|
if (id == P_SNAKE) return B_TRUE;
|
|
if (id == P_CLOUD) return B_TRUE;
|
|
if (id == P_COKE) return B_TRUE;
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
void usage(void) {
|
|
printf("usage: rc [-fs] [-l xx]\n");
|
|
printf(" -fs Start in full-screen mode.\n");
|
|
printf(" -l xx Skip to level xx.\n");
|
|
printf("\n");
|
|
}
|
|
|
|
// returns B_TRUE if the given player is able to walk/fall left/right
|
|
int canmove(sprite_t *pl) {
|
|
if (!pl->jumping && !pl->slamming ) {
|
|
if (!pl->netting) {
|
|
if (!isonladder(pl) || pl->falling || isonground(pl)) {
|
|
return B_TRUE;
|
|
}
|
|
} else if (pl->netting && pl->falling) { // netting and falling
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
// returns B_TRUE if the given player is able to change which direction they're facing
|
|
int canturn(sprite_t *pl) {
|
|
if (!pl->slamming && !pl->netting) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int loadfx(int sid , char *filename) {
|
|
char tempname[BUFLEN];
|
|
|
|
sprintf(tempname, "sounds/");
|
|
strncat(tempname, filename, BUFLEN);
|
|
sfx[sid] = Mix_LoadWAV(tempname);
|
|
if (!sfx[sid]) {
|
|
printf("error loading %s\n",tempname);
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int initsound(void) {
|
|
int i;
|
|
|
|
/* init */
|
|
if (Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 1024) < 0) {
|
|
printf("Error initialising sound: %s.\n",Mix_GetError());
|
|
return B_TRUE;
|
|
}
|
|
|
|
loadfx(FX_SHOOT, "shoot.wav");
|
|
loadfx(FX_SLAM, "slam.wav");
|
|
loadfx(FX_KILL, "kill.wav");
|
|
loadfx(FX_MULTIKILL, "multikill.wav");
|
|
loadfx(FX_JUMP, "jump.wav");
|
|
loadfx(FX_FRUIT, "fruit.wav");
|
|
loadfx(FX_POWERUP, "powerup.wav");
|
|
loadfx(FX_DIE, "die.wav");
|
|
loadfx(FX_WINLEVEL, "winlevel.wav");
|
|
|
|
|
|
// load sound effects
|
|
for (i = 0; i < MAXFX; i++) {
|
|
if (!sfx[i]) {
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
|
|
// load music
|
|
music = Mix_LoadMUS("music/main.mod");
|
|
if (!music) {
|
|
printf("can't load music\n");
|
|
return B_TRUE;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
void playfx(int num) {
|
|
Mix_PlayChannel(-1, sfx[num], 0);
|
|
}
|