diff options
Diffstat (limited to 'galax.c')
-rw-r--r-- | galax.c | 1888 |
1 files changed, 1888 insertions, 0 deletions
@@ -0,0 +1,1888 @@ +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xos.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <fcntl.h> + +#include <unistd.h> + +#include "Xbit.h" + +#define WINX 100 +#define WINY 100 +#define WINW 220 +#define WINWH 110 +#define WINH 250 +#define WINHH 125 + +#define TAGLINE 242 + +#define RND(x) (rand()%(x)) + +#define ITOF(x) ((x)<<8) +#define FTOI(x) ((x)>>8) + +#define AT(p,x,y) *((p)+(x)+(y)*WINW) + +#define HISCFILE "hisc.gal" + +#define CH(x,y) ((x)*SCALE),((y)*SCALE),SCALE,SCALE + +XSizeHints size_hints; +int black,white; +Display *disp; +Window top,sub; +Colormap cm; +XFontStruct *font; +XImage *img; +char *data; +char *coll_data; + +double si[3600],co[3600]; + +static XFuncControl Key(Window w, XPressRelease s, XEvent *e); +static XFuncControl ProcessTitle(void),ProcessIntro(void),ProcessGame(void), + ProcessGameOver(void),ProcessHiScore(void), + ProcessStartLevel(void); + +/* Hiscore +*/ +#define NOHI 10 + +typedef struct + { + char name[4]; + int score; + int level; + double percent; + } HiSc; + +HiSc hisc[NOHI]= + { + {"A.B",10000,1,50.0}, + {"C.D",5000,1,50.0}, + {"E.F",3000,1,50.0}, + {"G.H",1500,1,50.0}, + {"I.J",1000,1,50.0}, + {"K.L",800,1,50.0}, + {"M.N",600,1,50.0}, + {"O.P",400,1,50.0}, + {"Q.R",200,1,50.0}, + {"S.T",100,1,50.0}, + }; + +/* Keycontrols +*/ +static XWindowKeyCallback key[2]= + { + {0,Key}, + {0,NULL} + }; + +#define NONE -1 +#define LEFT 0 +#define RIGHT 1 +#define FIRE 2 +#define QUIT 3 +#define PAUSE 4 + +int inkey=NONE; +KeySym last_keysym; +int keymap[PAUSE+1]={False,False,False,False,False}; + + +/* Sprite defs +*/ +#define SPRW 8 +#define SPRH 8 + +#define CHXSPR(a) ((a)*SPRW) + +#define SPRMAXANIM 10 +#define SPRANIMFRAME 10 + +unsigned int framectr =0; +unsigned int sprframe =0; + +typedef struct + { + ulong data[SPRH][SPRW]; + } SpriteDef; + +typedef struct + { + int no; + char data[SPRH*SPRW]; + } CollData; + +typedef struct + { + int no; + SpriteDef *spr[SPRMAXANIM]; + } SpriteAnim; + +#define NOSPR 11 + +#define SHIP 0 +#define ABULLET 1 +#define SBULLET 2 +#define GALAX1 3 +#define GALAX2 4 +#define GALAX3 5 +#define FLAG1 6 +#define FLAG10 7 +#define ENTITY1 8 +#define ALIENUFO 9 +#define SAFESHIP 10 + +#include "sprdef.h" + + +/* Collision data codes +*/ +#define CNONE 0 +#define CSHIP 1 +#define CALIEN 2 +#define CABULL 3 +#define CUBULLM 64 +#define CUBULL(x) (CUBULLM+(x)) + + +/* Alien data +*/ +#define NOSHOT 0 +#define SISHOT 1 +#define GASHOT 2 +#define VISHOT 3 + +typedef struct + { + int y; + int x; + int xi; + int yi; + int inuse; + } Shot; + +typedef struct + { + int alive; + int type; + Shot shot; + int x,y; + int sx,sy; /* Use for workspace for 'alternative' coords */ + } Alien; + + +#define MAXALIEN 100 +int no_aliens; +int aliens_alive; + +Alien alien[MAXALIEN]; + + +/* Explosion FX data +*/ +#define MAXEXP 20 +#define EXPPART 20 +#define EXPLIFE 10 +struct + { + int inuse; + int cx[EXPPART],cy[EXPPART],x[EXPPART],y[EXPPART]; + } exp_fx[MAXEXP]; + +int no_exp; + + +/* Level data +*/ +#define NOLEV 11 + +struct + { + char *title; + int sx,sy; + int shot_type; + } levdata[NOLEV]= + { + {"A CLASSIC...",0,1,SISHOT}, + {"RUN AWAY - WATCH YOUR BACK",1,-2,GASHOT}, + {"DIZZY",0,1,SISHOT}, + {"VICIOUS CARNIVAL DUCKS!",0,1,VISHOT}, + {"THE ALIEN WARFLEET - WAVE 1",-1,0,GASHOT}, + {"BOUNCY",0,1,GASHOT}, + {"THE 1ST COLLECTIVE",0,2,SISHOT}, + {"THE 2ND COLLECTIVE",0,2,SISHOT}, + {"THE 3RD COLLECTIVE",0,2,GASHOT}, + {"THE ALIEN WARFLEET - WAVE 2",-1,0,GASHOT}, + {"THE ALIEN MOTHERBRAIN",0,1,GASHOT}, + }; + + + +/* Colour vars +*/ +#define NOCOLS 8 +#define RNDCOL (RND(NOCOLS-2)+2) +#define RGB(r,g,b) {(r)*255,(g)*255,(b)*255} + +static ulong pix[NOCOLS]; +static Colour cols[NOCOLS]= + { + RGB(0,0,0), /* BLACK */ + RGB(255,255,255), /* WHITE */ + RGB(255,100,100), /* RED */ + RGB(100,255,100), /* GREEN */ + RGB(100,100,255), /* BLUE */ + RGB(255,255,0), /* YELLOW */ + RGB(0,255,255), /* CYAN */ + RGB(165,42,42) /* BROWN */ + }; + +#define BLACKI 0 +#define WHITEI 1 +#define REDI 2 +#define GREENI 3 +#define BLUEI 4 +#define YELLOWI 5 +#define CYANI 6 +#define BROWNI 7 + +#define BLACK pix[BLACKI] +#define WHITE pix[WHITEI] +#define RED pix[REDI] +#define GREEN pix[GREENI] +#define BLUE pix[BLUEI] +#define YELLOW pix[YELLOWI] +#define CYAN pix[CYANI] +#define BROWN pix[BROWNI] + + +/* Parallax vars +*/ +#define NOPLXST 30 +#define NOPLXPL 3 + +struct {int x,y,c} plxst[NOPLXST][NOPLXPL]; + + +/* User bullet vars +*/ +#define MAXBULL 100 +#define BULLYI -3 + +typedef struct + { + int inuse,x,y; + } UserBullet; + +UserBullet ubull[MAXBULL]; +int bullctr=0; + +/* Control vars +*/ +int NOLIVES =3; +int NOBULL =4; +int BULLDEL =10; +int LEVEL =0; +int SCORE =0; +int PAUSESKIP =0; +int FONT =0; + +int SCALE =1; +int POKEIMG_NS(),POKEIMG_S(); +int (*POKEIMG)(); + + +/* Game and control vars +*/ +#define SHXINIT WINW/2-SPRW/2 +#define SHIPY WINH-16 +#define BLYINIT SHIPY-8 + +int quit=False; + +int score,level,levelndx,lives; +int shipx,hit,miss,dead; +int aliendead; + + +int main(argc,argv) +int argc; +char *argv[]; + +{ + void IntrHandler(); + int f,r,x,y,arg,noshm; + unsigned long evmask; + + arg=1; + noshm=False; + + if (argc>arg) + if (!strcmp(argv[arg],"-noshm")) + { + noshm=True; + arg++; + } + + if (argc>arg) + { + SCALE=atoi(argv[arg]); + + if (SCALE<1) + { + fprintf(stderr,"scale param must be +ve\n"); + exit(1); + } + } + + if (SCALE==1) + POKEIMG=POKEIMG_NS; + else + POKEIMG=POKEIMG_S; + + for(f=0;f<NOPLXST;f++) + for(r=0;r<NOPLXPL;r++) + { + plxst[f][r].x=RND(WINW); + plxst[f][r].y=RND(WINH); + plxst[f][r].c=RNDCOL; + } + + for(f=0;f<3600;f++) + { + si[f]=sin(M_PI/1800.0*f); + co[f]=cos(M_PI/1800.0*f); + } + + umask(0); + srand(getpid()); + + size_hints.flags=PPosition|PSize|PMinSize|PMaxSize; + size_hints.x=WINX; + size_hints.y=WINY; + size_hints.width=size_hints.min_width=WINW*SCALE; + size_hints.height=size_hints.min_height=WINH*SCALE; + size_hints.max_width=WINW; + size_hints.max_height=WINH; + + evmask=KeyPressMask|KeyReleaseMask; + + top=OpenWin(argc,argv,argv[0], + WINX,WINY,WINW*SCALE,WINH*SCALE, + WINW*SCALE,WINH*SCALE, + evmask, + &size_hints,&black,&white); + + key[0].w=top; + + DisableDoubleBuffer(); + disp=GetDisplay(); + + DisablePixmap(); + + if (noshm) + DisableShm(); + + img=CreateXImage(); + + if (!(coll_data=(char *)malloc(WINW*WINH))) + { + fprintf(stderr,"Couldn't malloc() collision data\n"); + exit(1); + } + + AllocColoursRGB(NOCOLS,pix,cols); + + for(f=0;f<NOSPR;f++) + for(r=0;r<SPRMAXANIM;r++) + if (anim[f].spr[r]) + for(x=0;x<SPRW;x++) + for(y=0;y<SPRH;y++) + anim[f].spr[r]->data[y][x]= + pix[anim[f].spr[r]->data[y][x]]; + + XAutoRepeatOff(disp); + + XISetFont(FONT); + + ReadScores(); + + XDoWindows(NULL,NULL,key,ProcessTitle); + + while(!quit) + { + score=SCORE; + level=LEVEL; + levelndx=LEVEL%NOLEV; + lives=NOLIVES; + hit=0; + miss=0; + + do + { + shipx=SHXINIT; + dead=False; + + ClearBullets(); + ClearExplosions(); + ClearKeys(); + XDoWindows(NULL,NULL,key,ProcessStartLevel); + + DefineAliens(); + + ClearBullets(); + ClearExplosions(); + ClearKeys(); + XDoWindows(NULL,NULL,key,ProcessGame); + } while (lives>0); + + if (score>-1) + { + ClearBullets(); + ClearExplosions(); + ClearKeys(); + XDoWindows(NULL,NULL,key,ProcessGameOver); + + ReadScores(); + if (score>hisc[NOHI-1].score) + { + XDoWindows(NULL,NULL,key,ProcessHiScore); + WriteScores(); + } + } + + ClearKeys(); + XDoWindows(NULL,NULL,key,ProcessTitle); + } + + XAutoRepeatOn(disp); + DestroyXImage(img); + XCloseDisplay(disp); +} + + +/* ----------------------------------------------- KEY AND UTILITY +*/ +static XFuncControl Key(Window w, XPressRelease s, XEvent *e) +{ + if (s==XRELEASE) + { + last_keysym=XK_VoidSymbol; + + switch(XLookupKeysym((XKeyEvent *)e,ShiftMapIndex)) + { + case XK_Z: + case XK_z: + keymap[LEFT]=False; + break; + + case XK_C: + case XK_c: + keymap[RIGHT]=False; + break; + + case XK_period: + keymap[FIRE]=False; + break; + + case XK_P: + case XK_p: + keymap[PAUSE]=False; + break; + + case XK_Q: + case XK_q: + keymap[QUIT]=False; + break; + + default: + keymap[NONE]=False; + break; + } + } + + if (s==XPRESS) + { + inkey=NONE; + + switch(last_keysym=XLookupKeysym((XKeyEvent *)e,ShiftMapIndex)) + { + case XK_Z: + case XK_z: + inkey=LEFT; + break; + + case XK_C: + case XK_c: + inkey=RIGHT; + break; + + case XK_period: + inkey=FIRE; + break; + + case XK_P: + case XK_p: + inkey=PAUSE; + break; + + case XK_Q: + case XK_q: + inkey=QUIT; + break; + + default: + inkey=NONE; + break; + } + + if (inkey!=NONE) + keymap[inkey]=True; + } + + return (XFUNCCONT); +} + + +int GetKey() + +{ + int k=inkey; + + if ((inkey==PAUSE)||(inkey==QUIT)||(inkey=FIRE)) + inkey=NONE; + + return(k); +} + + +KeySym RawKey() + +{ + KeySym k=last_keysym; + + last_keysym=XK_VoidSymbol; + return(k); +} + + +ClearKeys() +{ + int f; + + inkey=NONE; + + for(f=0;f<5;f++) + keymap[f]=False; +} + + +/* ----------------------------------------------- GRAPHICS UTILS +*/ +Cls(plx,xi,yi,clr) +int plx,xi,yi,clr; + +{ + static unsigned int col; + int f,r,x,y; + + if (!((framectr++)%SPRANIMFRAME)) + { + sprframe++; + + for(f=0;f<NOSPR;f++) + spr[f]=anim[f].spr[sprframe%anim[f].no]; + } + + if (clr) + { + /* memset(data,black,WINW*WINH*SCALE*SCALE); */ + ClsXImage(img); + memset(coll_data,CNONE,WINW*WINH); + } + + if (plx) + { + col++; + + for(f=0;f<NOPLXST;f++) + for(r=0;r<NOPLXPL;r++) + { + plxst[f][r].y+=((r+1)*yi); + + if (plxst[f][r].y<0) + plxst[f][r].y+=WINH; + + if (plxst[f][r].y>=WINH) + plxst[f][r].y-=WINH; + + plxst[f][r].x+=((r+1)*xi); + + if (plxst[f][r].x<0) + plxst[f][r].x+=WINW; + + if (plxst[f][r].x>=WINW) + plxst[f][r].x-=WINW; + + if (!(col%10)) + plxst[f][r].c=RNDCOL; + + (*POKEIMG)(img,plxst[f][r].x,plxst[f][r].y,plxst[f][r].c); + } + } +} + + +Update() +{ + DrawXImage(img); + XSync(disp,False); +} + + +Centre(y,c,s) +int y,c; +char *s; + +{ + XIprintf(img,CH(WINWH-strlen(s)*4,y),c,"%s",s); +} + + +POKEIMG_NS(img,x,y,c) +XImage *img; +int x,y,c; + +{ + XPutPixel(img,x,y,c); +} + + +POKEIMG_S(img,x,y,c) +XImage *img; +int x,y,c; + +{ + int sx,sy; + + for(sx=0;sx<SCALE;sx++) + for(sy=0;sy<SCALE;sy++) + XPutPixel(img,x*SCALE+sx,y*SCALE+sy,c); +} + + +Plot(x,y,c) +int x,y,c; + +{ + if ((x>=0)&&(x<WINW)&&(y>=0)&&(y<WINH)) + (*POKEIMG)(img,x,y,c); +} + + +Sprite(s,x,y,coll,collcode) +int s,x,y; +CollData *coll; + +{ + int sx,sy; + + if (coll) + coll->no=0; + + for(sy=0;sy<SPRW;sy++) + if (((y+sy)>=0)&&((y+sy)<WINH)) + for(sx=0;sx<SPRW;sx++) + if (spr[s]->data[sy][sx]!=BLACKI) + if (((x+sx)>=0)&&((x+sx)<WINW)) + { + if (coll) + { + if (AT(coll_data,x+sx,y+sy)!=CNONE) + coll->data[coll->no++]=AT(coll_data,x+sx,y+sy); + + AT(coll_data,x+sx,y+sy)=collcode; + } + + (*POKEIMG)(img,x+sx,y+sy,spr[s]->data[sy][sx]); + } +} + + +/* ----------------------------------------------- USER BULLET UTILS +*/ +ClearBullets() +{ + int f; + + bullctr=0; + + for(f=0;f<NOBULL;f++) + ubull[f].inuse=False; +} + + +NewBullet(x,y) +int x,y; + +{ + int f; + + for(f=0;f<NOBULL;f++) + if (!ubull[f].inuse) + { + ubull[f].inuse=True; + ubull[f].x=x; + ubull[f].y=y; + return; + } +} + + +DeleteBullet(f,y) + +{ + ubull[f].inuse=False; +} + + +int BulletsInUse() +{ + int f,c; + + for(f=c=0;f<NOBULL;f++) + if (ubull[f].inuse) + c++; + + return(c); +} + + +int FreeBullets() +{ + return(BulletsInUse()<NOBULL); +} + + +int UpdateBullets() +{ + CollData coll; + int f; + + for(f=0;f<NOBULL;f++) + if (ubull[f].inuse) + { + Sprite(SBULLET,ubull[f].x,ubull[f].y,&coll,CUBULL(f)); + + if ((ubull[f].y+=BULLYI)<-8) + { + ubull[f].inuse=False; + miss++; + } + } +} + + +/* ----------------------------------------------- TITLE SCREEN +*/ +static XFuncControl ProcessTitle(void) + +{ + static unsigned int ctr=0; + static int xi[8]={ 0,-1,-1,-1, 0, 1, 1, 1}; + static int yi[8]={ 1, 1, 0,-1,-1,-1, 0, 1}; + int f,k; + + ctr++; + + Cls(True,xi[(ctr%800)/100],yi[(ctr%800)/100],True); + + Centre(20,YELLOW,"GALAXY INVADERS"); + Centre(12,YELLOW,"________________"); + Centre(22,YELLOW,"________________"); + + if ((ctr/100)%2) + { + Centre(70,RNDCOL,"ALL TIME HEROES"); + for(f=0;f<NOHI;f++) + XIprintf(img,CH(4,95+f*10),WHITE, + "%2d %-3s %8d %5.1f%% %3d", + f+1,hisc[f].name,hisc[f].score, + hisc[f].percent,hisc[f].level); + /* + XIprintf(img,CH(8,85+f*10),WHITE, + "%2d %3s %8d %5.1f%%", + f+1,hisc[f].name,hisc[f].score,hisc[f].percent); + */ + } + else + { + Centre(100,RED," - 10 POINTS"); + Centre(115,RED," - 20 POINTS"); + Centre(130,RED," - 40 POINTS"); + + Sprite(GALAX1,7*8,100,NULL,CNONE); + Sprite(GALAX2,7*8,115,NULL,CNONE); + Sprite(GALAX3,7*8,130,NULL,CNONE); + } + + if ((ctr/10)%2) + Centre(220,WHITE,"PRESS FIRE TO PLAY"); + + DoDebugMenu(); + + Update(); + + k=GetKey(); + + if (k==FIRE) + return(XFUNCSTOP); + else if (k==QUIT) + { + quit=True; + return(XFUNCSTOP); + } + else + return(XFUNCCONT); +} + + +DoDebugMenu(fl) + +{ + static int debug_menu=False; + KeySym k; + int f; + + if ((k=RawKey())=='r') + debug_menu=!debug_menu; + + if (debug_menu) + { + Cls (False,0,0,True); + + for(f=0;f<128;f++) + XIprintf(img,CH((f%20)*8,(f/20)*8),CYAN,"%c",f); + + for(f=0;f<NOSPR;f++) + Sprite(f,f*8,80,NULL,CNONE); + + XIprintf(img,CH(0,TAGLINE-56),CYAN, + "(f) FONT : %5d",FONT); + XIprintf(img,CH(0,TAGLINE-48),CYAN, + "(k) PAUSE==SKIP : %5d",PAUSESKIP); + XIprintf(img,CH(0,TAGLINE-40),CYAN, + "(h) SCORE : %5d",SCORE); + XIprintf(img,CH(0,TAGLINE-32),CYAN, + "(l) LIVES : %5d",NOLIVES); + XIprintf(img,CH(0,TAGLINE-24),CYAN, + "(d) GUN DELAY : %5d",BULLDEL); + XIprintf(img,CH(0,TAGLINE-16),CYAN, + "(m) NO BULLETS : %5d",NOBULL); + XIprintf(img,CH(0,TAGLINE-8),CYAN, + "(s) START LEVEL : %5d",LEVEL); + XIprintf(img,CH(0,TAGLINE),CYAN, + "(%s)",levdata[LEVEL%NOLEV].title); + + XIprintf(img,CH(0,100),CYAN,"(x) SET TO DEFAULTS"); + XIprintf(img,CH(0,108),CYAN,"(o) SET TO DEBUG"); + XIprintf(img,CH(0,116),CYAN,"(w) SET TO SMALLER DEBUG"); + + switch(k) + { + case 'f': + FONT^=1; + XISetFont(FONT); + break; + case 'k': + PAUSESKIP=!PAUSESKIP; + break; + case 'h': + SCORE=hisc[0].score; + break; + case 'l': + if ((++NOLIVES)>10) + NOLIVES=1; + break; + case 'd': + if (BULLDEL==10) + BULLDEL=1; + else + BULLDEL=10; + break; + case 'm': + if (NOBULL==4) + NOBULL=MAXBULL; + else + NOBULL=4; + break; + case 's': + LEVEL++; + break; + case 'x': + SCORE=0; + NOLIVES=3; + BULLDEL=10; + NOBULL=4; + LEVEL=0; + break; + case 'o': + PAUSESKIP=1; + NOLIVES=1; + BULLDEL=1; + NOBULL=MAXBULL; + LEVEL=NOLEV-1; + SCORE=hisc[0].score; + break; + case 'w': + PAUSESKIP=1; + LEVEL=NOLEV-1; + break; + } + } +} + + +/* ----------------------------------------------- START LEVEL +*/ +static XFuncControl ProcessStartLevel(void) +{ + char s[80]; + + Cls(True,levdata[levelndx].sx,levdata[levelndx].sy,True); + + sprintf(s,"LEVEL %d",level+1); + + Centre (50,YELLOW,s); + Centre (100,RED,levdata[levelndx].title); + + Update(); + + if (GetKey()!=NONE) + return(XFUNCSTOP); + + return(XFUNCCONT); +} + + +/* ----------------------------------------------- PLAY LEVEL +*/ +static XFuncControl ProcessGame(void) + +{ + static unsigned int ctr=0; + static int immune=0; + int f,k; + CollData coll; + + ctr++; + + k=GetKey(); + + if (!PAUSESKIP) + if (Paused(k)) + return (XFUNCCONT); + + Cls(True,levdata[levelndx].sx,levdata[levelndx].sy,True); + + if (lives) + for(f=0;f<lives;f++) + Sprite(SHIP,WINW-CHXSPR(f),TAGLINE,NULL,CNONE); + + if ((level+1)/10) + for(f=0;f<(level+1)/10;f++) + Sprite(FLAG10,CHXSPR(f),TAGLINE,NULL,CNONE); + + if ((level+1)%10) + for(f=0;f<(level+1)%10;f++) + Sprite(FLAG1,CHXSPR((level+1)/10+f),TAGLINE,NULL,CNONE); + + XIprintf(img,CH(0,0),YELLOW,"SCORE %d",score); + + if (!dead) + { + if (keymap[LEFT]) + if (shipx>1) + shipx-=2; + + if (keymap[RIGHT]) + if (shipx<WINW-SPRW-1) + shipx+=2; + + if (keymap[FIRE]) + if (bullctr==0) + { + bullctr=BULLDEL; + NewBullet(shipx,BLYINIT); + } + } + + if (bullctr) + bullctr--; + + MoveAliens(); + + UpdateBullets(); + UpdateExplosions(); + DrawAndKillAliens(); + + if (!dead) + { + if (immune) + Sprite(SAFESHIP,shipx,SHIPY,&coll,CSHIP); + else + Sprite(SHIP,shipx,SHIPY,&coll,CSHIP); + + if ((bullctr==0)&&(FreeBullets())) + Sprite(SBULLET,shipx,BLYINIT,NULL,CNONE); + + if (immune) + immune--; + + if ((coll.no)&&(!immune)) + { + dead=True; + + for(f=0;f<5;f++) + { + NewExplosion(shipx+SPRW/2-(SPRW/2*f),SHIPY+SPRH/2,6-f); + NewExplosion(shipx+SPRW/2+(SPRW/2*f),SHIPY+SPRH/2,6-f); + NewExplosion(shipx+SPRW/2,SHIPY+SPRH/2-(SPRH/2*f),6-f); + } + } + } + + Update(); + + if (k==QUIT) + { + score=-1; + lives=0; + return(XFUNCSTOP); + } + + if ((k==PAUSE)&&(PAUSESKIP)) + { + level++; + levelndx=(levelndx+1)%NOLEV; + return(XFUNCSTOP); + } + + if ((dead)&&(no_exp==0)) + { + lives--; + + if (lives==0) + return(XFUNCSTOP); + else + { + shipx=SHXINIT; + dead=False; + immune=100; + } + } + + if ((aliendead)&&(no_exp==0)&&(!dead)) + { + level++; + levelndx=(levelndx+1)%NOLEV; + + if ((levelndx==0)&&(level>1)) + lives++; + + return(XFUNCSTOP); + } + + return(XFUNCCONT); +} + + +/* ----------------------------------------------- PAUSE CODE +*/ +DoPause() +{ + static unsigned int c=0; + + c++; + + if ((c/10)%2) + Centre(WINH/2-4,WHITE,"PAUSED"); + else + Centre(WINH/2-4,YELLOW,"PAUSED"); + + Update(); +} + + +int Paused(k) +int k; + +{ + static int paused=False; + + if (k==PAUSE) + paused=!paused; + + if (paused) + DoPause(); + + return(paused); +} + + +/* ----------------------------------------------- GAME OVER +*/ +static XFuncControl ProcessGameOver(void) +{ + static int posx=32; + static unsigned int ctr=0; + + Cls (True,0,1,True); + + ctr++; + + XIprintf(img,CH(posx,32),YELLOW,"SHOTS FIRED : %6d",hit+miss); + XIprintf(img,CH(posx,48),YELLOW,"HIT : %6d",hit); + XIprintf(img,CH(posx,64),YELLOW,"MISS : %6d",miss); + if (hit+miss) + XIprintf(img,CH(posx,80),YELLOW,"PERCENTAGE : %5.1f", + ((double)hit/(hit+miss))*100.0); + else + XIprintf(img,CH(posx,80),YELLOW,"PERCENTAGE : 0.0"); + + if ((ctr/10)%2) + Centre(120,WHITE,"GAME OVER"); + + Update(); + + if (GetKey()==NONE) + return(XFUNCCONT); + else + return(XFUNCSTOP); +} + + +/* ----------------------------------------------- HI SCORES +*/ +ReadScores() +{ + int fd,f; + + if ((fd=open(HISCFILE,O_RDONLY))==-1) + return; + + for(f=0;f<NOHI;f++) + read(fd,hisc+f,sizeof(HiSc)); + + close(fd); +} + + +WriteScores() +{ + int fd,f; + + if ((fd=open(HISCFILE,O_WRONLY|O_CREAT|O_TRUNC,0777))==-1) + { + fprintf(stderr,"Failed to write hiscores!\n"); + return; + } + + for(f=0;f<NOHI;f++) + write(fd,hisc+f,sizeof(HiSc)); + + close(fd); +} + + +static XFuncControl ProcessHiScore(void) +{ + static char *hisc_let="ABCDEFGHIJKLMNOPQRSTUVWXYZ.\177"; + static char *let; + static int len=0; + static char name[4]; + static int first=True; + static int pos=0; + static int bounce=0; + int f,done=False; + + if (first) + { + len=0; + strcpy(name,""); + let=hisc_let; + bounce=0; + + for(f=NOHI-1;f>-1;f--) + if (hisc[f].score<score) + pos=f; + + if (pos<NOHI-1) + for(f=NOHI-1;f>pos;f--) + hisc[f]=hisc[f-1]; + + strcpy(hisc[pos].name,""); + hisc[pos].score=score; + hisc[pos].level=level+1; + if (hit+miss) + hisc[pos].percent=((double)hit/(hit+miss))*100.0; + else + hisc[pos].percent=0.0; + + first=False; + } + + Cls (True,1,1,True); + + Centre(16,WHITE,"CONGRATULATIONS!"); + Centre(30,YELLOW,"ENTER YOUR INITIALS"); + Centre(40,YELLOW,"FOR THE ALL TIME HEROES"); + + hisc[pos].name[len]=*let; + hisc[pos].name[len+1]=0; + + for(f=0;f<NOHI;f++) + XIprintf(img,CH(4,110+f*10),(f==pos) ? (CYAN) : (RED), + "%2d %-3s %8d %5.1f%% %3d", + f+1,hisc[f].name,hisc[f].score, + hisc[f].percent,hisc[f].level); + + if ((keymap[LEFT])&&(!bounce)) + { + bounce=30; + if (let==hisc_let) + let=hisc_let+strlen(hisc_let)-1; + else + let--; + } + + if ((keymap[RIGHT])&&(!bounce)) + { + bounce=30; + if (!(*++let)) + let=hisc_let; + } + + switch (GetKey()) + { + case FIRE: + len++; + break; + case NONE: + bounce=0; + break; + } + + if (bounce) + bounce--; + + Update(); + + if (len==3) + { + first=True; + return(XFUNCSTOP); + } + else + return(XFUNCCONT); +} + + +/* ----------------------------------------------- PARTICLE EXPLOSION ROUTINES +*/ +ClearExplosions() +{ + int f; + + no_exp=0; + + for(f=0;f<MAXEXP;f++) + exp_fx[f].inuse=0; +} + + +NewExplosion(x,y,w) +int x,y,w; + +{ + int f,r; + + for(f=0;f<MAXEXP;f++) + if (!exp_fx[f].inuse) + { + exp_fx[f].inuse=EXPLIFE*w; + for(r=0;r<EXPPART;r++) + { + exp_fx[f].cx[r]=x+RND(5)-2; + exp_fx[f].cy[r]=y+RND(5)-2; + exp_fx[f].x[r]=RND(5)-2; + exp_fx[f].y[r]=RND(5)-2; + } + no_exp++; + return; + } +} + + +UpdateExplosions() +{ + int f,r; + + for(f=0;f<MAXEXP;f++) + if (exp_fx[f].inuse) + { + for(r=0;r<EXPPART;r++) + Plot(exp_fx[f].cx[r]+=exp_fx[f].x[r], + exp_fx[f].cy[r]+=exp_fx[f].y[r], + CYAN); + + if ((--exp_fx[f].inuse)==0) + no_exp--; + } +} + + +/* ----------------------------------------------- ALIEN DEFINITION AND MOVEMENT +*/ +int alienctr; +int alienyi; +int alienxi; + +InitAlien(f,x,y,t) +int f,x,y,t; + +{ + alien[f].alive=True; + alien[f].type=t; + alien[f].x=x; + alien[f].y=y; + alien[f].shot.inuse=False; +} + + +SinCos(cx,cy,a,rx,ry,x,y) +int cx,cy,a,rx,ry,*x,*y; + +{ + double dx,dy; + + dx=cx+si[a]*rx; + dy=cy+co[a]*ry; + + *x=(int)dx; + *y=(int)dy; +} + + +DefineAliens() +{ + int f,x,y; + + alienctr=0; + + switch(levelndx) + { + case 0: /* CLASSIC */ + no_aliens=0; + + for (x=0;x<10;x++) + for (y=0;y<3;y++) + { + InitAlien(no_aliens,x*16,y*16+50,GALAX3-y); + no_aliens++; + } + + alienxi=1; + + break; + + case 1: /* RUN AWAY */ + no_aliens=0; + + for(f=0;f<20;f++) + { + InitAlien(no_aliens,RND(WINW-SPRW*2)+SPRW,RND(WINH/2)+WINH/4, + GALAX1+RND(3)); + no_aliens++; + } + + break; + + case 2: /* DIZZY */ + no_aliens=0; + + for(y=0;y<3;y++) + for(x=0;x<10;x++) + { + InitAlien(no_aliens,360*x,y*20+20,GALAX3-y); + alien[no_aliens].sx=alien[no_aliens].x; + alien[no_aliens].sy=alien[no_aliens].y; + no_aliens++; + } + + break; + + case 3: /* CARNIVAL */ + no_aliens=0; + + for(f=0;f<WINW/10;f++) + { + InitAlien(no_aliens,f*10,WINH-120,GALAX1+RND(3)); + no_aliens++; + } + + break; + + case 4: /* FLEET WAVE 1 */ + no_aliens=0; + + for(x=0;x<24;x++) + for(y=0;y<3;y++) + { + InitAlien(no_aliens,3+x*9,50+8*y,ALIENUFO); + no_aliens++; + } + + break; + + case 5: /* BOUNCY */ + no_aliens=0; + + for(f=0;f<20;f++) + { + InitAlien(no_aliens,RND(WINW),RND(WINH/2)+WINH/4,GALAX1); + + do + { + alien[no_aliens].sx=RND(3)-1; + } while (alien[no_aliens].sx==0); + + do + { + alien[no_aliens].sy=RND(5)-2; + } while (alien[no_aliens].sy==0); + + no_aliens++; + } + + break; + + case 6: /* THE COLLECTIVE 1 */ + no_aliens=0; + + for(y=0;y<SPRH;y++) + for(x=0;x<SPRW;x++) + if (galax1_1.data[y][x]!=BLACK) + { + InitAlien(no_aliens,0,0,GALAX1); + alien[no_aliens].sx=x; + alien[no_aliens].sy=y; + no_aliens++; + } + else if (galax1_2.data[y][x]!=BLACK) + { + InitAlien(no_aliens,0,0,GALAX1); + alien[no_aliens].sx=x; + alien[no_aliens].sy=y; + no_aliens++; + } + break; + + case 7: /* THE COLLECTIVE 2 */ + no_aliens=0; + + for(y=0;y<SPRH;y++) + for(x=0;x<SPRW;x++) + if (galax2_1.data[y][x]!=BLACK) + { + InitAlien(no_aliens,0,0,GALAX2); + alien[no_aliens].sx=x; + alien[no_aliens].sy=y; + no_aliens++; + } + else if (galax2_2.data[y][x]!=BLACK) + { + InitAlien(no_aliens,0,0,GALAX2); + alien[no_aliens].sx=x; + alien[no_aliens].sy=y; + no_aliens++; + } + break; + + case 8: /* THE COLLECTIVE 2 */ + no_aliens=0; + + for(y=0;y<SPRH;y++) + for(x=0;x<SPRW;x++) + if (galax3_1.data[y][x]!=BLACK) + { + InitAlien(no_aliens,0,0,GALAX3); + alien[no_aliens].sx=x; + alien[no_aliens].sy=y; + no_aliens++; + } + else if (galax3_2.data[y][x]!=BLACK) + { + InitAlien(no_aliens,0,0,GALAX3); + alien[no_aliens].sx=x; + alien[no_aliens].sy=y; + no_aliens++; + } + else if (galax3_3.data[y][x]!=BLACK) + { + InitAlien(no_aliens,0,0,GALAX3); + alien[no_aliens].sx=x; + alien[no_aliens].sy=y; + no_aliens++; + } + break; + + case 9: /* FLEET WAVE 2 */ + no_aliens=0; + + for (y=0;y<3;y++) + for (x=0;x<20;x++) + { + InitAlien(no_aliens,(WINW*x)/20,y*10+WINH/2-10,GALAX3-y); + no_aliens++; + } + + break; + + case 10: /* ALIEN MOTHERBRAIN */ + no_aliens=0; + + x=10; + y=3; + for(f=0;f<44;f++) + { + InitAlien(no_aliens,0,0,ENTITY1); + alien[no_aliens].sx=x; + alien[no_aliens].sy=y; + + no_aliens++; + + x+=y; + + if ((x<10)||(x>WINW/3)) + { + y=-y; + x+=y; + } + } + break; + + default: + printf("undefined level %d?\n",levelndx); + exit(1); + } +} + + +MoveAliens() +{ + int f,x,y; + int flag=False; + + alienctr++; + + switch(levelndx) + { + case 0: /* CLASSIC */ + for (f=0;f<no_aliens;f++) + if (alien[f].alive) + { + alien[f].x+=alienxi; + + if ((alien[f].x<1)||(alien[f].x>WINW-SPRW-1)) + flag=True; + } + + if (flag) + { + alienxi=-alienxi; + + for (f=0;f<no_aliens;f++) + if (alien[f].alive) + if ((alien[f].y+=4)>WINH) + alien[f].y-=WINH; + } + + break; + + case 1: /* RUN AWAY */ + for (f=0;f<no_aliens;f++) + if (alien[f].alive) + if ((alien[f].y-=1)<=-SPRH) + alien[f].y+=WINH+SPRH; + + break; + + case 2: /* DIZZY */ + for(y=f=0;y<3;y++) + for(x=0;x<10;x++,f++) + if (alien[f].alive) + { + if (y%2) + { + if ((alien[f].sx+=10)>3599) + alien[f].sx-=3600; + } + else + { + if ((alien[f].sx-=10)<0) + alien[f].sx+=3600; + } + + SinCos(WINW/2,WINH/2,alien[f].sx,alien[f].sy*2, + alien[f].sy/2,&alien[f].x,&alien[f].y); + } + + break; + + case 3: /* CARNIVAL */ + for(f=0;f<no_aliens;f++) + if (alien[f].alive) + if ((alien[f].x+=(y+1))>=WINW) + alien[f].x-=WINW+SPRW; + + break; + + case 4: /* FLEET WAVE 1 */ + break; + + case 5: /* BOUNCY */ + for(f=0;f<no_aliens;f++) + if (alien[f].alive) + { + alien[f].x+=alien[f].sx; + if ((alien[f].x<=0)||(alien[f].x>=WINW)) + alien[f].sx=-alien[f].sx; + + alien[f].y+=alien[f].sy; + if ((alien[f].y<=0)||(alien[f].y>=SHIPY)) + alien[f].sy=-alien[f].sy; + } + break; + + case 6: /* THE COLLECTIVE 1 */ + for(f=0;f<no_aliens;f++) + if (alien[f].alive) + if (spr[GALAX1]->data[alien[f].sy][alien[f].sx]!=BLACK) + { + alien[f].x=WINW/2-(SPRW+2)*4+alien[f].sx*(SPRW+2); + alien[f].y=WINH/2-(SPRH+2)*4+alien[f].sy*(SPRH+2); + } + else + { + alien[f].x=-100; + alien[f].y=SHIPY; + } + + break; + + case 7: /* THE COLLECTIVE 2 */ + for(f=0;f<no_aliens;f++) + if (alien[f].alive) + if (spr[GALAX2]->data[alien[f].sy][alien[f].sx]!=BLACK) + { + alien[f].x=WINW/2-(SPRW+2)*4+alien[f].sx*(SPRW+2); + alien[f].y=WINH/2-(SPRH+2)*4+alien[f].sy*(SPRH+2); + } + else + { + alien[f].x=-100; + alien[f].y=SHIPY; + } + + break; + + case 8: /* THE COLLECTIVE 3 */ + for(f=0;f<no_aliens;f++) + if (alien[f].alive) + if (spr[GALAX3]->data[alien[f].sy][alien[f].sx]!=BLACK) + { + alien[f].x=WINW/2-(SPRW+2)*4+alien[f].sx*(SPRW+2); + alien[f].y=WINH/2-(SPRH+2)*4+alien[f].sy*(SPRH+2); + } + else + { + alien[f].x=-100; + alien[f].y=SHIPY; + } + + break; + + case 9: /* FLEET WAVE 2 */ + for(y=f=0;y<3;y++) + for(x=0;x<20;x++,f++) + if (alien[f].alive) + if (y%2) + { + if ((alien[f].x+=(y+1))>=WINW) + alien[f].x-=WINW+SPRW; + } + else + { + if ((alien[f].x-=(y+1))<=-SPRW) + alien[f].x+=WINW+SPRW; + } + + break; + + case 10: /* ALIEN MOTHERBRAIN */ + for(f=0;f<44;f++) + if (alien[f].alive) + { + SinCos(WINW/2,WINH/2,f*81,alien[f].sx, + alien[f].sx,&alien[f].x,&alien[f].y); + + alien[f].sx+=alien[f].sy; + + if ((alien[f].sx<10)||(alien[f].sx>WINW/3)) + { + alien[f].sy=-alien[f].sy; + alien[f].sx+=alien[f].sy; + } + } + break; + + default: + printf("undefined level %d?\n",levelndx); + exit(1); + } +} + + +CheckAlienShot(a) +Alien *a; + +{ + if ((levdata[levelndx].shot_type==NOSHOT)||(dead)) + return; + + if (a->shot.inuse) + return; + + if (RND(200)<(1+level)) + { + a->shot.inuse=True; + + a->shot.x=ITOF(a->x); + a->shot.y=a->y+SPRH; + + switch (levdata[levelndx].shot_type) + { + case VISHOT: + a->shot.yi=4+RND(4); + break; + default: + a->shot.yi=3; + break; + } + + switch (levdata[levelndx].shot_type) + { + case SISHOT: + a->shot.xi=0; + break; + + case VISHOT: + if (shipx<a->x) + a->shot.xi=-16*a->shot.yi; + else if (shipx<a->x) + a->shot.xi=16*a->shot.yi; + else + a->shot.xi=0; + break; + + case GASHOT: + if (shipx<a->x) + a->shot.xi=-64; + else if (shipx>a->x) + a->shot.xi=64; + else + a->shot.xi=0; + break; + + default: + a->shot.xi=0; + break; + } + } +} + + +DrawAndKillAliens() + +{ + CollData coll; + int f,r; + + aliendead=True; + + for(f=0;f<no_aliens;f++) + { + if (alien[f].alive) + { + aliendead=False; + + CheckAlienShot(&alien[f]); + + Sprite(alien[f].type,alien[f].x,alien[f].y,&coll,CALIEN); + + if (BulletsInUse()) + if (coll.no) + for(r=0;r<coll.no;r++) + if (coll.data[r]&CUBULLM) + { + NewExplosion(alien[f].x+SPRW/2,alien[f].y+SPRH/2,1); + + alien[f].alive=False; + + switch(alien[f].type) + { + case GALAX1: + score+=10; + break; + case GALAX2: + score+=20; + break; + case GALAX3: + score+=40; + break; + case ALIENUFO: + case ENTITY1: + score+=50; + break; + } + + DeleteBullet(coll.data[r]-CUBULLM); + hit++; + r=coll.no+1; + } + } + + if (alien[f].shot.inuse) + { + aliendead=False; + + alien[f].shot.x+=alien[f].shot.xi; + alien[f].shot.y+=alien[f].shot.yi; + + if (alien[f].shot.y>WINH) + alien[f].shot.inuse=False; + else + Sprite(ABULLET,FTOI(alien[f].shot.x),alien[f].shot.y, + &coll,CABULL); + } + } +} |