Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Shoot, a game by Donkeysoft MMXII Written for
- * the Sinclair ZX81, requires 16K of RAM to run.
- * Public beta V0.000000000000 */
- #include <zx81.h>
- #include <stdio.h>
- #include <input.h>
- // Definitions for ROM calls:
- #define POKEY 0x4005
- #define PRINTAT 0x08f5
- #define PRINT 0x10
- // To save a whole other conversion routine, it'd just be easier
- // to define the character codes for the ZX81's "graphical" chars,
- // especially as these are not available on the PC:
- #define BORDER 0x80
- #define INNER 0x08
- #define PLAYERL 0x12
- #define PLAYERT 0x3b
- // Function prototypes:
- // Here is our main entry:
- static void main(void);
- // This will display the title screen:
- static void title(void);
- // This function will scroll the text in our scrolly:
- static void scroll(void);
- // This clears the play area rather than clearing the screen and
- // resetting the DFILE:
- static void clearcanvas(void);
- // This will update the score and lives display:
- static void scoreandlives(void);
- // This is where most of the game mechanics are:
- static void play(void);
- // This updates the movements of the player on the vertical plane:
- static void playerposv(void);
- // Same as above but for the horizontal plane:
- static void playerposh(void);
- // This places our wormholes onto the screen:
- static void wormholes(void);
- // This allows upto four shots moving vertically:
- static void shootvert(void);
- // As above, but shots moving horizontally:
- static void shoothorz(void);
- // This starts the convoys:
- static void startwave(void);
- // and this will start each bomb attack:
- static void startattack(void);
- // Will check if the bomb has hit the drones:
- static void checkbomb(void);
- // This will check for inverse conditions
- static void checkinverse(char x, char y);
- // This will check if any of the convoys have been hit:
- static void checkhit(char a, char z);
- // Checks for high score, and if so, the player gets
- // to enter their initials for prosperity:
- static void highscorecheck(int c);
- // This places our character according to X and Y position:
- static void printat(char x, char y);
- // This will output our character to the screen:
- static void print(char c);
- // This allows a character to be printed inverse or not:
- static void printc(char ch, uchar inverse);
- // Global variables:
- static uchar x=0;
- static uchar y=0;
- // Level placements of wormholes:
- static char wormstart[]=
- {
- 9,9,9,8,8,8,7,9,7,8,8,7,6,6,6,6,6,5,5,5
- };
- static char wormend[]=
- {
- 8,16,7,16,7,15,7,14,7,13,8,12,9,11,10,10,11,9,12,8
- };
- // This will identify our ship, inside the game code, when
- // the correct conditions are met, it will either be a space
- // rogue O or a legal trader *
- static char ship[]=
- {
- 0,0,0,0
- };
- // Using simple normalisation principles, this will track the
- // each ship as it moves on the X and Y plane:
- static char ex[]=
- {
- 0,0,0,0
- };
- static char ey[]=
- {
- 0,0,0,0
- };
- // Bomb's X and Y position, bombs are zeros on the display:
- static char bx[]=
- {
- 0,0,0,0
- };
- static char by[]=
- {
- 0,0,0,0
- };
- // Old x and y position of bombs, again using simple normalisation
- // principles, for the love of Codd:
- static char tx[]=
- {
- 0,0,0,0
- };
- static char ty[]=
- {
- 0,0,0,0
- };
- // And here's our bomb, so if not null essentially (as it's a zero
- // char on the display, and not a number) then the bomb exists:
- static char bomb[]=
- {
- 0,0,0,0
- };
- // This is the target for each bomb, the code will keep track each
- // time the bomb movement code is called:
- static char targ[]=
- {
- 0,0,0,0
- };
- // This will store which target for each bomb, ie, if 0 then the
- // top drone and if 1 then the bottom drone, remembering whilst
- // the bomb is true (not null), if that makes sense:
- static char target=0;
- // Boolean for starting the attack:
- static char attackstart=0;
- // This will increase our level counter, once all of the levels
- // have cycled through, it becomes -2 to cycle back through each
- // level:
- static char levelchange=2;
- // This says that the convoys have started:
- static char wavecounter=0;
- // This keeps track on how many attacks have happened:
- static char attackcounter=0;
- // Here is our internal counter, which is increased for each pass of
- // the main game engine room, ie, while not dead:
- static char counter=1;
- // This is the speed of the wave generator:
- static char speed=47;
- // And here is the speed of the bomb generator:
- static char bombspeed=48;
- // Here is how often the waves are updated:
- static char wavetimer=13;
- // And here is how often the bombs are updated:
- static char attacktimer=14;
- // A boolean to say whether or not the wave has started:
- static char wavestart=0;
- // Skill level: Higher means more space between the worm holes:
- static char skill=9;
- // Level number:
- static char level=0;
- // This is used as a boolean to say that a new level is ready:
- static char newlevel=0;
- // Current highest score - char position 3, 4, and 5 will be changed
- // if the high score is beaten and 7, 8, 9 and 10 will be for the
- // updated score:
- static char hiscore[]="HI MUM 0015";
- // Player's X and Y position:
- static char x0=16;
- static char y0=11;
- // Player's old X and Y position (set to zero for now):
- static char x1=0;
- static char y1=0;
- static char ch=0;
- // Reusable counter:
- static char i=0;
- static int c=0;
- // Used for reading the keyboard:
- static uchar key=0;
- // used for determining maximum number of horizontal
- // and vertical shots:
- static char vert=0;
- static char shootv=0;
- static char horz=0;
- static char shooth=0;
- // These arrays will keep track of each bullet on the X and Y plane:
- static char shootvpos[]=
- {
- 0,0,0,0
- };
- static char downpos[]=
- {
- 3,3,3,3
- };
- static char shoothpos[]=
- {
- 0,0,0,0
- };
- static char acrosspos[]=
- {
- 3,3,3,3
- };
- // Dead or alive boolean:
- static char dead=0;
- // Inverse text boolean:
- static uchar inverse=0;
- // Title texts:
- static uchar donkey[]="DONKEYSOFT MMXII";
- static uchar presents[]="PRESENTS";
- static uchar gamename[]="SHOOT.";
- static uchar lrkeys[]="5, 8 MOVES LEFT AND RIGHT";
- static uchar udkeys[]="6, 7 MOVES UP AND DOWN";
- static uchar firekeys[]="3, 0 SHOOTS";
- static uchar scrolly[]="..........IN JANUARY 1981, AN ALIEN RACE CRASH-LANDED NEAR CAMBRIDGE. REQUIRING ADVANCED TECHNOLOGIES TO FIX THEIR NAVIGATIONAL COMPUTER, THE ALIENS SECRETLY MET WITH SIR CLIVE SINCLAIR, WHO OFFERED THEM A FEW ZX81 PROTOTYPES IN EXCHANGE FOR THOUSANDS OF SALVAGED BUT DODGY RAM CHIPS. THE TRADE WAS MADE AND THE ALIENS LEFT WITH THE NEW SINCLAIR SUPER COMPUTERS GUIDING THEM HOME. THE ZX81S WERE THEN USED BY THE ALIENS TO CONTROL THEIR OUTER DEFENCES, GUARDING THE WORMHOLES NEAREST TO THEIR HOME AGAINST THEIR FOES AND PIRATE TRADERS. CONTROL THE DRONES TO OBLITERATE THE INVADERS. DO NOT DESTROY * AS THESE ARE LEGAL TRADERS. SHOOT (C) DONKEYSOFT MMXII..........$";
- // Displayed if there's a new high score:
- static uchar newhighscore[]="ENTER INITIALS:";
- // Default high score:
- static int highscore=15;
- // Booleans used to tell the game to update the score and lives:
- static char scoreupdate=1;
- static char points=0;
- static char livesupdate=1;
- // Other messages on the display panel:
- static uchar lives[]="DRONES:";
- static uchar score[]="SCORE:";
- static char sc[]="0000";
- // I've been generous with the lives, but this could be changed to
- // fewer:
- static uchar livesremaining=7;
- // Main function:
- void main()
- {
- if(!dead)
- {
- // This might be helpful for machines >16K - easy enough
- // to comment out or remove:
- #asm
- PUSH HL
- LD HL,(POKEY)
- LD A,$ff
- LD (HL),A
- POP HL
- #endasm
- // This will clear the screen using the z88dk default:
- printk("%c ",12);
- // Prints the border:
- for(i=0;i<29;i=i+1)
- {
- printat(i,0);
- print(BORDER);
- if(i>=2 && i<=26)
- {
- printat(i,1);
- print(INNER);
- printat(i,20);
- print(INNER);
- printat(i,18);
- print(INNER);
- }
- if(i<21)
- {
- printat(0,i);
- print(BORDER);
- print(INNER);
- printat(27,i);
- print(INNER);
- print(BORDER);
- }
- printat(i,21);
- print(BORDER);
- }
- }
- // If the game has been played more than once then everything
- // will need to be reset:
- if(dead)
- {
- for(i=0;i<4;i=i+1)
- {
- // Clears all objects in the game world
- ship[i]=0; ex[i]=0; ey[i]=0;
- bx[i]=0; by[i]=0; bomb[i]=0;
- // Restores default positions:
- shootvpos[i]=0;
- downpos[i]=3;
- shoothpos[i]=0;
- acrosspos[i]=3;
- // Resets the score:
- sc[i]='0';
- }
- // Remaining variables reset:
- wavecounter=0;
- attackcounter=0;
- shooth=0;
- horz=0;
- shootv=0;
- vert=0;
- speed=47;
- bombspeed=48;
- wavetimer=13;
- attacktimer=14;
- wavestart=0;
- level=0;
- x0=16;
- y0=11;
- scoreupdate=1;
- livesupdate=1;
- livesremaining=7;
- skill=9;
- dead=0;
- }
- title();
- }
- static void title()
- {
- // This will output the title screen messages:
- for(i=0;i<25;i=i+1)
- {
- printat(2+i,10);
- printc(lrkeys[i],0);
- if(i<17)
- {
- printat(6+i,4);
- printc(donkey[i],0);
- printat(5+i,13);
- print(0);
- }
- if(i<8)
- {
- printat(10+i,6);
- printc(presents[i],0);
- }
- if(i<6)
- {
- printat(11+i,8);
- printc(gamename[i],1);
- }
- if(i<23)
- {
- printat(3+i,11);
- printc(udkeys[i],0);
- }
- if(i<11)
- {
- printat(8+i,12);
- printc(firekeys[i],0);
- printat(8+i,14);
- printc(hiscore[i],1);
- }
- }
- // This is a conditional loop which will end when a key is pressed:
- while(!key)
- {
- printat(2,19);
- // Gets last key press and stores it into key variable:
- key=in_Inkey();
- // Prints out the first 28 chars of the scrolly text using
- // inversed characters:
- for(i=0;i<25;i=i+1)
- {
- printc(scrolly[i],1);
- }
- // Moves the message one char to the 2
- scroll();
- }
- // Clears the playfield ready to start the game:
- clearcanvas();
- }
- void scroll()
- {
- // Sets counter to zero
- c=0;
- // The buffer will preserve the first char otherwise the
- // scrolling won't wrap around
- ch=scrolly[c];
- // Loop will happen whilst the terminator hasn't been reached:
- while(scrolly[c]!='$')
- {
- // Moves each character one element to the 2:
- scrolly[c]=scrolly[c+1];
- // Increase our counter
- c=c+1;
- }
- // Puts the old first character from the start to the end so
- // it wraps around:
- scrolly[c-1]=ch;
- // Checks to see if the terminator has been over-written, if not
- // then it's restored, but the code is fine so commented out:
- /**if(scrolly[c]!='$')
- {
- scrolly[c]='$';
- }*/
- }
- void clearcanvas()
- {
- for(i=17;i>1;i=i-1)
- {
- for(x=26;x>1;x=x-1)
- {
- printat(x,i);
- print(0);
- }
- }
- // Because this function is called once the player is dead
- // we don't want the following to happen after this condition:
- if(dead)
- {
- key=0;
- return;
- }
- // This adds to the skill level dependant on what key you've
- // pressed:
- skill=skill+(key%6);
- wavetimer=wavetimer+(key%3);
- attacktimer=attacktimer+(key%3);
- // Blanks out part of the status bar:
- printat(13,19);
- print(BORDER); print(BORDER);
- scoreandlives();
- play();
- }
- // This will update our score and lives display:
- void scoreandlives()
- {
- for(i=0;i<7;i=i+1)
- {
- printat(13+i,19);
- printc(lives[i],1);
- if(i<6)
- {
- printat(2+i,19);
- printc(score[i],1);
- }
- }
- /**if (sc[3]=='8' && sc[2]=='9' && sc[1]=='9' && sc[0]=='9')
- {
- ;; // This will eventually be our winning code.
- }*/
- // Logic to increase the score, as we're not using numbers, but
- // characters, then we need to work out which chars in the array
- // need updating:
- while(points!=0)
- {
- if(sc[1]=='9' && sc[2]=='9' && sc[3]=='9')
- {
- sc[3]=sc[3]+1;
- sc[2]=sc[2]+1;
- sc[1]=sc[1]+1;
- sc[0]=sc[0]+1;
- }
- else
- if(sc[2]=='9' && sc[3]=='9')
- {
- sc[3]=sc[3]+1;
- sc[2]=sc[2]+1;
- sc[1]=sc[1]+1;
- }
- else
- if(sc[3]=='9')
- {
- sc[3]=sc[3]+1;
- sc[2]=sc[2]+1;
- }
- else
- {
- sc[3]=sc[3]+1;
- }
- // This does a wrap-around so that the char doesn't continue
- // past 9:
- for(i=0;i<4;i=i+1)
- {
- if(sc[i]>'9')
- {
- sc[i]='0';
- }
- }
- // Converts the score to an integer number:
- c=(1000*(sc[0]-48))+(100*(sc[1]-48))+(10*(sc[2]-48))+(sc[3]-48);
- // Increases the level for every 12 points scored:
- if(c%12==0)
- {
- // Clears the old worm holes before increasing the level
- // and so displaying the new worm hole positions:
- printat(wormstart[level],wormstart[level+1]);
- print(0);
- printat(wormend[level]+skill,wormend[level+1]);
- print(0);
- level=level+levelchange;
- // Works out whether to increase the level count or
- // decrease it, to keep in the bounds of the array:
- if(level>17)
- {
- levelchange=-2;
- }
- if(level<1)
- {
- levelchange=2;
- }
- // These could be changed to increase the rate at which
- // the bombs and convoys are unleashed:
- if(speed>20)
- {
- speed=speed-1;
- bombspeed=bombspeed-1;
- }
- // This says how often to update the display to move each
- // of the elements on the screen:
- if(wavetimer>2)
- {
- wavetimer=wavetimer-1;
- attacktimer=attacktimer-1;
- }
- // Places new worm holes:
- wormholes();
- }
- // This is not decreasing the points, what it's doing is
- // decreasing the boolean, so if points=2 this will be called
- // twice:
- points=points-1;
- }
- // This will update the score display:
- while(scoreupdate)
- {
- // Prints score:
- printat(8,19);
- for(i=0;i<4;i=i+1)
- {
- printc(sc[i],1);
- }
- print(BORDER);
- // Resets the boolean:
- scoreupdate=scoreupdate-1;
- }
- // This will update the lives display:
- while(livesupdate)
- {
- printat(20,19);
- // Error checking as livesremaining is a char, so 0-1=255,
- // which is greater than 7, but is -1 twos compliment:
- if(livesremaining<=0 || livesremaining>7)
- {
- dead=1;
- print(BORDER);
- livesremaining=0;
- }
- // This displays the number of lives remaining:
- for(i=livesremaining;i!=0;i=i-1)
- {
- printc('X',1);
- }
- // Prints an inversed space to clear off any lives
- // that have been lost:
- if(livesremaining<7 && !dead)
- {
- for(i=7-livesremaining;i!=0;i=i-1)
- {
- print(BORDER);
- }
- }
- // Resets the boolean:
- livesupdate=livesupdate-1;
- }
- }
- // Most of the game engine:
- void play()
- {
- // This stops spaces been drawn in odd places:
- x1=x0-1; y1=y0-1;
- // Displays player's position:
- playerposv();
- playerposh();
- // Displays wormholes:
- wormholes();
- // All of this happens while not dead:
- while(!dead)
- {
- key=in_Inkey();
- // This allows four shots on the horizontal plane:
- if(key=='0' && horz<4)
- {
- shooth=shooth+1;
- acrosspos[horz]=3;
- shoothpos[horz]=y0;
- horz=horz+1;
- }
- // 7 and 6 is up and down:
- if(key=='7' && y0>3)
- {
- y1=y0; y0=y0-1;
- playerposv();
- }
- if(key=='6' && y0<17)
- {
- y1=y0; y0=y0+1;
- playerposv();
- }
- // 5 and 8 is left and right:
- if(key=='5' && x0>3)
- {
- x1=x0; x0=x0-1;
- playerposh();
- }
- if(key=='8' && x0<26)
- {
- x1=x0; x0=x0+1;
- playerposh();
- }
- // This is the other fire button:
- if(key=='3' && vert<4)
- {
- downpos[vert]=x0;
- shootvpos[vert]=3;
- vert=vert+1;
- shootv=1;
- }
- // This works out which ship to display on the convoys,
- // so 0 is a pirate and 1 is a legal trader:
- i=(x0+y0+wavecounter)%2;
- // If counter has counted up to speed then the convoys
- // will start:
- if(counter%speed==0 && wavecounter<4)
- {
- ex[wavecounter]=wormstart[level];
- ey[wavecounter]=wormstart[level+1];
- // Sets convoys:
- if(i==0)
- {
- ship[wavecounter]='O';
- }
- else
- {
- ship[wavecounter]='*';
- }
- // Increases wave counter and tells the program to
- // call the wave function:
- wavecounter=wavecounter+1;
- wavestart=1;
- }
- // Will start the bombs from level 1 onwards (starting at
- // level zero, of course):
- if(level && attackcounter<4 && counter%bombspeed==0)
- {
- attackstart=1;
- bomb[attackcounter]='0';
- if(i==1)
- {
- bx[attackcounter]=wormstart[level];
- by[attackcounter]=wormstart[level+1];
- }
- else
- {
- bx[attackcounter]=wormend[level]+skill;
- by[attackcounter]=wormend[level+1];
- }
- // We could re-use the i variable above to decide
- // which of the drones is being targetted by the bomb:
- target=((x0+y0+attackcounter)%2);
- targ[attackcounter]=target;
- attackcounter=attackcounter+1;
- }
- // Increases internal counter:
- counter=counter+1;
- // Calls functions:
- if(wavestart && counter%wavetimer==0)
- {
- startwave();
- }
- if(attackstart && counter%attacktimer==0)
- {
- startattack();
- checkbomb();
- }
- if(scoreupdate || livesupdate)
- {
- scoreandlives();
- }
- if(shooth)
- {
- shoothorz();
- }
- // This will slow things down whilst the screen isn't so busy
- // so that the player's movement do not significantly increase:
- else
- {
- in_Wait(6);
- }
- if(shootv)
- {
- shootvert();
- }
- else
- {
- in_Wait(6);
- }
- if(!wavecounter)
- {
- in_Wait(6);
- }
- if(!attackcounter)
- {
- in_Wait(6);
- }
- // This simply stops the auto-fire thingy if one of the fire
- // buttons has been depressed for a fraction of a second too
- // long:
- if(key=='0' || key=='3')
- {
- key=in_Inkey();
- key=in_Inkey();
- key=0;
- }
- }
- // Okay, so the player is dead, let's clear the canvas before
- // working out the final score, checking against the current
- // high score and then returning to the main routine:
- clearcanvas();
- c=(1000*(sc[0]-48))+(100*(sc[1]-48))+(10*(sc[2]-48))+(sc[3]-48);
- highscorecheck(c);
- main();
- }
- // Updates player's vertical position:
- void playerposv()
- {
- printat(2,y0);
- print(PLAYERL);
- printat(2,y1);
- print(0);
- }
- // Updates the player's horizontal position:
- void playerposh()
- {
- printat(x0,2);
- print(PLAYERT);
- printat(x1,2);
- print(0);
- }
- // Display's the worm holes:
- void wormholes()
- {
- printat(wormstart[level],wormstart[level+1]);
- print(BORDER);
- printat(wormend[level]+skill,wormend[level+1]);
- print(BORDER);
- }
- // This will happen if the player has fired a shot on the vertical
- // plane:
- void shootvert()
- {
- for(i=0; i<vert; i=i+1)
- {
- // To speed things up a bit, the boundary of the bullet if
- // the Y position of the worm hole:
- if(shootvpos[i]<wormend[level+1]+1)
- {
- // Check if the bullet is passing over the worm hole:
- checkinverse(downpos[i],shootvpos[i]);
- // Displays the bullets:
- printat(downpos[i],shootvpos[i]);
- printc('\"',inverse);
- }
- // Take a copy of the old bullet location
- x=downpos[i]; y=shootvpos[i]-1;
- // This checks if one of the convoys has been hit:
- checkhit(downpos[i],shootvpos[i]);
- if(ch)
- {
- // ch is true if a bullet has hit something, so it
- // sets the vertical position out of bounds:
- shootvpos[i]=wormend[level+1]+1;
- }
- // Clears bullet:
- if(y>2 && y<=wormend[level+1])
- {
- checkinverse(x,y);
- printat(x,y);
- printc(0,inverse);
- }
- // Increases position of bullet:
- if(shootvpos[i]<=wormend[level+1]+1)
- {
- shootvpos[i]=shootvpos[i]+1;
- }
- }
- // Checks to see if all of the bullets have been spent:
- c=wormend[level+1]+1;
- if(vert==4 && shootvpos[0]>c && shootvpos[1]>c && shootvpos[2]>c && shootvpos[3]>c)
- {
- vert=0; shootv=0;
- }
- }
- // And as above but for the horizontal bullets:
- void shoothorz()
- {
- for(i=0; i<horz; i=i+1)
- {
- if(acrosspos[i]<wormend[level]+skill+1)
- {
- checkinverse(acrosspos[i],shoothpos[i]);
- printat(acrosspos[i],shoothpos[i]);
- printc('-',inverse);
- }
- // Take a copy of the old bullet location
- x=acrosspos[i]-1; y=shoothpos[i];
- // This checks if one of the convoy has been hit:
- checkhit(acrosspos[i],shoothpos[i]);
- if(ch)
- {
- acrosspos[i]=wormend[level]+skill+2;
- }
- if(x>2 && x<=wormend[level]+skill)
- {
- checkinverse(x,y);
- printat(x,y);
- printc(0,inverse);
- }
- if(acrosspos[i]<=wormend[level]+skill+1)
- {
- acrosspos[i]=acrosspos[i]+1;
- }
- }
- c=wormend[level]+skill+1;
- if(horz==4 && acrosspos[0]>c && acrosspos[1]>c && acrosspos[2]>c && acrosspos[3]>c)
- {
- horz=0; shooth=0;
- }
- }
- // This starts the convoys:
- void startwave()
- {
- for(i=0;i<wavecounter;i=i+1)
- {
- checkinverse(ex[i],ey[i]);
- if(ex[i]==wormend[level]+skill && ey[i]==wormend[level+1])
- {
- printat(ex[i],ey[i]);
- printc(ship[i],inverse);
- ship[i]=0;
- }
- printat(ex[i],ey[i]);
- printc(ship[i],inverse);
- c=((counter+ship[i])%8);
- // Old position of the enemy:
- x=ex[i]; y=ey[i];
- if((c==4 || c==3 || c==7) && ex[i]<wormend[level]+skill && ship[i]!=0)
- {
- ex[i]=ex[i]+1;
- }
- else
- if((c==2 || c==5) && ey[i]<wormend[level+1] && ship[i]!=0)
- {
- ey[i]=ey[i]+1;
- }
- else
- if((c==0 || c==1 || c==6) && ex[i]<wormend[level]+skill && ey[i]<wormend[level+1] && ship[i]!=0)
- {
- ex[i]=ex[i]+1;
- ey[i]=ey[i]+1;
- }
- else
- if(ex[i]<wormend[level]+skill && ship[i]!=0)
- {
- ex[i]=ex[i]+1;
- }
- else
- if(ey[i]<wormend[level+1]-1 && ship[i]!=0)
- {
- ey[i]=ey[i]+1;
- }
- if(ex[i]>wormend[level]+skill || ey[i]>wormend[level+1])
- {
- ex[i]=ex[i]-1;
- ey[i]=ey[i]-1;
- }
- for(c=0;c<wavecounter;c=c+1)
- {
- if(ex[i]==ex[c] && ey[i]==ey[c] && i!=c && ship[c]!=0)
- {
- ex[i]=x; ey[i]=y;
- }
- }
- checkinverse(x,y);
- if(x!=ex[i] || y!=ey[i])
- {
- printat(x,y);
- printc(0,inverse);
- }
- if(ship[i])
- {
- checkinverse(ex[i],ey[i]);
- printat(ex[i],ey[i]);
- printc(ship[i],inverse);
- }
- }
- if(!ship[0] && !ship[1] && !ship[2] && !ship[3])
- {
- wavecounter=0;
- }
- }
- // This starts the bomb attacks:
- void startattack()
- {
- for(i=0;i<attackcounter;i=i+1)
- {
- // This will update each bomb target every
- // time the function is called:
- if(targ[i])
- {
- tx[i]=x0; ty[i]=2;
- }
- else
- {
- tx[i]=2; ty[i]=y0;
- }
- checkinverse(bx[i],by[i]);
- // Checks if bomb exists (ie, not zero)
- if(bomb[i]!=0)
- {
- printat(bx[i],by[i]);
- printc(bomb[i],inverse);
- c=((counter+level+x0+y0)%12);
- // Old position of the enemy:
- x=bx[i]; y=by[i];
- if(targ[i]==0 && bomb[i]!=0)
- {
- if(c>=6 && by[i]<ty[i])
- {
- by[i]=by[i]+1;
- }
- else
- if(c<6 && by[i]>ty[i])
- {
- by[i]=by[i]-1;
- }
- if(bx[i]>2 && c==0)
- {
- bx[i]=bx[i]-1;
- }
- }
- if(targ[i]==1 && bomb[i]!=0)
- {
- if(c>=6 && bx[i]<tx[i])
- {
- bx[i]=bx[i]+1;
- }
- else
- if(bx[i]>tx[i] && c<6)
- {
- bx[i]=bx[i]-1;
- }
- if(by[i]>2 && c==0)
- {
- by[i]=by[i]-1;
- }
- }
- checkinverse(x,y);
- if(x!=bx[i] || y!=by[i])
- {
- printat(x,y);
- printc(0,inverse);
- }
- if(bomb[i])
- {
- checkinverse(bx[i],by[i]);
- printat(bx[i],by[i]);
- printc(bomb[i],inverse);
- }
- }
- }
- if(!bomb[0] && !bomb[1] && !bomb[2] && !bomb[3])
- {
- attackcounter=0;
- }
- }
- // This will check to see if either of the drones has been hit:
- void checkbomb()
- {
- for(c=0;c<=attackcounter;c=c+1)
- {
- for(i=0;i<=attackcounter;i=i+1)
- {
- if(bx[c]==tx[i] && by[c]==ty[i] && bomb[c])
- {
- bomb[c]=0;
- livesupdate=livesupdate+1;
- livesremaining=livesremaining-1;
- playerposv();
- playerposh();
- }
- }
- }
- }
- // This will check the position to see X or Y have passed over one
- // of the worm holes:
- void checkinverse(char x, char y)
- {
- if((x==wormstart[level] && y==wormstart[level+1]) || (x==wormend[level]+skill && y==wormend[level+1]))
- {
- inverse=1;
- }
- else
- {
- inverse=0;
- }
- }
- // This checks if the bullets have hit any objects on the screen:
- void checkhit(char a, char z)
- {
- ch=0;
- for(c=0;c<=4;c=c+1)
- {
- if((a==ex[c] && z==ey[c] && ship[c]=='O') || (a==bx[c] && z==by[c] && bomb[c]=='0'))
- {
- if(a==ex[c] && z==ey[c])
- {
- ship[c]=0;
- }
- else
- {
- bomb[c]=0;
- }
- printat(a,z);
- printc(' ',inverse);
- scoreupdate=scoreupdate+1;
- points=points+1;
- ch=1;
- }
- if(a==ex[c] && z==ey[c] && ship[c]=='*')
- {
- ship[c]=0;
- printat(a,z);
- printc(' ',inverse);
- livesupdate=livesupdate+1;
- livesremaining=livesremaining-1;
- ch=1;
- }
- }
- }
- // Checks the score:
- void highscorecheck(int c)
- {
- if(c<highscore+1)
- {
- return;
- }
- highscore=c;
- for(i=0;i<15;i=i+1)
- {
- if(i<4)
- {
- hiscore[7+i]=sc[i];
- }
- printat(6+i,13);
- printc(newhighscore[i],0);
- if(i<11)
- {
- printat(8+i,14);
- printc(hiscore[i],1);
- }
- }
- c=0;
- while(c<3)
- {
- key=in_Inkey();
- if(key=='5' || key=='6')
- {
- hiscore[3+c]=hiscore[3+c]-1;
- }
- if(key=='7' || key=='8')
- {
- hiscore[3+c]=hiscore[3+c]+1;
- }
- if(key=='3' || key=='0')
- {
- c=c+1;
- }
- if(hiscore[3+c]<'A' && c!=3)
- {
- hiscore[3+c]='Z';
- }
- if(hiscore[3+c]>'Z' && c!=3)
- {
- hiscore[3+c]='A';
- }
- in_Wait(48);
- printat(11+c,14);
- printc(hiscore[3+c],1);
- if(key=='3' || key=='0')
- {
- key=in_Inkey();
- in_WaitForKey();
- }
- key=0;
- }
- }
- // This sets the X and Y position of the cursor:
- void printat(char x, char y)
- {
- // Error checking if needed:
- /**if((x<0 || x>31) || (y<0 || y>21))
- {
- printk("OUT OF BOUNDS ERROR ON X/Y POSITION");
- return -1;
- }*/
- #asm
- PUSH BC
- PUSH HL
- LD HL,6
- ADD HL,SP
- LD B,(HL)
- INC HL
- INC HL
- LD C,(HL)
- CALL PRINTAT
- POP HL
- POP BC
- RET
- #endasm
- }
- // This will print out a char, may need conversion if not a valid
- // character code for the ZX81, see below for the conversion:
- void print(char c)
- {
- #asm
- PUSH AF
- PUSH HL
- LD HL,6
- ADD HL,SP
- LD A,(HL)
- RST PRINT
- POP HL
- POP AF
- RET
- #endasm
- }
- // This function does the necessary conversion from the way that
- // strings are stored using the z88dk to something that the ZX81
- // will understand with our simple print(); function above:
- void printc(char ch, uchar inverse)
- {
- // As the char codes are stored in bytes differently from the
- // chr$ codes, and there are different sets too, then there's
- // a lot of working out to do. I've grouped each char as
- // appropriate:
- c=0;
- if(ch>='A' && ch<='Z')
- {
- c=27;
- }
- else
- if(ch>='0' && ch<='9')
- {
- c=20;
- }
- else
- if(ch==' ')
- {
- c=32;
- }
- else
- // 59 is semi-colon
- if(ch==59)
- {
- c=34;
- }
- if(ch=='(' || ch==')')
- {
- c=24;
- }
- else
- // * and .
- if(ch==42 || ch==46)
- {
- c=19;
- }
- else
- if(ch=='+')
- {
- c=22;
- }
- else
- if(ch==',')
- {
- c=18;
- }
- else
- // 45 is minus, 47 is / and 36 is $
- if(ch==45 || ch==47 || ch==36 || ch=='\"')
- {
- c=23;
- }
- else
- // 58 is : and 62 is >
- if(ch==58 || ch==62)
- {
- c=44;
- }
- else
- if(ch=='<' || ch=='=')
- {
- c=41;
- }
- else
- if(ch=='?')
- {
- c=48;
- }
- else
- if(ch=='£')
- {
- c=151;
- }
- /**if(a==0)
- {
- printk("?ILLEGAL CHAR ERROR");
- return;
- }*/
- // Okay for normal and inverse:
- ch=ch-c;
- if(inverse)
- {
- ch=ch+128;
- }
- print(ch);
- }
- // Compile with:
- // zcc +zx81 -startup=2 -create-app -DTEXT -o SHOOT Shoot.c
- // (C) 2012 Donkeysoft
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement