home *** CD-ROM | disk | FTP | other *** search
/ Falcon 030 Power 2 / F030_POWER2.iso / ST_STE / MAGS / ICTARI10.ARJ / ictari.10 / C / BOINKOUT / BOUT2.C < prev    next >
C/C++ Source or Header  |  1987-04-22  |  21KB  |  893 lines

  1. /********************************************
  2. *        Bout2.c                                *
  3. *        Samuel Streeper 90/01/26            *
  4. *                                            *
  5. *                                            *
  6. *    Copyright 1990 by Antic Publishing Inc.    *
  7. *                                            *
  8. *    Miscellaneous boinkout routines            *
  9. *                                            *
  10. ********************************************/
  11.  
  12. /* edited with tabsize = 4 */
  13.  
  14. #include <obdefs.h>
  15. #include <gemdefs.h>
  16. #include <osbind.h>
  17. #include "boinkout.h"
  18.  
  19. extern int ballarray[], handle, paddlearray[];
  20. extern int xwork, ywork, wwork, hwork;
  21. extern int paddle_x, paddle_y, *lineaptr;
  22. extern MFDB pic_buf, windsource, screen_fdb, ballsource, paddlesource;
  23. extern MFDB bricksource, permbricksource, fujisource, fmasksource;
  24. extern MFDB eyesource, twobricksource;
  25. extern long score, old_score, bonus_life, old_bonus;
  26. extern int pad_y_min, pad_y_max, brickarray[], ani_count, num_bricks;
  27. extern int level, n_redraws, num_balls, lives, old_lives;
  28. extern int event_kind, cheat, pad_y_top;
  29. extern int pady_offset, max_pad_dy, pad_ht, fuji_ht, fmask_ht;
  30.  
  31. extern long get_time();
  32. int brick_erase(), perm_flash(), brick_spin(), spin_erase();
  33.  
  34. extern RECT region[];
  35.  
  36. ANI_STRUCT ani_struct[MAX_ANI];
  37. extern BALL_STRUCT bs[];
  38.  
  39. int magic_bell[] = {
  40.     0x0ff,0x100,0x2fe,0x300,0x400,0x500,0x600,0x7fc,
  41.     0x810,0x910,0xa00,0xb00,0xc20,0xd09,0xff00
  42.     };
  43.  
  44. int bricksound[] = {
  45.     0x035,0x100,0x234,0x300,0x400,0x500,0x600,0x7fc,
  46.     0x810,0x910,0xa00,0xb00,0xc15,0xd09,0xff00
  47.     };
  48.  
  49. int permbricksound[] = {
  50.     0x038,0x100,0x237,0x300,0x400,0x500,0x600,0x7fc,
  51.     0x810,0x910,0xa00,0xb00,0xc0b,0xd09,0xff00
  52.     };
  53.  
  54. int death[] = {
  55.     0x0018,0x0100,0x073e,0x0810,0x0d09,0x8000,0x0b00,0x0c60,
  56.     0x8100,0xce01,0xff00
  57.     };
  58.  
  59. int lost_ball[] = {
  60.     0x0000,0x0102,0x073e,0x0810,0x0d09,0x8000,0x0b00,0x0c30,
  61.     0x8100,0x1801,0xff00
  62.     };
  63.  
  64. int magic_bottom, mode = 3;
  65. int brick_ani, randomize;
  66. extern int max_xspeed, min_yspeed;
  67.  
  68. extern int btop, btopm, bth, bh, block_bot, bleft, btw;
  69.  
  70. extern char brickcount[];
  71.  
  72. int psound[] = {
  73.     0x041,0x100,0x240,0x300,0x400,0x500,0x600,0x7fc,
  74.     0x810,0x910,0xa00,0xb00,0xc15,0xd09,0xff00
  75.     };
  76.  
  77. /* move the ball to its new bounce position */
  78.  
  79. new_ball()
  80. {
  81.     register BALL_STRUCT *p;
  82.     register int i;
  83.     int l2,t2,r2,b2;
  84.     int xt, yt;
  85.     int o_padx, o_pady, pad_dx, pad_dy;
  86.     int pcollide;
  87.  
  88.     for (i=0; i<num_balls; i++)
  89.     {
  90.         p = &bs[i];
  91.  
  92.         p->l = p->array[0] = p->array[4];
  93.         p->t = p->array[1] = p->array[5];
  94.         p->r = p->array[2] = p->array[6];
  95.         p->b = p->array[3] = p->array[7];
  96.  
  97.         /* Restore the background picture to its virgin state    */
  98.         /* i.e.  remove the image of the ball from it.            */
  99.  
  100.         vro_cpyfm(handle,mode,p->array,&pic_buf,&windsource);
  101.     }
  102.  
  103.     o_padx = l2 = paddlearray[0] = paddlearray[4];
  104.     o_pady = t2 = paddlearray[1] = paddlearray[5];
  105.     r2 = paddlearray[2] = paddlearray[6];
  106.     b2 = paddlearray[3] = paddlearray[7];
  107.  
  108.     /* Restore the background picture to its virgin state    */
  109.     /* i.e.  remove the image of the paddle from it.            */
  110.  
  111.     vro_cpyfm(handle,mode,paddlearray,&pic_buf,&windsource);
  112.  
  113.  
  114.     /* run background animations first so things appear on top of them */
  115.     brick_ani = FALSE;                /* not animating any bricks */
  116.     if (ani_count) animate();
  117.  
  118.  
  119. /*** Calculate paddle position  **********************************/
  120.  
  121.     paddle_x = (*(lineaptr - 301)) - xwork - 25;
  122.     if (paddle_x < 0) paddle_x = 0;
  123.     else if (paddle_x + 52 > wwork) paddle_x = wwork - 52;
  124. /* limit paddle_x speed here, if desired */
  125.     pad_dx = paddle_x - o_padx;
  126.  
  127.     if (paddle_x < l2) l2 = paddle_x; else r2 = paddle_x + 52;
  128.  
  129.     paddle_y = (*(lineaptr - 300)) - ywork - pady_offset;
  130.     if (paddle_y < pad_y_top) paddle_y = pad_y_top;
  131.     else if (paddle_y > pad_y_max) paddle_y = pad_y_max;
  132.  
  133. /* limit paddle_y speed here */
  134.     pad_dy = paddle_y - o_pady;
  135.     if (pad_dy > max_pad_dy)
  136.     {
  137.         paddle_y = o_pady + max_pad_dy;
  138.         pad_dy = max_pad_dy;
  139.     }
  140.     else if (pad_dy < -max_pad_dy)
  141.     {
  142.         paddle_y = o_pady - max_pad_dy;
  143.         pad_dy = -max_pad_dy;
  144.     }
  145.  
  146.     if (paddle_y < t2) t2 = paddle_y; else b2 = paddle_y + pad_ht - 1;
  147.  
  148. /*********************************************/
  149.  
  150.     for (i=0; i<num_balls; i++)
  151.     {
  152.         p = &bs[i];
  153.  
  154.     /* calculate new ball x position */
  155.     p->x += p->xspeed;
  156.  
  157.     if (p->x <= 0)                /* ball hit left edge */
  158.     {    
  159.         p->xspeed = -p->xspeed;
  160.         p->spin_dir = -p->spin_dir;
  161.         bsound(SIDE_S);
  162.         p->x = 0;
  163.         if (p->xspeed == 0) p->xspeed = 1;
  164.     }
  165.  
  166.     else if (p->x >= (wwork - (p->ball_wid+1)))    /* ball hit right edge */
  167.     {    bsound(SIDE_S);
  168.         p->xspeed = -p->xspeed;
  169.         p->x = (wwork - (p->ball_wid+1));
  170.         p->spin_dir = -p->spin_dir;
  171.         if (p->xspeed == 0) p->xspeed = -1;
  172.     }
  173.  
  174.     if (p->x < p->l) p->l = p->x; else p->r = p->x + p->ball_wid;
  175.  
  176.     /* calculate new ball vertical position */
  177.     p->y += p->yspeed;
  178.  
  179.     if (p->y <= 0)                /* ball hit top of window */
  180.     {
  181.         rand(p);
  182.         bsound(TOP_S);
  183.         p->yspeed = -p->yspeed;
  184.         p->y = 0;
  185.         p->spin_dir = -p->spin_dir;
  186.     }
  187.  
  188.     else if (p->y > (hwork - p->ball_ht - 1))    /* ball hit bottom of window */
  189.     {
  190.         if (cheat || (magic_bottom > 0))
  191.         {
  192.             bsound(BOT_S);
  193.             p->yspeed = -p->yspeed;
  194.             p->y = (hwork - p->ball_ht - 1);
  195.             p->spin_dir = -p->spin_dir;
  196.             magic_bottom--;
  197.         }
  198.         else
  199.         {
  200.             kill_ball(i);
  201.             if (num_balls <= 0)
  202.             {
  203.                 Dosound(death);
  204.                 if (--lives > 0)
  205.                 {    evnt_timer(1000,0);
  206.                     cont_level();
  207.                 }
  208.                 else
  209.                 {
  210.                     show_lives();
  211.                     n_redraws = 0;
  212.                     add_region(xwork,ywork,wwork,hwork);
  213.                     do_redraw();
  214.                     event_kind = MU_MESAG;
  215.                 }
  216.                 goto end;
  217.             }
  218.  
  219.             Dosound(lost_ball);
  220.             i--;    /* a new ball takes this slot */
  221.             goto loopend;
  222.         }
  223.     }
  224.  
  225.  
  226. /******************************************************
  227.     We have now calculated the projected next positions
  228.     for the ball and paddle. Time to look for brick and
  229.     paddle collisions!
  230. ******************************************************/
  231.  
  232.     xt = p->x + p->half_wid; yt = p->y + p->ball_ht;
  233.     if (yt >= paddle_y && xt >= paddle_x && (xt <= paddle_x + 52))
  234.     {
  235.         pcollide = FALSE;
  236.  
  237.         /* if ball passed into paddle from the top */
  238.         if (yt <= (paddle_y + p->yspeed - pad_dy))
  239.         {
  240.             pcollide = TRUE;
  241.  
  242.             if (p->yspeed > 0) p->yspeed = -p->yspeed;
  243.             p->yspeed += pad_dy;
  244.             if (p->yspeed < min_yspeed) p->yspeed = min_yspeed;
  245.             p->y = paddle_y - p->ball_ht;
  246.         }
  247.  
  248.         /* else if the ball in the paddle nevertheless */
  249.         else if (p->y <= paddle_y + pad_ht)
  250.         {
  251.             if ((p->xspeed * pad_dx) <= 0) p->xspeed = -p->xspeed;
  252.             pcollide = TRUE;
  253.         }
  254.  
  255.         if (pcollide)
  256.         {
  257.             p->spin_dir = -p->spin_dir;
  258.             Dosound(psound);
  259.  
  260.             p->xspeed += pad_dx/2;
  261.             if (p->xspeed < -max_xspeed) p->xspeed = -max_xspeed;
  262.             else if (p->xspeed > max_xspeed) p->xspeed = max_xspeed;
  263.  
  264.             if (p->xspeed == 0)        /* too easy! */
  265.             {
  266.                 if (++randomize & 1) p->xspeed = -1;
  267.                 else p->xspeed = 1;
  268.             }
  269.         }
  270.     }
  271.  
  272.     if (p->y < p->t) p->t = p->y; else p->b = p->y + p->ball_ht;
  273.  
  274.  
  275. /************************************************
  276. *    Check for collisions with the bricks        *
  277. ************************************************/
  278.  
  279.     if (bcollide(i))
  280.     {
  281.         p->spin_dir = -p->spin_dir;
  282.  
  283.         /* logically this doesn't really go here, but            */
  284.         /* its more efficient than checking every iteration...    */
  285.         if (num_bricks <= 0)
  286.         {
  287.             while (ani_count && brick_ani)
  288.             {    animate();
  289.                 do_redraw();
  290.                 evnt_timer(75,0);
  291.             }
  292.  
  293.             level++;
  294.             add_difficulty();
  295.  
  296.             old_lives = lives;
  297.             old_score = score;
  298.             old_bonus = bonus_life;
  299.             restart_level();
  300.             goto end;
  301.         }
  302.     }
  303.  
  304.  
  305. /****** call the animation function for this ball now, *****/
  306. /****** pass it a pointer to it's animation structure ******/
  307.     (*p->ani_funct)(p);
  308. loopend:;
  309.     }
  310.  
  311.     paddlearray[0] = 0;
  312.     paddlearray[1] = 0;
  313.     paddlearray[2] = 52;
  314.     paddlearray[3] = pad_ht - 1;
  315.     paddlearray[4] = paddle_x;
  316.     paddlearray[5] = paddle_y;
  317.     paddlearray[6] = paddle_x + 52;
  318.     paddlearray[7] = paddle_y + paddlearray[3];
  319.  
  320.     vro_cpyfm(handle,7,paddlearray,&paddlesource,&windsource);
  321.  
  322.     /* Whew! we are now done creating the ball image in our background    */
  323.     /* buffer. Now we must blit the updated picture into the boink        */
  324.     /* window. The area we must update is the smallest rectangle that    */
  325.     /* will enclose both the ball's old position and its new one. This    */
  326.     /* technique will erase the old ball and draw in the new one        */
  327.     /* without any flickering of the image. Note also that the area        */
  328.     /* we update must be clipped to our windows rectangle list so that    */
  329.     /* we don't trash the contents of another window.                    */
  330.  
  331.  
  332.     /* Use the rectangle list to draw the window in an orderly fashion */
  333.  
  334.     add_region(xwork + l2,ywork + t2,r2-l2+1,b2-t2+1);
  335.  
  336.     do_redraw();
  337. end:;
  338. }
  339.  
  340.  
  341. bcollide(i)
  342. {
  343.     register BALL_STRUCT *p;
  344.     register int x1, y1, x2, y2;    /* 2 collision points */
  345.     int x3, y3, x4, y4;                /* 2 dragging corners */
  346.     int row, col, x, y, ndx, r2, c2, ndx2;
  347.  
  348.     p = &bs[i];
  349.  
  350.     if (p->y > block_bot) return FALSE;
  351.     if (p->y + p->ball_ht < btopm) return FALSE;
  352.  
  353.     x2 = p->x - bleft;            /* corrected left point */
  354.     x1 = x2 + p->half_wid;        /* corrected top point */
  355.     y1 = p->y - btopm;            /* corrected top point */
  356.     y2 = y1 + p->half_ht;        /* corrected left point */
  357.  
  358.     x3 = x2;                    /* the dragging corners */
  359.     x4 = x2 + p->ball_wid;
  360.  
  361.     if (x2 < 0) x2 = x3 = 0;
  362.  
  363.     if (p->xspeed > 0) x2 = x4;    /* use center point on right side */
  364.  
  365.     if ((p->xspeed * p->yspeed) < 0)
  366.     {    y3 = y1;
  367.         y4 = y1 + p->ball_ht;
  368.     }
  369.     else
  370.     {    y3 = y1 + p->ball_ht;
  371.         y4 = y1;
  372.     }
  373.  
  374.     if (p->yspeed > 0)            /* going down */
  375.     {
  376.         y1 += p->ball_ht;
  377.     }
  378.  
  379. /**** look for horizontal collision ****/
  380.  
  381.     if (y2 < 0) goto c1;
  382.     row = y2 / bth;
  383.     col = x2 / btw;
  384.     if (col > 8) col = 8;
  385.  
  386.     ndx = 9 * row + col;
  387.     if (brickcount[ndx] && ndx < 63)
  388.     {
  389.         if (p->xspeed == 0) p->yspeed = -p->yspeed;
  390.         else
  391.         {
  392.             if (p->xspeed < 0) p->x = ((col + 1) * btw) + bleft + 1;
  393.             else p->x = col * btw - 21 + bleft;
  394.             fixx(p);
  395.             p->xspeed = -p->xspeed;
  396.  
  397. /*            p->y -= p->yspeed / 2;*/
  398.         }
  399.  
  400. /******* We got a horizontal collision, lets check *********/
  401. /******* for a vertical one too and correct position *******/
  402.  
  403.         if (y1 < 0) goto collision;
  404.         r2 = y1 / bth;
  405.         c2 = x1 / btw;
  406.         if (c2 > 8) c2 = 8;
  407.  
  408.         ndx2 = 9 * r2 + c2;
  409.         if (brickcount[ndx2] && (ndx2 < 63) && (row != r2))
  410.         {
  411.             if (p->yspeed < 0) p->y = btopm + (r2+1) * bth;
  412.             else p->y = btopm + r2 * bth - p->ball_ht;
  413. /*            p->yspeed = -p->yspeed;*/
  414.         }
  415.  
  416.         goto collision;
  417.     }
  418.  
  419. /*** check vertical for collision ***/
  420. c1:
  421.     if (y1 < 0) goto c2;
  422.     row = y1 / bth;
  423.     col = x1 / btw;
  424.     if (col > 8) col = 8;
  425.  
  426.     ndx = 9 * row + col;
  427.     if (brickcount[ndx] && ndx < 63)
  428.     {
  429.         if (p->yspeed < 0) p->y = btopm + (row+1) * bth + 1;
  430.         else p->y = btopm + row * bth - p->ball_ht - 1;
  431.         p->yspeed = -p->yspeed;
  432.  
  433.         goto collision;
  434.     }
  435.  
  436. /************ check left corner **************/
  437. c2:
  438.     if (y3 < 0) goto c3;
  439.     row = y3 / bth;
  440.     col = x3 / btw;
  441.     if (col > 8) col = 8;
  442.  
  443.     ndx = 9 * row + col;
  444.     if (brickcount[ndx] && ndx < 63)
  445.     {
  446.         if (p->xspeed < 0)
  447.         {
  448.             p->x = ((col + 1) * btw) + bleft + 1;
  449.             p->xspeed = -p->xspeed;
  450.         }
  451.         else
  452.         {
  453.             if (p->yspeed < 0) p->y = btopm + (row+1) * bth + 1;
  454.             else p->y = btopm + row * bth - p->ball_ht - 1;
  455.             p->yspeed = -p->yspeed;
  456.         }
  457.  
  458.         goto collision;
  459.     }
  460.  
  461. /************ check right corner **************/
  462. c3:
  463.     if (y4 < 0) goto c4;
  464.     row = y4 / bth;
  465.     col = x4 / btw;
  466.     if (col > 8) col = 8;
  467.  
  468.     ndx = 9 * row + col;
  469.     if (brickcount[ndx] && ndx < 63)
  470.     {
  471.         if (p->xspeed <= 0)
  472.         {
  473.             if (p->yspeed < 0) p->y = btopm + (row+1) * bth + 1;
  474.             else p->y = btopm + row * bth - p->ball_ht - 1;
  475.             p->yspeed = -p->yspeed;
  476.         }
  477.         else
  478.         {
  479.             p->x = col * btw - 21 + bleft;
  480.             fixx(p);
  481.             p->xspeed = -p->xspeed;
  482.         }
  483.  
  484. collision:
  485.         x = bleft + col * btw;
  486.         y = btop + row * bth;
  487.         switch(brickcount[ndx])
  488.         {
  489.             case -1:
  490.                 Dosound(permbricksound);
  491.                 add_ani(perm_flash,x,y);
  492.                 rand(p);
  493.                 break;
  494.             case 1:
  495.                 Dosound(bricksound);
  496.                 brick_ani = TRUE;
  497.                 brickcount[ndx] = 0;
  498.                 add_ani(brick_erase,x,y);
  499.                 num_bricks--;
  500.                 score += 10;
  501.                 show_score();
  502.                 break;
  503.  
  504.             case 2:                    /* magic */
  505.                 Dosound(magic_bell);
  506.                 brickcount[ndx] = 0;
  507.                 erase_brick(x,y);
  508.                 num_bricks--;
  509.                 magic(i);
  510.                 score += 13;
  511.                 show_score();
  512.                 break;
  513.  
  514.             case 3:
  515.                 Dosound(bricksound);
  516.                 brick_ani = TRUE;
  517.                 brickcount[ndx] = 0;
  518.                 add_ani(spin_erase,x,y);
  519.                 num_bricks--;
  520.                 score += 11;
  521.                 show_score();
  522.                 break;
  523.             case 4:
  524.             case 5:
  525.             case 6:
  526.                 Dosound(bricksound);
  527.                 brick_ani = TRUE;
  528.                 brickcount[ndx]--;
  529.                 add_ani(brick_spin,x,y);
  530.                 score += 2;
  531.                 show_score();
  532.                 break;
  533.         }
  534.  
  535.         return TRUE;
  536.     }
  537. c4:
  538.     return FALSE;
  539. }
  540.  
  541. /********************************************************
  542. *    animate runs and updates all the animation threads    *
  543. ********************************************************/
  544. animate()
  545. {
  546.     register int i;
  547.     register ANI_STRUCT *p;
  548.  
  549.     for (i = 0; i < ani_count; i++)
  550.     {
  551.         p = &ani_struct[i];
  552.         if ((*p->ani_funct)(p->x,p->y,p->frame))
  553.         {
  554.             kill_ani(i--);
  555.         }
  556.         else (p->frame)++;
  557.     }
  558. }
  559.  
  560. /************************************************
  561. fix ball x position to keep it within window
  562. after x corrections. The blit routines bomb
  563. if passed a coordinate less than zero, too.
  564. ************************************************/
  565. fixx(p)
  566. register BALL_STRUCT *p;
  567. {
  568.     if (p->x < 0)                                /* ball hit left edge */
  569.         p->x = 0;
  570.  
  571.     else if (p->x >= (wwork - (p->ball_wid+1)))    /* ball hit right edge */
  572.         p->x = (wwork - (p->ball_wid+1));
  573. }
  574.  
  575. add_ani(f,x,y)
  576. int (*f)();
  577. {
  578.     register ANI_STRUCT *p;
  579.     register int i;
  580.  
  581.     /* kill any other animations of this brick */
  582.     for (i=0; i<ani_count; i++)
  583.     {
  584.         p = &ani_struct[i];
  585.         if (x == p->x && y == p->y)
  586.         {
  587.             kill_ani(i);
  588.             break;
  589.         }
  590.     }
  591.  
  592.     if (ani_count >= MAX_ANI) return;    /* would overflow list */
  593.  
  594.     p = &ani_struct[ani_count];
  595.     p->ani_funct = f;
  596.     p->x = x;
  597.     p->y = y;
  598.     p->frame = 0;
  599.     ani_count++;
  600. }
  601.  
  602. kill_ani(n)
  603. {
  604.     register int i;
  605.     ani_count--;
  606.     for (i = n; i < ani_count; i++)
  607.         ani_struct[i] = ani_struct[i+1];    /* structure assignment */
  608. }
  609.  
  610. /*** animation function to erase a standard brick ***/
  611. brick_erase(x,y,frame)
  612. {
  613.     brick_ani = TRUE;
  614.     frame++;            /* we start at 1 */
  615.  
  616.     if (mode == BLACKMODE) goto nd;
  617.  
  618.     brickarray[0] = brickarray[4] = x;
  619.     brickarray[1] = brickarray[5] = y;
  620.     brickarray[2] = brickarray[6] = x + 43;
  621.     brickarray[3] = brickarray[7] = y + bh - 1;
  622.  
  623.     /* erase old brick */
  624.     vro_cpyfm(handle,3,brickarray,&pic_buf,&windsource);
  625.  
  626.     brickarray[0] = frame * btw;
  627.     brickarray[1] = 0;
  628.     brickarray[2] = brickarray[0] + 43;
  629.     brickarray[3] = bh - 1;
  630.  
  631.     /* draw new brick */
  632.     if (frame < 4)
  633.         vro_cpyfm(handle,7,brickarray,&bricksource,&windsource);
  634.  
  635.     add_region(xwork + x, ywork + y, 44, bh);
  636. nd:
  637.     if (frame < 4) return FALSE;
  638.     return TRUE;    /* all done! */
  639. }
  640.  
  641. /*** animation function to flash a permanent brick ***/
  642. perm_flash(x,y,frame)
  643. {
  644.     register int f2;
  645.  
  646.     frame++;            /* we start at 1 */
  647.  
  648.     if (frame < 4) f2 = frame;
  649.     else f2 = 6 - frame;
  650.  
  651.     brickarray[0] = f2 * btw;
  652.     brickarray[1] = 0;
  653.     brickarray[2] = brickarray[0] + 43;
  654.     brickarray[3] = bh - 1;
  655.     brickarray[4] = x;
  656.     brickarray[5] = y;
  657.     brickarray[6] = x + 43;
  658.     brickarray[7] = y + brickarray[3];
  659.  
  660.     /* draw new brick */
  661.     vro_cpyfm(handle,3,brickarray,&permbricksource,&windsource);
  662.  
  663.     add_region(xwork + x, ywork + y, 44, bh);
  664.  
  665.     if (frame < 6) return FALSE;
  666.     return TRUE;    /* all done! */
  667. }
  668.  
  669.  
  670. /**************************************
  671. animate a boink ball
  672. **************************************/
  673. ball_ani(p)
  674. register BALL_STRUCT *p;
  675. {
  676.     /* rotate the ball by selecting a new ball image to blit */
  677.     /* we have an image of the ball in 6 different stages of rotation */
  678.  
  679.     p->ball_num += p->spin_dir;
  680.     if (p->ball_num >= 6) p->ball_num = 0;
  681.     else if (p->ball_num < 0) p->ball_num = 5;
  682.  
  683.     p->array[0] = 120;
  684.     p->array[1] = 0;
  685.     p->array[2] = 140;
  686.     p->array[3] = p->ball_ht-1;
  687.     p->array[4] = p->x;
  688.     p->array[5] = p->y;
  689.     p->array[6] = p->x + 20;
  690.     p->array[7] = p->y + p->ball_ht-1;
  691.  
  692.     /* blit the ball mask into the background picture which cuts a     */
  693.     /* white hole in the picture */
  694.  
  695.     vro_cpyfm(handle,4,p->array,&ballsource,&windsource);
  696.  
  697.     /* blit the ball into the white hole we just cut out of the picture */
  698.     /* with the mask */
  699.  
  700.     p->array[0] = 20 * p->ball_num;
  701.     p->array[2] = 20 * (p->ball_num+1);
  702.  
  703.     vro_cpyfm(handle,7,p->array,&ballsource,&windsource);
  704.     add_region(xwork + p->l, ywork + p->t,
  705.         p->r - p->l + 1, p->b - p->t + 1);
  706. }
  707.  
  708. char fn[] = { 0,0,0,0,1,1,1,2,3,4,5,6,5,4,3,2,1 };
  709. /**************************************
  710. animate a spinning fuji
  711. **************************************/
  712. fuji_ani(p)
  713. register BALL_STRUCT *p;
  714. {
  715.     register int offset;
  716.     /* rotate the ball by selecting a new ball image to blit */
  717.     /* we have an image of the ball in 6 different stages of rotation */
  718.  
  719.     p->ball_num++;
  720.     if (p->ball_num > 16) p->ball_num = 0;
  721.  
  722.     offset = 16 * fn[p->ball_num];
  723.  
  724.     p->array[0] = offset;
  725.     p->array[1] = 0;
  726.     p->array[2] = offset + 15;
  727.     p->array[3] = fmask_ht - 1;
  728.     p->array[4] = p->x;
  729.     p->array[5] = p->y;
  730.     p->array[6] = p->x + 15;
  731.     p->array[7] = p->y + fmask_ht - 1;
  732.  
  733.     /* blit the ball mask into the background picture which cuts a     */
  734.     /* white hole in the picture */
  735.  
  736.     vro_cpyfm(handle,4,p->array,&fmasksource,&windsource);
  737.  
  738.     /* blit the ball into the white hole we just cut out of the picture */
  739.     /* with the mask */
  740.  
  741.     p->array[0] = offset;
  742.     p->array[1] = 0;
  743.     p->array[2] = offset + 15;
  744.     p->array[3] = fuji_ht - 1;
  745.     p->array[4] = p->x;
  746.     p->array[5] = p->y + 1;
  747.     p->array[6] = p->x + 15;
  748.     p->array[7] = p->y + fuji_ht - 1;
  749.  
  750.     vro_cpyfm(handle,7,p->array,&fujisource,&windsource);
  751.  
  752.     p->array[5] = p->y;
  753.     p->array[7] = p->y + fmask_ht - 1;
  754.  
  755.     add_region(xwork + p->l, ywork + p->t,
  756.         p->r - p->l + 1, p->b - p->t + 1);
  757. }
  758.  
  759. char efn[] = { 0,0,1,2,1,0,1,2,1,0,0,3,4,5,4,3 };
  760. /**************************************
  761. animate an eye
  762. **************************************/
  763. eye_ani(p)
  764. register BALL_STRUCT *p;
  765. {
  766.     register int ndx;
  767.     /* rotate the ball by selecting a new ball image to blit */
  768.     /* we have an image of the ball in 6 different stages of rotation */
  769.  
  770.     p->ball_num++;
  771.     if (p->ball_num > 31) p->ball_num = 0;
  772.  
  773.     ndx = efn[p->ball_num/2];
  774.  
  775.     p->array[0] = 120;
  776.     p->array[1] = 0;
  777.     p->array[2] = 140;
  778.     p->array[3] = p->ball_ht - 1;
  779.     p->array[4] = p->x;
  780.     p->array[5] = p->y;
  781.     p->array[6] = p->x + 20;
  782.     p->array[7] = p->y + p->ball_ht - 1;
  783.  
  784.     /* blit the ball mask into the background picture which cuts a     */
  785.     /* white hole in the picture */
  786.  
  787.     vro_cpyfm(handle,4,p->array,&eyesource,&windsource);
  788.  
  789.     /* blit the ball into the white hole we just cut out of the picture */
  790.     /* with the mask */
  791.  
  792.     p->array[0] = 20 * ndx;
  793.     p->array[2] = 20 * (ndx + 1);
  794.  
  795.     vro_cpyfm(handle,7,p->array,&eyesource,&windsource);
  796.  
  797.     add_region(xwork + p->l, ywork + p->t,
  798.         p->r - p->l + 1, p->b - p->t + 1);
  799. }
  800.  
  801. brick_spin(x,y,frame)
  802. {
  803.     register int f2;
  804.  
  805.     brick_ani = TRUE;
  806.     frame+=2;            /* we start at 2 */
  807.  
  808.     if (mode == BLACKMODE) goto nd;
  809.  
  810.     if (frame < 4) f2 = frame;
  811.     else f2 = 6-frame;
  812.  
  813.     brickarray[0] = brickarray[4] = x;
  814.     brickarray[1] = brickarray[5] = y;
  815.     brickarray[2] = brickarray[6] = x + 43;
  816.     brickarray[3] = brickarray[7] = y + bh - 1;
  817.  
  818.     /* erase old brick */
  819.     vro_cpyfm(handle,3,brickarray,&pic_buf,&windsource);
  820.  
  821.     brickarray[0] = f2 * 48;
  822.     brickarray[1] = 0;
  823.     brickarray[2] = brickarray[0] + 43;
  824.     brickarray[3] = bh - 1;
  825.  
  826.     /* draw new brick */
  827.     vro_cpyfm(handle,7,brickarray,&twobricksource,&windsource);
  828.  
  829.     add_region(xwork+x,ywork+y, 44, bh);
  830. nd:
  831.     if (frame < 5) return FALSE;
  832.     return TRUE;    /* all done! */
  833. }
  834.  
  835. spin_erase(x,y,frame)
  836. {
  837.     brick_ani = TRUE;
  838.     frame+=2;            /* we start at 2 */
  839.  
  840.     if (mode == BLACKMODE) goto nd;
  841.  
  842.     brickarray[0] = brickarray[4] = x;
  843.     brickarray[1] = brickarray[5] = y;
  844.     brickarray[2] = brickarray[6] = x + 43;
  845.     brickarray[3] = brickarray[7] = y + bh - 1;
  846.  
  847.     /* erase old brick */
  848.     vro_cpyfm(handle,mode,brickarray,&pic_buf,&windsource);
  849.  
  850.     brickarray[0] = frame * 48;
  851.     brickarray[1] = 0;
  852.     brickarray[2] = brickarray[0] + 43;
  853.     brickarray[3] = bh - 1;
  854.  
  855.     /* draw new brick */
  856.     if (frame < 4)
  857.         vro_cpyfm(handle,7,brickarray,&twobricksource,&windsource);
  858.  
  859.     add_region(xwork+x, ywork+y, 44, bh);
  860. nd:
  861.     if (frame < 4) return FALSE;
  862.     return TRUE;    /* all done! */
  863. }
  864.  
  865. /* used to erase a magic brick */
  866. erase_brick(x,y)
  867. {
  868.     brickarray[0] = brickarray[4] = x;
  869.     brickarray[1] = brickarray[5] = y;
  870.     brickarray[2] = brickarray[6] = x + 43;
  871.     brickarray[3] = brickarray[7] = y + bh - 1;
  872.  
  873.     vro_cpyfm(handle,mode,brickarray,&pic_buf,&windsource);
  874.     add_region(xwork+x,ywork+y,44,bh);
  875. }
  876.  
  877. rand(p)
  878. register BALL_STRUCT *p;
  879. {
  880.     register int val;
  881.  
  882.     if (++randomize > 40)
  883.     {
  884.         val = (Supexec(get_time) & 3);
  885.         if (val > 2) val = 2;
  886.  
  887.         randomize = 0;
  888.         p->xspeed += val;
  889.         while (p->xspeed > max_xspeed)
  890.             p->xspeed -= (Supexec(get_time) & 3);
  891.     }
  892. }
  893.