- More work on King Ant

- Added "Bigfirewall" (which melts ice bridges)
This commit is contained in:
Rob Pearce 2009-03-05 01:53:20 +00:00
parent 6175ce4859
commit 859e8c10a5
7 changed files with 336 additions and 17 deletions

View File

@ -1,4 +1,4 @@
bgfile snow2.png
bgfile fire1.png
bg 0
hurryup 30
help
@ -7,9 +7,6 @@ monsters
0 2 16
134 37 16
163 7 28
163 7 28
163 7 28
163 7 28
endmonsters
exitdir 1
91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,91,

BIN
data/sprites/bigfire1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
data/sprites/bigfire2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

27
defs.h
View File

@ -1,3 +1,4 @@
#define KAS_WAITFORTOP 2
#ifndef __DEFS_H
#define __DEFS_H
@ -22,6 +23,12 @@
#define CH_LASTCHANNEL 21
#define CH_HURRYUP 20
// max number of regrowing tiles
#define MAXREGROW 200
// time a tile takes to regrow
#define REGROWTIMER_SHORT 200
#define REGROWTIMER_LONG 400
#define MAXCREDITS 5
@ -270,9 +277,17 @@
#define KFS_VERT 8
// king ant
#define KA_WALKTIME 200
#define KA_WALKTIME 400
#define KA_SHOOTTIME 100
// king ant stats
#define KAS_WALK1 0
#define KAS_JUMP1 1
#define KAS_WAITFORTOP1 2
#define KAS_WAITFORTOP2 3
#define KAS_FALL1 4
#define KAS_FALL2 5
#define KAS_WALK2 6
#define KAS_JUMP2 7
// bell states
#define BELL_DONESOUND 1
@ -428,7 +443,7 @@
#define S_SLOPE 2
// Sprite types
#define MAXPTYPES 165
#define MAXPTYPES 166
#define P_PLAYER 0
#define P_RAT 1
#define P_CHEESE 2
@ -599,6 +614,7 @@
#define P_TOPHAT 162
#define P_KINGANT 163
#define P_FLAME 164 // like mace smash but harmless
#define P_BIGFIREBALL 165
#define FLY_FLYTIME 150
@ -1035,6 +1051,13 @@ typedef struct sprite_s {
struct sprite_s *prev;
} sprite_t;
typedef struct regrow_s {
int tx;
int ty;
int origid;
int timer;
} regrow_t;
typedef struct imageset_s {
SDL_Surface *img[MAXFRAMES*4];
int numimages;

312
rc.c
View File

@ -88,6 +88,10 @@ int gameovertime;
int sprayalpha; // for spray effect
regrow_t regrow[MAXREGROW]; // for tile regrowth
int numregrow = 0;
int gameover;
int firstlevel;
@ -986,7 +990,33 @@ int main (int argc, char **argv) {
* Timers
*/
if (!paused) {
int n;
if (++timer == 100) timer = 0;
for (n = 0 ; n < numregrow; n++) {
regrow[n].timer--;
if (regrow[n].timer <= 0) {
int nn,tx,ty;
// put original tile back
tx = regrow[n].tx;
ty = regrow[n].ty;
curlevel->map[ty * LEVELW + tx] = regrow[n].origid;
drawtile(temps, tx,ty);
puffin(-1, tx*TILEW+(TILEW/2), ty*TILEH+TILEH, "nothing", 0);
// remove from list
for (nn = n ; nn < (numregrow-1); nn++) {
regrow[nn].tx = regrow[nn+1].tx;
regrow[nn].ty = regrow[nn+1].ty;
regrow[nn].origid = regrow[nn+1].origid;
regrow[nn].timer = regrow[nn+1].timer;
}
numregrow--;
// do this number again
n--;
}
}
}
if (toggletimer > 0) toggletimer--;
@ -1001,6 +1031,7 @@ int main (int argc, char **argv) {
}
}
// screenshot
if (autoshot && (levelcomplete == LV_INPROGRESS)) {
if (shottaken) {
@ -1062,10 +1093,10 @@ void tick(void) {
SDL_framerateDelay(&manager);
}
if (paused) return;
if (levelcomplete == LV_HELPFREEZE) return;
fpsticks = SDL_GetTicks();
if (fpsstart == 0) {
fpsstart = fpsticks;
@ -1159,7 +1190,7 @@ void tick(void) {
if (!levelcomplete) {
// all sprites get angry and un-iced
for (s = sprite; s; s = s->next) {
if (!isplayer(s) && (ismonster(s->id))) {
if (!isplayer(s) && ismonster(s->id) ) {
s->angry = B_TRUE;
s->iced = B_FALSE;
}
@ -2266,7 +2297,9 @@ void checkcollide(sprite_t *s) {
}
// if a bullet hit us, it dies too
if (isbullet(s2->id)) {
s2->dead = D_FINAL;
if (s2->id != P_BIGFIREBALL) {
s2->dead = D_FINAL;
}
}
}
}
@ -4463,6 +4496,125 @@ printf("setting target to y = %d\n",ss->timer2);
addsprite(P_FLAME, s->x + (rand() % s->img->w) - (s->img->w/2),
s->y - (s->img->h/2) + (rand() % s->img->h/2), "antflame");
}
// move back and forth
if ((s->timer1 == KAS_WALK1) || (s->timer1 == KAS_WALK2)) {
// move
rv = movex(s, s->dir*getspeed(s), B_TRUE);
if (rv) {
/* if we couldn't move (hit a wall), turn */
s->dir = -s->dir;
}
// shoot out monsters
s->timer3--;
if (s->timer3 <= 0) {
// reset shoot timer
s->timer3 = KA_SHOOTTIME;
if (s->timer1 == KAS_WALK1) {
// shoot an ant out
if (countmonsters(-1) < 6) { // max 5 ants + king ant
sprite_t *newsp;
newsp = addsprite(P_ANT1, s->x, s->y-(s->img->h/2),"babant");
// make it shoot upwards
newsp->jumping = 1;
newsp->jumpspeed = (rand() % 7) + 7; // 7 - 13
newsp->jumpdir = (((double)(rand() % 110) - 50) / 10); // -5 to 5
if (rand() % 2) newsp->dir = 1;
else newsp->dir = -1;
playfx(FX_WHOOSH);
} else {
// TODO enough monsters, shoot food instead
}
}
}
// dec walk timer
s->timer2--;
if (s->timer2 == 0) {
if (playersalive()) {
// jump to other side height
if (s->timer1 == KAS_WALK1) s->timer1 = KAS_JUMP1;
else s->timer1 = KAS_JUMP2;
} else {
// nobody alive - reset timer
s->timer2 = KA_WALKTIME;
s->timer3 = KA_SHOOTTIME;
}
}
} else if ((s->timer1 == KAS_JUMP1) || (s->timer1 == KAS_JUMP2)) {
// jump to closest player height
if (!s->jumping) {
if (!playersalive() ) { // player below or dead
// go back to walking
s->timer1 = KAS_WALK1;
s->timer2 = KA_WALKTIME;
s->timer3 = KA_SHOOTTIME;
} else {
int jumpheight, jumptarget,nextstate;
jump(s, 0);
if (s->timer1 == KAS_JUMP1) {
jumpheight = 13;
jumptarget = TILEH*3; // jump to top
nextstate = KAS_WAITFORTOP1;
} else {
jumpheight = 3;
jumptarget = 480 - (TILEH*3); // jump to bottom
nextstate = KAS_WAITFORTOP2;
}
s->willjumpspeed = jumpheight;
// next state
s->timer1 = nextstate;
s->timer3 = jumptarget;
}
}
} else if (s->timer1 == KAS_WAITFORTOP1) {
if (!s->jumping) {
s->timer1 = KAS_FALL1;
}
} else if (s->timer1 == KAS_WAITFORTOP2) {
if (!s->jumping) {
s->timer1 = KAS_FALL2;
}
} else if ((s->timer1 == KAS_FALL1) || (s->timer1 == KAS_FALL2)) {
// King Ant's jump is handled specially in dogravity()
if (s->falling) {
if (!s->bullet) {
sprite_t *mytarget;
// shoot fireball if player in front!
mytarget = isplayerahead(s);
if (mytarget) {
sprite_t *ss;
// shoot!
playfx(FX_METEOR);
ss = addsprite(P_BIGFIREBALL,s->x,mytarget->y+(TILEH/2),"horzfireball" );
ss->ys = 0;
ss->xs = s->dir * 4;
ss->dir = s->dir;
ss->owner = s;
s->bullet = ss;
}
}
} else {
// back to normal state
if (s->timer1 == KAS_FALL1) {
s->timer1 = KAS_WALK2;
} else {
s->timer1 = KAS_WALK1;
}
s->timer2 = KA_WALKTIME;
s->timer3 = KA_SHOOTTIME;
}
}
} else if (s->id == P_PLATFORM) { // moving platform
// timer1 tells whether we are at top speed
double dstx,dsty;
@ -5184,6 +5336,26 @@ printf("setting target to y = %d\n",ss->timer2);
if (movex(s, s->xs, B_TRUE)) {
s->dead = D_FINAL;
}
} else if (s->id == P_BIGFIREBALL) {
tiletype_t *tt;
int yyy,tx,ty;
// move
s->x += s->xs;
// melt any ice bridges it touches
for (yyy = s->y - s->img->h ; yyy < s->y ; yyy += 4) {
tt = gettileat(s->x + (s->img->w/2),yyy, &tx,&ty);
if (tt->id == T_BRIDGE) {
melttile(tx,ty,REGROWTIMER_SHORT);
}
}
// die if it leaves screen
if (s->x >= (640-TILEW)) {
s->dead = D_FINAL;
} else if (s->x <= TILEW) {
s->dead = D_FINAL;
}
} else if (s->id == P_RAYGUNBULLET) {
s->x += s->xs;
if (s->x >= (640-TILEW)) {
@ -6316,6 +6488,8 @@ double getspeed(sprite_t *s ) {
else speed = 1.5;
} else if (id == P_KINGRAT) {
speed = 1.5;
} else if (id == P_KINGANT) {
speed = 1.5;
} else if (id == P_KINGFLY) {
speed = 2;
} else if (id == P_PLATFORM) {
@ -7440,14 +7614,61 @@ void dogravity(sprite_t *s) {
}
}
// king ant makes flames
if (s->id == P_KINGANT) {
// add flames on it
if (( timer % 2) == 0) {
addsprite(P_FLAME, s->x + (rand() % s->img->w) - (s->img->w/2),
s->y - (s->img->h/2) + (rand() % s->img->h/2), "antflame");
}
}
/* have we hit a roof ? */
/* can jump through one tile, but not two or more */
if (isroofabove(s) && isroofnabove(s,2)) {
if (s->id != P_KINGRAT) { // king rat can't hit roof
/* stop jumping */
s->jumping = B_FALSE;
s->falling = B_TRUE;
s->fallspeed = 0;
if (isroofabove(s)) {
// king ANT destroys tiles when jumping, and shoots at players
if (s->id == P_KINGANT) {
int xxx;
int tx,ty;
// melt roof
for (xxx = s->x - (s->img->w/2) ; xxx < s->x + (s->img->w/2) ; xxx += TILEW) {
tt = gettileat(xxx, s->y - s->img->h,&tx,&ty);
if (tt->id == T_BRIDGE) {
// melt it!
melttile(tx,ty,REGROWTIMER_LONG);
}
}
// shoot at players
if (!s->bullet) {
sprite_t *mytarget;
// shoot fireball if player in front!
mytarget = isplayerahead(s);
if (mytarget) {
sprite_t *ss;
// shoot!
playfx(FX_METEOR);
ss = addsprite(P_BIGFIREBALL,s->x,mytarget->y+(TILEH/2),"horzfireball" );
ss->ys = 0;
ss->xs = s->dir * 4;
ss->dir = s->dir;
ss->owner = s;
s->bullet = ss;
}
}
}
/* can jump through one tile, but not two or more */
if (isroofnabove(s,2)) {
if ((s->id != P_KINGRAT) && (s->id != P_KINGANT)) { // king rat can't hit roof
/* stop jumping */
s->jumping = B_FALSE;
s->falling = B_TRUE;
s->fallspeed = 0;
}
}
}
@ -7491,6 +7712,30 @@ void dogravity(sprite_t *s) {
s->falling = B_FALSE;
s->climbing = B_FALSE;
}
} else if ((s->id == P_KINGANT) && ((s->timer1 == KAS_FALL1) || (s->timer1 == KAS_FALL2))) { // special case
int xxx,tx,ty;
// add extra flames on it
if (( timer % 2) == 0) {
addsprite(P_FLAME, s->x + (rand() % s->img->w) - (s->img->w/2),
s->y - (s->img->h/2) + (rand() % s->img->h/2), "antflame");
}
// king ant drops until he is at the wanted height
if (s->y >= s->timer3) {
s->dropping = B_FALSE;
s->falling = B_FALSE;
s->climbing = B_FALSE;
} else {
// keep falling through
ontheground = B_FALSE;
}
// king ant melts ground
for (xxx = s->x - (s->img->w/2) ; xxx < s->x + (s->img->w/2) ; xxx += TILEW) {
tt = gettileat(xxx, s->y + 2 ,&tx,&ty);
if (tt->id == T_BRIDGE) {
melttile(tx,ty,REGROWTIMER_LONG);
}
}
} else if ((s->id == P_KINGSNAIL) && (s->timer1 == KSS_JUMPING)) { // special case
// king snail drops until he is at original height
if (s->y < s->timer3) { // above orig height
@ -12942,6 +13187,36 @@ sprite_t *isplayerright(sprite_t *s) {
return NULL;
}
sprite_t *isplayerahead(sprite_t *s) {
sprite_t *seen = NULL;
int ydis;
if (!playersalive()) {
seen = NULL;
} else {
if (player) {
ydis = abs((s->y - s->img->h/2) - (player->y - player->img->h/2));
if (ydis > TILEH*2) {
seen = NULL;
} else if ((s->dir < 0) && (player->x > s->x)) {
seen = NULL;
} else if ((s->dir > 0) && (player->x < s->x)) {
seen = NULL;
} else seen = player;
}
if (!seen && (player2)) {
ydis = abs((s->y - s->img->h/2) - (player2->y - player2->img->h/2));
if (ydis > TILEH*2) {
seen = NULL;
} else if ((s->dir < 0) && (player2->x > s->x)) {
seen = NULL;
} else if ((s->dir > 0) && (player2->x < s->x)) {
seen = NULL;
} else seen = player2;
}
}
return seen;
}
SDL_Color *getcolour(int id) {
@ -13207,3 +13482,20 @@ int savebmp(SDL_Surface *which) {
printf("Screenshot saved in %s\n",filename);
return rv;
}
void melttile(int tx, int ty,int howlong) {
if (numregrow >= (MAXREGROW-1)) {
return;
}
regrow[numregrow].tx = tx;
regrow[numregrow].ty = ty;
regrow[numregrow].origid = curlevel->map[ty * LEVELW + tx ];
regrow[numregrow].timer = howlong;
numregrow++;
curlevel->map[ty * LEVELW + tx ] = getuniq(T_BLANK);
drawtile(temps, tx,ty);
puffin(-1, tx*TILEW+(TILEW/2), ty*TILEH+TILEH, "nothing", 0);
}

2
rc.h
View File

@ -119,6 +119,7 @@ int inintro(void);
sprite_t *isplayerbelow(sprite_t *s);
sprite_t *isplayerabove(sprite_t *s);
sprite_t *isplayerright(sprite_t *s);
sprite_t *isplayerahead(sprite_t *s);
SDL_Color *getcolour(int id);
SDL_Color *getbgcolour(int id);
void dointroseq(void);
@ -128,3 +129,4 @@ int isonplatform(double x, double y);
int countbabies(sprite_t *s, int babytype);
int isice(int id);
int savebmp(SDL_Surface *which);
void melttile(int tx,int ty, int howlong);

View File

@ -859,7 +859,7 @@ void setdefaults(sprite_t *s) {
} else if (s->id == P_KINGANT) {
s->timer1 = KAS_WALK1;
s->timer2 = KA_WALKTIME;
s->timer3 = 0;
s->timer3 = KA_SHOOTTIME;
}
if (isboss(s->id)) {
s->lives = getbosshealth(s->id); // health
@ -1870,6 +1870,10 @@ int loadimagesets(void) {
loadspriteimage(P_FIREBALL,1, "sprites/fire2.png");
imageset[P_FIREBALL].numimages = 2;
loadspriteimage(P_BIGFIREBALL,0, "sprites/bigfire1.png");
loadspriteimage(P_BIGFIREBALL,1, "sprites/bigfire2.png");
imageset[P_BIGFIREBALL].numimages = 2;
// manual angry image for black cloud
@ -2745,6 +2749,7 @@ int isfruit(int id) {
int isbullet(int id) {
if (id == P_SPIT) return B_TRUE;
if (id == P_FIREBALL) return B_TRUE;
if (id == P_BIGFIREBALL) return B_TRUE;
return B_FALSE;
}