SHARE
TWEET

Bounce v1.0000000 for the ZX81

Shaun_B Jan 10th, 2012 149 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /** Bouncing ball game by Donkeysoft MMXII
  2.  *  Written for the Sinclair ZX81, requires
  3.  *  16K of RAM to run. Release candidate v1.0000000.
  4.  *  See www.z88dk.org for information about the
  5.  *  zcc compiler. */
  6. #include <zx81.h>
  7. #include <stdio.h>
  8. #include <input.h>
  9. // Definitions for ROM calls:
  10. #define POKEY           0x4005
  11. #define PRINTAT         0x08f5
  12. // The following definitions are used in the print(int a);
  13. // sub-rountine or function or method. Basically, there's
  14. // a zxcursorat(x,y) routine included in the ZX81 library
  15. // but unfortunately this didn't work and crashed my code,
  16. // so I had to make a couple of small assembly routines to
  17. // set the cursor position and also print a character to
  18. // the canvas. #defining stuff seemed the safest way to
  19. // send the necessary character codes to the print()
  20. // function.
  21. #define CLEAR           0x00
  22. #define BALL            0x34
  23. #define BAT                     0x80
  24. #define BORDER          0x08
  25. #define GAMEROW         0x0a
  26. // Defines start of numbers:
  27. #define ZERO            0x1c
  28. // 1 will be ZERO+1 etc...     
  29. // ZX81 chars (BALL is defined):
  30. #define CHARA           0x26
  31. #define _B                      0x27
  32. #define _C                      0x28
  33. #define _D                      0x29
  34. #define _E                      0x2a
  35. #define _F                      0x2b
  36. #define _G                      0x2c
  37. #define _H                      0x2d
  38. #define _I                      0x2e
  39. #define _J                      0x2f
  40. #define _K                      0x30
  41. #define _L                      0x31
  42. #define _M                      0x32
  43. #define _N                      0x33
  44. // O is BALL above ;-)
  45. //#define _O                    0x34
  46. #define _P                      0x35
  47. // Q will be _P+1
  48. #define _R                      0x37
  49. #define _S                      0x38
  50. #define _T                      0x39
  51. #define _U                      0x3a
  52. // V will be U+1
  53. // W will be U+2
  54. // X will be U+3
  55. // Y will be U+4
  56. // Z will be U+5
  57. // Function prototypes:
  58. static void main(void);
  59. static void title(void);
  60. static void waitforkey(void);
  61. static void clearcanvas(void);
  62. static void play(void);
  63. static void printlives(void);
  64. static void increaselevel(void);
  65. static void levelup(void);
  66. static void pausegame(void);
  67. static void restart(void);
  68. static void printat(short x, short y);
  69. static void print(int a);
  70. // x0 is current screen position, x1 is last screen position
  71. // and x2 is direction
  72. static short x0=0;
  73. static short x1=0;
  74. static short x2=1;
  75. // Ditto for y0, y1 and y2
  76. static short y0=0;
  77. static short y1=0;
  78. static short y2=1;
  79. // This is the boundary for our X axis:
  80. // Unused game feature
  81. // static char minx=1;
  82. // static char maxx=30;
  83. // I was thinking of the walls closing in from the sides too
  84. // but decided against it.
  85. // This awards a bonus point on the internal
  86. // scoring if you make the ball go the other way:
  87. static char skills=0;
  88. // If you get it right eight times, you get an extra life,
  89. // so we need to count the number of times:
  90. static char skillcount=0;
  91. // This is used to define the top of the play area:
  92. static char top=1;
  93. // Player position (and at line 20):
  94. static char px=14;
  95. // Re-usable variables:
  96. static short a=0;
  97. static short i=0;
  98. // Number of lives:
  99. static char lives=8;
  100. // Score:
  101. // Score default is set to one because of the way the extra
  102. // lives are rewarded. I could have added && (score!=0) to
  103. // the condition I suppose, but as the scoring system is not
  104. // seen by the player, it doesn't matter either way. Plus
  105. // adding an extra condition might translate into more of the
  106. // CPUs time being eaten away, but probably only by a few cycles...
  107. // This might matter on bigger projects.
  108. static short score=1;
  109. // Check if missed or not:
  110. static char hit=1;
  111. static char once=0;
  112. // Difficulty level, higher is easier:
  113. static char dif=6;
  114. // This is the actual level:
  115. static char level=0;
  116. // 1=dead:
  117. static char dead=0;
  118. // Used to pause game, 1=pause
  119. static char pause=0;
  120. // For key inputs:
  121. static char key=' ';
  122. // For game over message, ie, the players rating when lives
  123. // are spent. Basically, each rating is 5 characters so that
  124. // I can say a=level*5; for(i=0;i<5;i=i+1) { print(fail[i+a]; }:
  125. static int fail[]=
  126. {
  127.         _F, CHARA, _I, _L, BORDER,
  128.         _L, BALL, _S, _E, _R,
  129.         _B, BALL, _U+5, BALL, BORDER,
  130.         _D, BALL, _P, _E, _U+4,
  131.         BORDER, _B, CHARA, _D, BORDER,
  132.         BALL, _K, CHARA, _U+4, BORDER,
  133.         _S, CHARA, _F, _E, BORDER,
  134.         _G, BALL, BALL, _D, BORDER,
  135.         _S, _U+2, _E, _E, _T,
  136.         BORDER, _H, BALL, _T, BORDER,
  137.         _G, _R, _E, CHARA, _T,
  138.         _S, _U, _P, _E, _R,
  139.         BORDER, CHARA, _C, _E, BORDER,
  140.         _C, BALL, BALL, _L, BORDER,
  141.         _S, _T, CHARA, _R, BORDER,
  142.         _C, _R, CHARA, _U+5, _U+4,
  143.         _E, _P, _I, _C, BORDER,
  144.         _K, BALL, BALL, _L, BORDER
  145. };
  146. // Level names - each four characters long for the above reason:
  147. static int levels[]=
  148. {
  149.         _U+5, _U+5, _U+5, _U+5,
  150.         _D, _U, _L, _L,
  151.         _P, _U, _N, _U+4,
  152.         _B, BALL, _R, _E,
  153.         _S, _L, BALL, _U+2,
  154.         _F, _L, CHARA, _T,
  155.         _S, BALL, _M, CHARA,
  156.         _P, _R, _E, _P,
  157.         _S, CHARA, _F, _E,
  158.         _G, BALL, BALL, _D,
  159.         _H, _E, _L, _L,
  160.         BALL, CLEAR, _M, _U,
  161.         _M, CLEAR, _H, _E,
  162.         _L, _L, BALL, CLEAR,
  163.         _R, _U, _B, _U+4,
  164.         CLEAR, _M, CHARA, _E,
  165.         _U+5, _U+3, ZERO+8, ZERO,
  166.         _U+5, _U+3, ZERO+8, ZERO+1
  167.        
  168. };
  169. // Game over message, 13 used for newline and 255 used
  170. // as terminator:
  171. static int gameover[]=
  172. {
  173.         _P, _R, _E, _S, _S, CLEAR, _T, CLEAR, _F, BALL, _R, CLEAR,
  174.         _T, _I, _T, _L, _E, CLEAR, BALL, _R, CLEAR, _T, _H, _E,
  175.         CLEAR, CHARA, _N, _U+4, 13, CLEAR, _K, _E, _U+4,
  176.         CLEAR, _T, BALL, CLEAR, _R, _E, _P, _L, CHARA, _U+4, 255
  177. };
  178. // This condition is set to true when a new level is entered
  179. // so that the program knows to update the display:
  180. static char newlevel=0;
  181. // This will print BALLS at the appropriate place on the screen:
  182. static int balls[]=
  183. {
  184.         _B, CHARA, _L, _L, _S, 255
  185. };
  186. // Title screen message:
  187. static uchar titletext[]="\n\n    --= DONKEYSOFT MMXII =--\n\n            PRESENTS\n\n             BOUNCE\n\n      5 : MOVE BAT LEFT AND\n\n       8 : MOVE BAT RIGHT\n\n         P : PAUSE GAME\n\n        R : UNPAUSE GAME\n\n   PRESS THE ANY KEY TO PLAYZ";
  188. void main(void)
  189. {
  190.         if(!dead)
  191.         {
  192.                 // This bit of code sets the RAM TOP to max
  193.                 // and means it's a bit more stable on machines
  194.                 // with more than 16K - or at least on the emulator:
  195.                 #asm
  196.                 PUSH    HL
  197.                 LD              HL,(POKEY)
  198.                 LD              A,$ff
  199.                 LD              (HL),A
  200.                 POP             HL
  201.                 #endasm
  202.                 // Ensures that the ZX81 is in 'slow' mode:
  203.                 zx_slow();
  204.                 // Prints a nice message welcome message:
  205.                 printk("FAIRLY STABLE VERSION OF BOUNCE THIS IS ABOUT AS GOOD AS I'M    ABLE TO GET THINGS AT THE MOMENTAS I'M USING Z88DK. MOVE THE BATLEFT AND RIGHT TO KEEP IT IN    PLAY. PRESS THE ANY KEY --->>\n\n\nPLEASE LEAVE FEEDBACK ABOUT THISGAME\n\n\n\n(C) JANUARY 2012 DONKEYSOFT\n\nVERSION V1.0000000\n--------------------------------");
  206.                 // Delay in milliseconds:
  207.                 in_Wait(128);
  208.                 // Sets cursor position:
  209.                 printat(0,0);
  210.                 // Waits for keyboard input:
  211.                 in_WaitForKey();
  212.                 // Stores key pressed in the variable key:
  213.                 key=in_Inkey();
  214.                 // Clears the screen:
  215.         }
  216.         // Clears the screen and calls the title(); function, basically
  217.         // a title screen:
  218.         printk("%c ",12);
  219.         title();
  220. }
  221. // This is the main bit of code that does the title screen:
  222. void title(void)
  223. {
  224.         // Sets temporary variables:
  225.         i=0; x0=0; y0=0;
  226.         // Condition prints the title screen character by character:
  227.         while(titletext[i]!='Z')
  228.         {
  229.                 // My printat(x,y); function can be set to a different
  230.                 // position from the stdio printk(); function - so my
  231.                 // print function follows the printat(), whereas for
  232.                 // the version of z88dk I was using, the zxsetcursor(x,y);
  233.                 // didn't work at all:
  234.                 print(CLEAR);
  235.                 // Takes a copy of the last cursor position:
  236.                 x1=x0; y1=y0;
  237.                 // prints the character from the char array:
  238.                 printk("%c",titletext[i]);
  239.                 // prints char at current position:
  240.                 printat(x0,y0);
  241.                 // prints an 'inversed L' character, which will be familair
  242.                 // to ZX81 users:
  243.                 print(177);
  244.                 // If there's a new line then the x0 and y0 needs updating
  245.                 // to trace where the cursor is at on the printk(); function:
  246.                 if(titletext[i]=='\n')
  247.                 {
  248.                         print(CLEAR);
  249.                         y0=y0+1; x0=0;
  250.                 }
  251.                 // increase our index:
  252.                 i=i+1;
  253.                 // increase on our x axis for our char:
  254.                 x0=x0+1;
  255.                 // updates the char position for the print(); function:
  256.                 printat(x1,y1);
  257.         }
  258.         // Finally, print the inversed L when finished:
  259.         print(177);
  260.         // reset the cursor position for the print(); function:
  261.         printat(0,0);
  262.         // The following code will print a border around the screen.
  263.         // It would be faster to 'POKE' the byte directly to the DFile
  264.         // but this isn't stable in z88dk. This is a little slow but
  265.         // it works without crashing:
  266.         for(i=0;i<32;i=i+1)
  267.         {
  268.                 print(BORDER);
  269.         }
  270.         for(i=1;i<22;i=i+1)
  271.         {
  272.                 printat(0,i);
  273.                 print(BORDER);
  274.                 printat(31,i);
  275.                 print(BORDER);
  276.         }
  277.         printat(0,21);
  278.         for(i=0;i<=31;i=i+1)
  279.         {
  280.                 print(BORDER);
  281.         }
  282.         // This now sets up the canvas for play, printing BALLS as the
  283.         // lives indicator and the starting level:
  284.         printat(3,21);
  285.         i=0;
  286.         while(balls[i]!=255)
  287.         {
  288.                 print(balls[i]);
  289.                 i=i+1;
  290.         }
  291.         printat(25,21);
  292.         for(i=0;i<4;i=i+1)
  293.         {
  294.                 print(levels[i]);
  295.         }
  296.         // Again, print's the inversed L but at the end of the title
  297.         // text - not sure if this is entirely necessary, I think
  298.         // it might be for presentation purposes... Comment out the
  299.         // next two lines and see:
  300.         printat(x1,y1);
  301.         print(177);
  302.         // The waitforkey(); function resets the game values and waits
  303.         // for a key to start the game:
  304.         waitforkey();
  305. }
  306. // As above:
  307. void waitforkey()
  308. {
  309.         // Resets everything if the title screen is
  310.         // called again, ie, a game has already been
  311.         // played:
  312.         if(dead)
  313.         {
  314.                 dead=0;
  315.                 top=1;
  316.                 dif=6;
  317.                 lives=8;
  318.                 score=1;
  319.                 px=14;
  320.                 hit=0;
  321.                 once=0;
  322.                 level=0;
  323.                 skills=0;
  324.                 skillcount=0;
  325.         }
  326.         in_WaitForKey();
  327.         // This will check which any key is pressed and set some
  328.         // values before starting the game:
  329.         key=in_Inkey();
  330.         if(key>1 && key<63)
  331.         {
  332.                 x0=4; y0=2;
  333.         }
  334.         else
  335.                 if(key>64 && key<127)
  336.                 {
  337.                         x0=5; y0=3;
  338.                 }
  339.         else
  340.                 if(key>128 && key<191)
  341.                 {
  342.                         x0=6; y0=4;
  343.                 }
  344.         else
  345.                 if(key>192 && key<255)
  346.                 {
  347.                         x0=7; y0=5;
  348.                 }
  349.         else
  350.                 {
  351.                         // This is the secret 'trainer' mode, set if the
  352.                         // player has pressed the correct any key:
  353.                         x0=1; y0=6; lives=12; top=1;
  354.                         levelup();
  355.                         top=top+1;
  356.                         dif=dif+1;
  357.                 }
  358.         // Simple function to clear the canvas:
  359.         clearcanvas();
  360.         // Prints the bottom row, also where the bat resides:
  361.         printat(1,20);
  362.         for(i=0;i<30;i=i+1)
  363.         {
  364.                 print(GAMEROW);
  365.         }
  366.         // Level up adds a new row of bricks:
  367.         levelup();
  368.         // increase the top of screen marker:
  369.         top=top+1;
  370.         // printat(9,21);
  371.         // Calls the main game routine:
  372.         play();
  373. }
  374. void clearcanvas(void)
  375. {
  376.         // Clears the canvas and prints the default number of
  377.         // lives:
  378.         for(i=1;i<=19;i=i+1)
  379.         {
  380.                 for(a=0;a<30;a=a+1)
  381.                 {
  382.                         printat(a+1,i);
  383.                         print(CLEAR);
  384.                 }
  385.         }
  386.         if(lives>0)
  387.         {
  388.                 printlives();
  389.         }
  390. }
  391. void play(void)
  392. {
  393.         // This is simple, do the code while not dead :-)
  394.         while (!dead)
  395.         {
  396.                 // Gets keyboard input and stores it as a variable in
  397.                 // the key var:
  398.                 key=in_Inkey();
  399.                 // Current position of ball:
  400.                 printat(x0,y0);
  401.                 print(BALL);
  402.                 // current position of bat:
  403.                 printat(px,20);
  404.                 // Prints the bat, length is determined by the dif variable:
  405.                 for(i=0;i<dif;i=i+1)
  406.                 {
  407.                         print(BAT);
  408.                 }
  409.                 // Checks for new level condition to update the level code:
  410.                 if(newlevel)
  411.                 {
  412.                         printat(25,21);
  413.                         a=level*4;
  414.                         for(i=0;i<4;i=i+1)
  415.                         {
  416.                                 print(levels[a+i]);
  417.                         }
  418.                         // Resets newlevel condition:
  419.                         newlevel=0;
  420.                 }
  421.                 // Moves bat right on the X axis:
  422.                 if(key=='5' && px>1)
  423.                 {
  424.                         printat(px, 20);
  425.                         px=px-1;
  426.                         printat(px-1, 20);
  427.                         // This clears the bat position without using the space
  428.                         // character, which is 'flickery':
  429.                         if(px==1)
  430.                         {
  431.                                 print(BORDER);
  432.                         }
  433.                         else
  434.                                 if(px>1)
  435.                                 {
  436.                                         print(GAMEROW);
  437.                                 }
  438.                         // Prints current size of bat followed by the character
  439.                         // used on the bottom row:
  440.                         for(i=0;i<dif;i=i+1)
  441.                         {
  442.                                 print(BAT);
  443.                         }
  444.                         print(GAMEROW);
  445.                 }
  446.                 // Moves right on the X axis using the same logic as above
  447.                 // but obviously for right movements:
  448.                 if(key=='8' && px<31-dif)
  449.                 {
  450.                         printat(px, 20);
  451.                         px=px+1;
  452.                         printat(px-1, 20);
  453.                         print(GAMEROW);
  454.                         for(i=0;i<dif;i=i+1)
  455.                         {
  456.                                 print(BAT);
  457.                         }
  458.                         if(px+dif==31)
  459.                         {
  460.                                 print(BORDER);
  461.                         }
  462.                         else
  463.                                 if(px+dif<31)
  464.                                 {
  465.                                         print(GAMEROW);
  466.                                 }
  467.                 }
  468.                 // Secret key, slows down play *but* the player can't move
  469.                 // whilst zero is depressed:
  470.                 if(key=='0')
  471.                 {
  472.                         in_Wait(64);
  473.                 }
  474.                 // Checks for the P key, ie, pause:
  475.                 if(key==80)
  476.                 {
  477.                         printat(x0,y0);
  478.                         print(BALL);
  479.                         pause=1;
  480.                         pausegame();
  481.                 }
  482.                 // Prints position of ball again, I think doing this twice (?)
  483.                 // makes the animation a bit better:
  484.                 printat(x0, y0);
  485.                 print(BALL);
  486.                 // Copies old locations and moves the ball to a new position:
  487.                 x1=x0; y1=y0; x0=x0+x2; y0=y0+y2;
  488.                 //Checks for the boundaries of the play area for the ball and
  489.                 // ensures that it 'bounces' if it hits the boundaries... This
  490.                 // happens even if the player misses the ball so that the play
  491.                 // is constant until all lives have been lost:
  492.                 if (x0<1)
  493.                 {
  494.                         x0=1; x2=1;
  495.                 }
  496.                 if (x0>30)
  497.                 {
  498.                         x0=30; x2=-1;
  499.                 }
  500.                 if (y0<top)
  501.                 {
  502.                         y0=top; y2=1; once=0; hit=0;
  503.                 }
  504.                 if (y0>19)
  505.                 {
  506.                         y0=19; y2=-1;
  507.                 }
  508.                 if (y0==19 && (x0<px || x0>px+dif))
  509.                 {
  510.                         // This simply checks if the player has legally hit the ball
  511.                         // first due to the way the ball bounces around the play
  512.                         // area:
  513.                         if(once)
  514.                         {
  515.                                 hit=1;
  516.                         }
  517.                         else
  518.                                 {
  519.                                         hit=0;
  520.                                 }
  521.                         // So, if the player has not hit the ball...
  522.                         if(!hit)
  523.                         {
  524.                                 lives=lives-1;
  525.                                 hit=1; once=1;
  526.                                 // Prints the number of lives remaining:
  527.                                 printlives();
  528.                                 // Prints the border char to 'clear' the last ball
  529.                                 // so that the player can keep track of the number
  530.                                 // of lives remaining:
  531.                                 print(BORDER);                         
  532.                         }
  533.                         // If lives are spent...
  534.                         if(lives<=0)
  535.                         {
  536.                                 // Once dead is 'true' then all code within this while
  537.                                 // condition stops:
  538.                                 dead=1;
  539.                         }
  540.                 }
  541.                 // Okay, so it might be that the player has hit the ball if the
  542.                 // conditions are true:
  543.                 if (y0==19 && (x0>=px && x0<=px+dif))
  544.                 {
  545.                         // Says that the ball has been legally hit:
  546.                         once=0; hit=1;
  547.                         // Increases internal scoring system:
  548.                         score=score+1;
  549.                         // Checks score against conditions for increasing the
  550.                         // level and also checks for extra lives awarded:
  551.                         increaselevel();
  552.                         // This will allow the ball to be hit in the opposite
  553.                         // direction it's travelling on the X axis as long as
  554.                         // the conditions are true:
  555.                         if((x0==px || x0==px+1) && (x0>=3 && key=='5'))
  556.                         {
  557.                                 // Congratulations, a bonus point is awarded and so
  558.                                 // is a skill point (eventually).
  559.                                 x2=-1; score=score+1; skills=1;
  560.                                 // Checks score again:
  561.                                 increaselevel();
  562.                         }
  563.                         // Same logic as above but for forcing the ball right:
  564.                         if((x0==px+dif || x0==px+dif-1) && (x0<=27 && key=='8'))
  565.                         {
  566.                                 x2=1; score=score+1; skills=1;
  567.                                 increaselevel();
  568.                         }      
  569.                 }
  570.                 // Rewards an extra life when score is 100 or a multiple thereof:
  571.                 if(score%100==0 && lives<13)
  572.                 {
  573.                         lives=lives+1;
  574.                         printlives();
  575.                 }
  576.                 // Checks skills boolean:
  577.                 if(skills)
  578.                 {
  579.                         skills=0;
  580.                         skillcount=skillcount+1;
  581.                 }
  582.                 // If the player has eight skill points, and they have
  583.                 // 12 lives or less, an extra life is rewarded:
  584.                 if(skillcount==8 && lives<13)
  585.                 {
  586.                         lives=lives+1;
  587.                         skillcount=0;
  588.                         printlives();
  589.                 }
  590.                 // Sets cursor to old position of ball:
  591.                 printat(x1, y1);
  592.                 // Works out length of delay according to the level the player is on:
  593.                 a=(2*dif)-(y1-level)+22;
  594.                 if(y1<16 && y2==-1)
  595.                 {
  596.                         // This slows the ball slightly as it travels
  597.                         // up the screen, relitive to its' position:
  598.                         a=a+24;
  599.                         for(i=0;i<y1;i=i+1)
  600.                         {
  601.                                 a=a-1;
  602.                         }
  603.                 }
  604.                 // General delay for game worked out above... in theory
  605.                 // the ball falls faster than it rises:
  606.                 for(i=0;i<=a;i=i+1)
  607.                 {
  608.                         #asm
  609.                         nop
  610.                         #endasm
  611.                 }
  612.                 // Clears ball:
  613.                 print(CLEAR);
  614.         }
  615.         // Oops, all lives are lost!
  616.         // Print's final position of ball before restarting:
  617.         printat(x0,y0);
  618.         print(BALL);
  619.         printat(9,21);
  620.         print(BORDER);
  621.         restart();
  622.         in_WaitForKey();
  623.         key=in_Inkey();
  624.         if(key=='T')
  625.         {
  626.                 main();
  627.         }
  628.         level=0;
  629.         printat(25,21);
  630.         for(i=0;i<4;i=i+1)
  631.         {
  632.                 print(levels[level+i]);
  633.         }
  634.         waitforkey();
  635. }
  636. void increaselevel()
  637. {
  638.         // Sets new level, slightly increasing the difficulty by speeding
  639.         // things up very slightly:
  640.         if(score==10 || score==20 || score==220 || score==250 || score==275)
  641.         {
  642.                 level=level+1;
  643.                 score=score+1;
  644.                 newlevel=1;
  645.         }
  646.         // Increases difficulty level by decreasing the size of bat:
  647.         if(score==45 || score==112 || score==130 || score==175)
  648.         {
  649.                 dif=dif-1;
  650.                 score=score+1;
  651.                 level=level+1;
  652.                 newlevel=1;
  653.                 printat(px, 20);
  654.                 for(i=0;i<dif;i=i+1)
  655.                 {
  656.                         print(BAT);
  657.                 }
  658.                 if(px+dif==31)
  659.                 {
  660.                         print(BORDER);
  661.                 }
  662.                 else
  663.                         if(px+dif<31)
  664.                         {
  665.                                 print(GAMEROW);
  666.                         }
  667.         }
  668.         // This increases difficulty based on score:
  669.         if(score==30 || score==65 || score==80 || score==100 || score==125 || score==150 || score==200 || score==300)
  670.         {
  671.                 // Makes things a little more claustrophobic:
  672.                 levelup();
  673.                 top=top+1;
  674.                 score=score+1;
  675.                 level=level+1;
  676.                 newlevel=1;
  677.         }
  678. }
  679. // This function or method or sub-routine adds a new row to the game
  680. // to reduce the size of the play area:
  681. void levelup()
  682. {
  683.         printat(1,top);
  684.         for(i=0;i<31;i=i+1)
  685.         {
  686.                 print(BORDER);
  687.         }
  688.         return;
  689. }
  690. // Prints number of lives remaining:
  691. void printlives()
  692. {
  693.         printat(9,21);
  694.         for(i=1;i<=lives;i=i+1)
  695.         {
  696.                 print(BALL);
  697.         }
  698. }
  699. // Pause routine:
  700. void pausegame()
  701. {
  702.         while(pause)
  703.         {
  704.                 key=in_Inkey();
  705.                 if(key==82)
  706.                 {
  707.                         pause=0;
  708.                 }
  709.         }
  710. }
  711. // This prints the player's rating before restarting:
  712. void restart()
  713. {
  714.         a=level*5;
  715.         for(i=0;i<5;i=i+1)
  716.         {
  717.                 printat(14+i,1);
  718.                 print(fail[a+i]);
  719.                
  720.                 in_Wait(40);
  721.         }
  722.         // Prints a message asking the player to press T for title screen
  723.         // or press the any key to play again:
  724.         printat(2,10);
  725.         a=0;
  726.         while(gameover[a]!=13)
  727.         {
  728.                 print(gameover[a]);
  729.                 a=a+1;
  730.         }
  731.         a=a+1;
  732.         printat(8,11);
  733.         while(gameover[a]!=255)
  734.         {
  735.                 print(gameover[a]);
  736.                 a=a+1;
  737.         }
  738.         // This checks that the player still isn't holding down the key from
  739.         // playing the game, so that the game doesn't restart too quickly:
  740.         while(key!=0)
  741.         {
  742.                 key=in_Inkey();
  743.         }
  744.         printat(1,1);
  745. }
  746. // A little bit of assembly is a good thing, this sets the X and Y
  747. // position of the cursor for the print(); routine:
  748. void printat(short x, short y)
  749. {
  750.         #asm
  751.         PUSH    BC
  752.         PUSH    HL
  753.         LD              HL,6
  754.         ADD             HL,SP
  755.         LD              B,(HL)
  756.         INC             HL
  757.         INC             HL
  758.         LD              C,(HL)
  759.         CALL    PRINTAT
  760.         POP             HL
  761.         POP             BC
  762.         RET
  763.         #endasm
  764. }
  765. // This prints out our char:
  766. void print(int a)
  767. {
  768.         #asm
  769.         PUSH    AF
  770.         PUSH    HL
  771.         LD              HL,6
  772.         ADD             HL,SP
  773.         LD              A,(HL)
  774.         RST             $10
  775.         POP             HL
  776.         POP             AF
  777.         RET
  778.         #endasm
  779. }
  780. // Compile with:
  781. // zcc +zx81 -startup=2 -create-app -DTEXT -o BOUNCE BounceX.c
  782. // (C) 2012 Donkeysoft
RAW Paste Data
Top