From c4a574a2ed490a9ec77efc1392260ee4305f1fbf Mon Sep 17 00:00:00 2001 From: Ian C Date: Tue, 12 May 2020 21:08:42 +0000 Subject: Builds, just, and runs. --- galax.c | 1888 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1888 insertions(+) create mode 100644 galax.c (limited to 'galax.c') diff --git a/galax.c b/galax.c new file mode 100644 index 0000000..2283765 --- /dev/null +++ b/galax.c @@ -0,0 +1,1888 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#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;fdata[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=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=0)&&(x=0)&&(yno=0; + + for(sy=0;sy=0)&&((y+sy)data[sy][sx]!=BLACKI) + if (((x+sx)>=0)&&((x+sx)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;f10) + 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;f1) + shipx-=2; + + if (keymap[RIGHT]) + if (shipx1)) + 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-1;f--) + if (hisc[f].scorepos;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;fWINW/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;fWINW-SPRW-1)) + flag=True; + } + + if (flag) + { + alienxi=-alienxi; + + for (f=0;fWINH) + alien[f].y-=WINH; + } + + break; + + case 1: /* RUN AWAY */ + for (f=0;f3599) + 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=WINW) + alien[f].x-=WINW+SPRW; + + break; + + case 4: /* FLEET WAVE 1 */ + break; + + case 5: /* BOUNCY */ + for(f=0;f=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;fdata[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;fdata[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;fdata[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 (shipxx) + a->shot.xi=-16*a->shot.yi; + else if (shipxx) + a->shot.xi=16*a->shot.yi; + else + a->shot.xi=0; + break; + + case GASHOT: + if (shipxx) + 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;fWINH) + alien[f].shot.inuse=False; + else + Sprite(ABULLET,FTOI(alien[f].shot.x),alien[f].shot.y, + &coll,CABULL); + } + } +} -- cgit v1.2.3