home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser 2002 January / STC_CD_01_2002.iso / GAMES / BOINKO21 / SRC / SRC / BOUT2.C < prev    next >
C/C++ Source or Header  |  2000-11-27  |  24KB  |  998 lines

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