- Added new monster: moth
- Fixed bug where the player would get stuck after falling/jumping onto the top of a ladder
5
Makefile
|
@ -1,2 +1,5 @@
|
|||
rc: rc.c rc.h
|
||||
rc: rc.c rc.h shared.c shared.h defs.h
|
||||
gcc -Wall -DREV=`./getsvnrev.sh` -orc -g rc.c shared.c `sdl-config --cflags --libs` -I/usr/local/include -L/usr/local/lib -lSDLmain -lSDL -lSDL_image -lSDL_gfx -lSDL_ttf -lSDL_mixer
|
||||
|
||||
edit: edit.c edit.h shared.c shared.h defs.h
|
||||
gcc -D__EDITOR -Wall -DREV=`./getsvnrev.sh` -oedit -g edit.c shared.c `sdl-config --cflags --libs` -I/usr/local/include -L/usr/local/lib -lSDLmain -lSDL -lSDL_image -lSDL_gfx -lSDL_ttf -lSDL_mixer
|
||||
|
|
|
@ -4,9 +4,9 @@ hurryup 10
|
|||
help
|
||||
endhelp
|
||||
monsters
|
||||
134 18 15
|
||||
0 17 15
|
||||
171 4 7
|
||||
134 18 15
|
||||
172 17 28
|
||||
endmonsters
|
||||
exitdir 1
|
||||
4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,
|
||||
|
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 674 B |
After Width: | Height: | Size: 686 B |
After Width: | Height: | Size: 687 B |
After Width: | Height: | Size: 694 B |
15
defs.h
|
@ -1,4 +1,3 @@
|
|||
#define KAS_WAITFORTOP 2
|
||||
#ifndef __DEFS_H
|
||||
#define __DEFS_H
|
||||
|
||||
|
@ -289,6 +288,15 @@
|
|||
#define KAS_WALK2 6
|
||||
#define KAS_JUMP2 7
|
||||
|
||||
// moth
|
||||
#define MOTH_PAUSE 20
|
||||
#define MOTH_FIRESPACE 5 // space between shots
|
||||
// moth states
|
||||
#define MS_FLY 0
|
||||
#define MS_PAUSE1 1
|
||||
#define MS_PAUSE2 2
|
||||
|
||||
|
||||
// bell states
|
||||
#define BELL_DONESOUND 1
|
||||
#define BELL_DONEFLASH 2
|
||||
|
@ -444,7 +452,7 @@
|
|||
#define S_SLOPE 2
|
||||
|
||||
// Sprite types
|
||||
#define MAXPTYPES 172
|
||||
#define MAXPTYPES 174
|
||||
#define P_PLAYER 0
|
||||
#define P_RAT 1
|
||||
#define P_CHEESE 2
|
||||
|
@ -622,6 +630,8 @@
|
|||
#define P_LAMP 169
|
||||
#define P_GOLDBAR 170
|
||||
#define P_WSPIDER 171
|
||||
#define P_MOTH 172
|
||||
#define P_MOTHFIRE 173
|
||||
|
||||
|
||||
#define FLY_FLYTIME 150
|
||||
|
@ -811,6 +821,7 @@
|
|||
#define D_LEFT (-1)
|
||||
#define D_UP (-2)
|
||||
#define D_DOWN (2)
|
||||
#define D_NONE (0)
|
||||
|
||||
// boss health bar
|
||||
#define HEALTHBARY 480-100 // y position of health bar
|
||||
|
|
182
rc.c
|
@ -2800,12 +2800,14 @@ int movesprite(sprite_t *s) {
|
|||
if (isonground(s) || ((s->id == P_KINGRAT) && (s->timer1 == KRS_WALK))) {
|
||||
if ((!s->falling) && (!s->jumping)) {
|
||||
if (!s->climbing && !s->dropping) {
|
||||
if (!isonladder(s)) {
|
||||
if (!isonladder(s) ) {
|
||||
if ((s->id == P_KINGFLY) || ((s->id == P_FLY) && (s->owner))) {
|
||||
// don't adjust
|
||||
} else {
|
||||
adjustheight(s);
|
||||
}
|
||||
} else if (!s->climbing) { // on ladder but not climbing
|
||||
adjustheight(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5029,6 +5031,133 @@ int movesprite(sprite_t *s) {
|
|||
movex(s, s->jumpdir*getspeed(s), B_TRUE);
|
||||
faceplayer(s);
|
||||
}
|
||||
} else if (s->id == P_MOTH) {
|
||||
/* timer1 tracks state, timer2 tracks previous direction
|
||||
timer3 is current direction
|
||||
*/
|
||||
if (s->timer1 == MS_FLY) {
|
||||
if (s->timer3 == D_NONE) {
|
||||
int tx,ty;
|
||||
int d;
|
||||
int maxdist = -99;
|
||||
int newdir = D_NONE;
|
||||
tiletype_t *tt;
|
||||
|
||||
// get current pos
|
||||
tt = gettileat(s->x,s->y-2,&tx,&ty);
|
||||
// pick a direction
|
||||
// scan each direction...
|
||||
for (d = 0; d < 4; d++) {
|
||||
int xm,ym,dir;
|
||||
if (d == 0) {
|
||||
dir = D_UP;
|
||||
xm = 0; ym = -1;
|
||||
} else if (d == 1) {
|
||||
dir = D_RIGHT;
|
||||
xm = 1; ym = 0;
|
||||
} else if (d == 2) {
|
||||
dir = D_DOWN;
|
||||
xm = 0; ym = 1;
|
||||
} else { // ie. d == 3
|
||||
dir = D_LEFT;
|
||||
xm = -1; ym = 0;
|
||||
}
|
||||
// are we allowed to go this dir?
|
||||
if ((dir != s->timer2) && (dir != oppositedir(s->timer2))) {
|
||||
int curx,cury,hitwall=B_FALSE;
|
||||
int dist = 0;
|
||||
curx = tx;
|
||||
cury = ty;
|
||||
// check distance until wall
|
||||
while (!hitwall) {
|
||||
curx += xm;
|
||||
cury += ym;
|
||||
tt = gettilexy(curx, cury);
|
||||
|
||||
if (tt->solid) hitwall = 1;
|
||||
if (curx < 0) hitwall = 2;
|
||||
if (cury < 0) hitwall = 3;
|
||||
if (curx >= LEVELW) hitwall = 4;
|
||||
if (cury >= LEVELH) hitwall = 5;
|
||||
dist++;
|
||||
}
|
||||
if (dist > maxdist) {
|
||||
newdir = dir;
|
||||
maxdist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
// update our direction
|
||||
s->timer2 = s->timer3; // old dir
|
||||
s->timer3 = newdir; // current dir
|
||||
} else { // we DO have a current direction
|
||||
tiletype_t *tt;
|
||||
if (s->timer3 == D_UP) {
|
||||
tt = gettileat(s->x, s->y - s->img->h - getspeed(s), NULL, NULL);
|
||||
if (tt->solid) {
|
||||
// hit a wall
|
||||
s->timer1 = MS_PAUSE1;
|
||||
s->timer2 = s->timer3; // old dir
|
||||
s->timer3 = MOTH_PAUSE;
|
||||
} else {
|
||||
s->moved = MV_FLY;
|
||||
s->y -= getspeed(s);
|
||||
}
|
||||
} else if (s->timer3 == D_DOWN) {
|
||||
tt = gettileat(s->x, s->y + getspeed(s), NULL, NULL);
|
||||
if (tt->solid) {
|
||||
// hit a wall
|
||||
s->timer1 = MS_PAUSE1;
|
||||
s->timer2 = s->timer3; // old dir
|
||||
s->timer3 = MOTH_PAUSE;
|
||||
} else {
|
||||
s->moved = MV_FLY;
|
||||
s->y += getspeed(s);
|
||||
}
|
||||
} else { // right or left
|
||||
s->dir = s->timer3;
|
||||
if (movex(s, s->dir * getspeed(s), B_TRUE)) {
|
||||
// hit a wall
|
||||
s->timer1 = MS_PAUSE1;
|
||||
s->timer2 = s->timer3; // old dir
|
||||
s->timer3 = MOTH_PAUSE;
|
||||
} else {
|
||||
s->moved = MV_FLY;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (s->timer1 == MS_PAUSE1) {
|
||||
s->moved = MV_FLY;
|
||||
// wait for countdown...
|
||||
s->timer3--;
|
||||
if ((s->timer3 == MOTH_FIRESPACE*2) || (s->timer3 == MOTH_FIRESPACE) || (s->timer3 == 0)) {
|
||||
sprite_t *ss,*target = NULL;
|
||||
// closest player
|
||||
target = getclosestplayer(s);
|
||||
if (target) {
|
||||
double ang;
|
||||
// get angle towards target
|
||||
ang = atan2(target->y - s->y, target->x - s->x);
|
||||
// shoot
|
||||
ss = addsprite(P_MOTHFIRE,s->x,s->y - s->img->h/2,"mothfire" );
|
||||
ss->xs = cos(ang) * getspeed(ss);
|
||||
ss->ys = sin(ang) * getspeed(ss);
|
||||
}
|
||||
}
|
||||
if (s->timer3 == 0) {
|
||||
// go to next state
|
||||
s->timer1 = MS_PAUSE2;
|
||||
s->timer3 = MOTH_PAUSE;
|
||||
}
|
||||
} else if (s->timer1 == MS_PAUSE2) {
|
||||
s->moved = MV_FLY;
|
||||
s->timer3--;
|
||||
if (s->timer3 == 0) {
|
||||
// go to next state
|
||||
s->timer1 = MS_FLY;
|
||||
s->timer3 = D_NONE;
|
||||
}
|
||||
}
|
||||
} else if (s->id == P_SNAKE) {
|
||||
/* timer1 loopsfrom 0 - 19
|
||||
|
||||
|
@ -5628,6 +5757,20 @@ int movesprite(sprite_t *s) {
|
|||
} else if (s->x <= TILEW) {
|
||||
s->dead = D_FINAL;
|
||||
}
|
||||
} else if (s->id == P_MOTHFIRE) {
|
||||
// move
|
||||
s->x += s->xs;
|
||||
s->y += s->ys;
|
||||
// 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->y >= (480-TILEH)) {
|
||||
s->dead = D_FINAL;
|
||||
} else if (s->y <= TILEH) {
|
||||
s->dead = D_FINAL;
|
||||
}
|
||||
} else if (s->id == P_RAYGUNBULLET) {
|
||||
s->x += s->xs;
|
||||
if (s->x >= (640-TILEW)) {
|
||||
|
@ -6760,8 +6903,13 @@ double getspeed(sprite_t *s ) {
|
|||
else speed = 1.5;
|
||||
}
|
||||
} else if (id == P_SPIDER) {
|
||||
if (s->angry) speed = 2;
|
||||
else speed = 1.5;
|
||||
if (s->angry) speed = 2.5;
|
||||
else speed = 2.5;
|
||||
} else if (id == P_MOTH) {
|
||||
if (s->angry) speed = 3;
|
||||
else speed = 2.5;
|
||||
} else if (id == P_MOTHFIRE) {
|
||||
speed = 2.5;
|
||||
} else if (id == P_KINGRAT) {
|
||||
speed = 1.5;
|
||||
} else if (id == P_KINGANT) {
|
||||
|
@ -8542,7 +8690,7 @@ int movex(sprite_t *s,double amt,int onpurpose) {
|
|||
s->xs = 0;
|
||||
return NM_SIDE;
|
||||
}
|
||||
if (tt2->solid == S_SLOPE && (!candoslopes(s->id))) {
|
||||
if ((tt2->solid == S_SLOPE) && (!candoslopes(s->id))) {
|
||||
s->xs = 0;
|
||||
return NM_SIDE;
|
||||
}
|
||||
|
@ -13497,6 +13645,32 @@ void doplayermovement(sprite_t *pl) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
sprite_t *getclosestplayer(sprite_t *s) {
|
||||
double xdiff1,xdiff2,ydiff1,ydiff2,diff1,diff2;
|
||||
sprite_t *closest = NULL;
|
||||
// closest player
|
||||
if (player && !player->dead) {
|
||||
xdiff1 = abs(player->x - s->x);
|
||||
ydiff1 = abs(player->y - s->y);
|
||||
diff1 = xdiff1 + ydiff1;
|
||||
closest = player;
|
||||
} else {
|
||||
diff1 = 9999;
|
||||
}
|
||||
|
||||
if (player2 && !player2->dead) {
|
||||
xdiff2 = abs(player2->x - s->x);
|
||||
ydiff2 = abs(player2->y - s->y);
|
||||
diff2 = xdiff2 + ydiff2;
|
||||
if (closest == NULL) closest = player2;
|
||||
else if (closest == player) {
|
||||
if (diff2 > diff1) closest = player2;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
double getxdisttoplayer(sprite_t *s, sprite_t **pl) {
|
||||
double xdiff1,xdiff2,xdiff = 9999;
|
||||
if (globpowerup == PW_CAMERA) return 9999;
|
||||
|
|
1
rc.h
|
@ -113,6 +113,7 @@ void swimup(sprite_t *pl);
|
|||
void swimdown(sprite_t *pl);
|
||||
double getdistance(double x1, double y1, double x2, double y2);
|
||||
void doplayermovement(sprite_t *pl);
|
||||
sprite_t *getclosestplayer(sprite_t *s);
|
||||
double getxdisttoplayer(sprite_t *s, sprite_t **pl);
|
||||
double getydisttoplayer(sprite_t *s);
|
||||
int playersalive(void);
|
||||
|
|
58
shared.c
|
@ -843,7 +843,7 @@ void setdefaults(sprite_t *s) {
|
|||
s->lives = 1;
|
||||
}
|
||||
|
||||
// special for bosses
|
||||
// special for bosses/other monsters
|
||||
if (s->id == P_KINGRAT) {
|
||||
s->timer1 = 0;
|
||||
s->timer2 = KR_WALKTIME;
|
||||
|
@ -862,6 +862,10 @@ void setdefaults(sprite_t *s) {
|
|||
s->timer1 = KAS_WALK1;
|
||||
s->timer2 = KA_WALKTIME;
|
||||
s->timer3 = KA_SHOOTTIME;
|
||||
} else if (s->id == P_MOTH) {
|
||||
s->timer1 = MS_FLY;
|
||||
s->timer2 = D_NONE;
|
||||
s->timer3 = D_NONE;
|
||||
}
|
||||
if (isboss(s->id)) {
|
||||
s->lives = getbosshealth(s->id); // health
|
||||
|
@ -875,6 +879,7 @@ void setdefaults(sprite_t *s) {
|
|||
case P_BLACKCLOUD:
|
||||
case P_SPIDER:
|
||||
case P_KINGFLY:
|
||||
case P_MOTH:
|
||||
s->flies = B_TRUE;
|
||||
break;
|
||||
case P_FLY:
|
||||
|
@ -1046,6 +1051,36 @@ tiletype_t *gettileat(int pixx,int pixy, int *tilex,int *tiley) {
|
|||
return gettile(tid);
|
||||
}
|
||||
|
||||
int oppositedir(int dir) {
|
||||
if (dir == D_RIGHT) return D_LEFT;
|
||||
if (dir == D_LEFT) return D_RIGHT;
|
||||
if (dir == D_UP) return D_DOWN;
|
||||
if (dir == D_DOWN) return D_UP;
|
||||
|
||||
return D_NONE;
|
||||
}
|
||||
|
||||
tiletype_t *gettilexy(int tilex,int tiley) {
|
||||
int tx,ty;
|
||||
int tid;
|
||||
|
||||
tx = tilex;
|
||||
ty = tiley;
|
||||
|
||||
if (tx >= LEVELW) tx = LEVELW-1;
|
||||
if (ty >= LEVELH) ty = LEVELH-1;
|
||||
|
||||
if (ty < 0) ty = 0;
|
||||
if (tx < 0) tx = 0;
|
||||
|
||||
// return layer2 if it exists
|
||||
tid = curlevel->map2[ty*LEVELW+tx];
|
||||
if (tid == T_BLANK) {
|
||||
tid = curlevel->map[ty*LEVELW+tx];
|
||||
}
|
||||
return gettile(tid);
|
||||
}
|
||||
|
||||
int loadtiletypes(char *filename) {
|
||||
char fullfile[BUFLEN];
|
||||
tiletype_t *t = NULL;
|
||||
|
@ -1417,6 +1452,14 @@ int loadimagesets(void) {
|
|||
loadspriteimage(P_WSPIDER,F_CLIMB2, "sprites/whitespiderclimb1.png");
|
||||
imageset[P_WSPIDER].numimages = 10;
|
||||
|
||||
loadspriteimage(P_MOTH,F_WALK1, "sprites/moth.png");
|
||||
loadspriteimage(P_MOTH,F_JUMP, "sprites/moth1.png");
|
||||
loadspriteimage(P_MOTH,F_FALL, "sprites/moth1.png");
|
||||
loadspriteimage(P_MOTH,F_CAUGHT, "sprites/mothcaught.png");
|
||||
loadspriteimage(P_MOTH,F_DEAD, "sprites/mothdead.png");
|
||||
/* next 3 are auto generated */
|
||||
imageset[P_MOTH].numimages = 8;
|
||||
|
||||
|
||||
loadspriteimage(P_SPIDER,F_WALK1, "sprites/newspider.png");
|
||||
loadspriteimage(P_SPIDER,F_JUMP, "sprites/newspiderjump.png");
|
||||
|
@ -1906,6 +1949,14 @@ int loadimagesets(void) {
|
|||
loadspriteimage(P_BIGFIREBALL,1, "sprites/bigfire2.png");
|
||||
imageset[P_BIGFIREBALL].numimages = 2;
|
||||
|
||||
loadspriteimage(P_MOTHFIRE,0, "sprites/mothfire0.png");
|
||||
loadspriteimage(P_MOTHFIRE,1, "sprites/mothfire1.png");
|
||||
loadspriteimage(P_MOTHFIRE,2, "sprites/mothfire2.png");
|
||||
loadspriteimage(P_MOTHFIRE,3, "sprites/mothfire3.png");
|
||||
loadspriteimage(P_MOTHFIRE,4, "sprites/mothfire2.png");
|
||||
loadspriteimage(P_MOTHFIRE,5, "sprites/mothfire1.png");
|
||||
imageset[P_MOTHFIRE].numimages = 6;
|
||||
|
||||
|
||||
// manual angry image for black cloud
|
||||
|
||||
|
@ -2787,6 +2838,7 @@ 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;
|
||||
if (id == P_MOTHFIRE) return B_TRUE;
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -3246,6 +3298,7 @@ int ismonster(int id) {
|
|||
case P_ANT1:
|
||||
case P_ANT2:
|
||||
case P_ANT3:
|
||||
case P_MOTH:
|
||||
return MT_MONSTER;
|
||||
case P_BLACKCLOUD:
|
||||
case P_KINGRAT:
|
||||
|
@ -3761,6 +3814,7 @@ void setfruitinfo(void) {
|
|||
|
||||
setinfo(P_SPIDER, "Redback", "Redback spiders will lurk quietly on the ceiling, crawling back and forth. If they notice a player nearby however they will swiftly pounce down onto their prey!", "spider.png");
|
||||
setinfo(P_WSPIDER, "Whitetail", "Whitetail spiders are more intelligent than other monsters - they are aware of nearby players and will use the landscape to track them down!", "whitespider.png");
|
||||
setinfo(P_MOTH, "Moth", "The moth moves in straight lines until it hits a wall. Although simplistic in their movement, moths have the ability to fire a burst of hypno-rays to take out an unwary player!", "moth.png");
|
||||
|
||||
setinfo(P_FROG, "Frog", "Green frogs will continually bounce around, making them more difficult to catch. They are also excellent swimmers.", "frog.png");
|
||||
|
||||
|
@ -3847,6 +3901,8 @@ void dumpinfo(void) {
|
|||
printf("<img src=\"img/newspiderfall.png\">");
|
||||
} else if (i == P_WSPIDER) {
|
||||
printf("<img src=\"img/whitespiderclimb.png\">");
|
||||
} else if (i == P_MOTH) {
|
||||
printf("<img src=\"img/mothfire.png\">");
|
||||
}
|
||||
|
||||
printf("<br>%s</td><td>%s</td>\n",
|
||||
|
|
2
shared.h
|
@ -10,6 +10,7 @@ void setdefaults(sprite_t *s);
|
|||
int loadtiletypes(char *filename);
|
||||
sprite_t *addsprite(int id,int x, int y, char *name);
|
||||
tiletype_t *gettileat(int pixx,int pixy, int *tilex, int *tiley);
|
||||
tiletype_t *gettilexy(int tilex,int tiley);
|
||||
int loadimagesets(void);
|
||||
int isbullet(int id);
|
||||
void flip(void);
|
||||
|
@ -71,6 +72,7 @@ int getnumplayers(void);
|
|||
int isbadpowerup(int id);
|
||||
int iswinpowerup(int id);
|
||||
int isabilitypowerup(int id);
|
||||
int oppositedir(int dir);
|
||||
// for doco
|
||||
void setfruitinfo(void);
|
||||
void setinfo(int id, char *name, char *desc, char *file);
|
||||
|
|
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.1 KiB |
|
@ -34,7 +34,9 @@
|
|||
<img src="img/fire1.png"><br>Queen Ant</td><td>After an ant has eaten enough, they become a Queen. Queens are just as fast as soldiers and can also breath fire. Furthermore, they are only one meal away from spawning additional ants!</td>
|
||||
</tr><tr><td width=10% align=center><img src="img/whitespider.png">
|
||||
<img src="img/whitespiderclimb.png"><br>Whitetail</td><td>Whitetail spiders are more intelligent than other monsters - they are aware of nearby players and will use the landscape to track them down!</td>
|
||||
<td colspan=2> </td></tr><tr bgcolor="#ffff00"><th colspan=4>Bosses</th></tr>
|
||||
<td width=10% align=center><img src="img/moth.png">
|
||||
<img src="img/mothfire.png"><br>Moth</td><td>The moth moves in straight lines until it hits a wall. Although simplistic in their movement, moths have the ability to fire a burst of hypno-rays to take out an unwary player!</td>
|
||||
</tr></tr><tr bgcolor="#ffff00"><th colspan=4>Bosses</th></tr>
|
||||
<tr><td align=center><img src="img/cloud.png"><br>Cloud of Doom</td><td>This unkillable cloud will appear if you spend too much time on one level. Beware, as the only way to defeat the cloud of doom is to complete the level before it grows too large to handle!</td>
|
||||
<td align=center><img src="img/kingrat.png"><br>King Rat</td><td>This mighty creature is the ruler of the rats, and impervious to the player's net. It can only be harmed by slamming another monster into it! King Rat will roam the level searching for a player, and upon spotting them will charge at high speed.</td>
|
||||
</tr><tr><td align=center><img src="img/kingsnail.png"><br>King Snail</td><td>The absolute ruler of the snail kingdom is far too large and heavy to catch in a net. In addition, its shell provides protection against all attacks, leaving only its head vulnerable. While King Snail is too proud to chase down enemies itself, it can use its snail army to destroy its foes.</td>
|
||||
|
|