home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d115 / marketroid.lha / Marketroid / src / anim.c next >
C/C++ Source or Header  |  1987-11-22  |  9KB  |  413 lines

  1. /*  :ts=8 bk=0
  2.  *
  3.  * anim.c:    Animation drivers.
  4.  *
  5.  * Leo L. Schwab            8710.2        (415) 456-3960
  6.  */
  7. #include <exec/types.h>
  8. #include <exec/lists.h>
  9. #include <exec/memory.h>
  10. #include <graphics/rastport.h>
  11. #include "marketroid.h"
  12.  
  13. extern struct object    ob_grunt;    /*  Special case for movement  */
  14. extern struct BitMap    *sbm;
  15.  
  16. struct BitMap        *getxpmap();
  17. struct List        guys;
  18. static int        opened;
  19. int            leftbound, rightbound, topbound, bottombound;
  20.  
  21. struct obcontrol *
  22. addobject (ob, pri, dir, x, y)
  23. register struct object *ob;
  24. int pri, dir, x, y;
  25. {
  26.     register struct obcontrol    *oc;
  27.  
  28.     if (!(oc = AllocMem ((long) sizeof (*oc), MEMF_CLEAR)))
  29.         return (0);
  30.  
  31.     oc -> node.ln_Pri    = pri;
  32.     oc -> ob        = ob;
  33.     oc -> x            = x;
  34.     oc -> y            = y;
  35.     oc -> frame        = 0;
  36.     oc -> delay        = 1;
  37.  
  38.     if (oc->x + ob->width > rightbound ||
  39.         oc->x < leftbound ||
  40.         oc->y + ob->height > bottombound ||
  41.         oc->y < topbound)
  42.         oc -> flags |= OFFSCREEN;
  43.  
  44.     setdir (oc, dir);
  45.     Enqueue (&guys, oc);
  46.     return (oc);
  47. }
  48.  
  49. removeobject (oc)
  50. register struct obcontrol *oc;
  51. {
  52.     register struct object    *ob = oc -> ob;
  53.     register struct BitMap    *bm;
  54.  
  55.     /*  Pull it out of the list  */
  56.     Remove (oc);
  57.  
  58.     /*  Erase the image from the screen  */
  59.     if (!(oc -> flags & OFFSCREEN))
  60.         BltBitMap (ob -> bitmap, 0L, 0L,
  61.                sbm, (long) oc -> x, (long) oc -> y,
  62.                (long) ob -> width, (long) ob -> height,
  63.                0L, 0xffL, NULL);
  64.  
  65.     /*  Free dynamically allocated stuff  */
  66.     if (bm = (struct BitMap *) oc -> node.ln_Name) {
  67.         if (bm -> Planes[0])
  68.             FreeRaster (bm -> Planes[0],
  69.                     (long) ob->width, bm->Rows * 4L);
  70.         FreeMem (bm, (long) sizeof (*bm));
  71.     }
  72.     FreeMem (oc, (long) sizeof (*oc));
  73. }
  74.  
  75. deleteallof (ob)
  76. register struct object *ob;
  77. {
  78.     register struct obcontrol    *oc;
  79.  
  80.     oc = (struct obcontrol *) guys.lh_Head;
  81.     while (oc -> node.ln_Succ) {
  82.         oc = (struct obcontrol *) oc -> node.ln_Succ;
  83.         if (((struct obcontrol *) oc -> node.ln_Pred) -> ob == ob)
  84.             removeobject (oc -> node.ln_Pred);
  85.     }
  86. }
  87.  
  88. setdir (oc, dir)
  89. register struct obcontrol *oc;
  90. int dir;
  91. {
  92.     switch (dir) {
  93.     case UP:
  94.         oc -> dx = 0;
  95.         oc -> dy = -(oc -> ob -> incr);
  96.         oc -> xoff = oc->ob->upx;
  97.         oc -> yoff = oc->ob->upy;
  98.         break;
  99.  
  100.     case DOWN:
  101.         oc -> dx = 0;
  102.         oc -> dy = oc -> ob -> incr;
  103.         oc -> xoff = oc->ob->downx;
  104.         oc -> yoff = oc->ob->downy;
  105.         break;
  106.  
  107.     case LEFT:
  108.         oc -> dy = 0;
  109.         oc -> dx = -2 * oc->ob->incr;
  110.         oc -> xoff = oc->ob->leftx;
  111.         oc -> yoff = oc->ob->lefty;
  112.         break;
  113.  
  114.     case RIGHT:
  115.         oc -> dy = 0;
  116.         oc -> dx = 2 * oc->ob->incr;
  117.         oc -> xoff = oc->ob->rightx;
  118.         oc -> yoff = oc->ob->righty;
  119.         break;
  120.     }
  121.     oc -> dir = dir;
  122. }
  123.  
  124. setbounds (lb, rb, tb, bb)
  125. {
  126.     leftbound    = lb;
  127.     rightbound    = rb;
  128.     topbound    = tb;
  129.     bottombound    = bb;
  130. }
  131.  
  132. setexplode (oc)
  133. register struct obcontrol *oc;
  134. {
  135.     oc -> flags |= EXPLODING;
  136.     oc -> dir = 1;
  137.     oc -> frame = 0;
  138.     oc -> delay = 1;
  139. }
  140.  
  141. cls (rp)
  142. struct RastPort *rp;
  143. {
  144.     register BYTE    pensav = rp -> FgPen;
  145.  
  146.     SetAPen (rp, 0L);
  147.     RectFill (rp, (long) leftbound, (long) topbound,
  148.           rightbound - 1L, bottombound - 1L);
  149.     SetAPen (rp, (long) pensav);
  150. }
  151.  
  152. animate ()
  153. {
  154.     register struct obcontrol    *oc;
  155.  
  156.     for (oc = (struct obcontrol *) guys.lh_Head;
  157.          oc -> node.ln_Succ;
  158.          oc = (struct obcontrol *) oc -> node.ln_Succ) {
  159.         if (!--(oc->delay)) {
  160.             /*  Countdown ran out, update image  */
  161.             moveobject (oc);
  162.             if (oc -> flags & EXPLODING)
  163.                 /*  Special mod. for exploding stuff  */
  164.                 oc -> delay = 2;
  165.             else if (oc -> ob == &ob_grunt)
  166.                 /*  Grunts move randomly  */
  167.                 oc -> delay = rnd (oc->ob->framerate) +
  168.                           oc -> ob -> framerate;
  169.             else
  170.                 oc -> delay = oc -> ob -> framerate;
  171.         }
  172.     }
  173. }
  174.  
  175. moveobject (oc)
  176. register struct obcontrol *oc;
  177. {
  178.     register struct object    *ob = oc -> ob;
  179.     long            ex, ey, sizx, sizy;
  180.     long            yoff;
  181.  
  182.     yoff = oc -> yoff;
  183.     if (oc -> flags & FREEZE)    /*  Don't move it, just draw it  */
  184.         goto frozen;        /*  Up yours, Djikstra :-)  */
  185.  
  186.     if (oc -> flags & EXPLODING) {
  187.         explode (oc);
  188.         return;
  189.     }
  190.  
  191.     switch (oc -> dir) {
  192.     case UP:
  193.         oc -> y += oc -> dy;
  194.         ex = oc -> x;
  195.         ey = oc -> y + ob -> height;
  196.         sizx = ob -> width;
  197.         sizy = -oc -> dy;
  198.         break;
  199.  
  200.     case DOWN:
  201.         ex = oc -> x;
  202.         ey = oc -> y;
  203.         sizx = ob -> width;
  204.         sizy = oc -> dy;
  205.         oc -> y += oc -> dy;
  206.         break;
  207.  
  208.     case LEFT:
  209.         oc -> x += oc -> dx;
  210.         ex = oc -> x + ob -> width;
  211.         ey = oc -> y;
  212.         sizx = -oc -> dx;
  213.         sizy = ob -> height;
  214.         break;
  215.  
  216.     case RIGHT:
  217.         ex = oc -> x;
  218.         ey = oc -> y;
  219.         sizx = oc -> dx;
  220.         sizy = ob -> height;
  221.         oc -> x += oc -> dx;
  222.         break;
  223.     }
  224.  
  225.     /*
  226.      * This next 'if' is tricky.  If the object wanders off the screen
  227.      * in any way, we mark it as OFFSCREEN and don't render it.  If,
  228.      * during the last animation pass, it was onscreen, we erase it at
  229.      * it's last known position.
  230.      */
  231.     if (oc->x + ob->width > rightbound ||
  232.         oc->x < leftbound ||
  233.         oc->y + ob->height > bottombound ||
  234.         oc->y < topbound) {
  235.         if (!(oc -> flags & OFFSCREEN))
  236.             BltBitMap
  237.              (ob -> bitmap, 0L, 0L,
  238.               sbm, (long) oc->x - oc->dx, (long) oc->y - oc->dy,
  239.               (long) ob -> width, (long) ob -> height,
  240.               0L, 0xffL, NULL);
  241.         oc -> flags |= OFFSCREEN;
  242.         return;
  243.     }
  244.  
  245.     /*  Do erasure only if it really moved and was onscreen last time  */
  246.     if (sizx && sizy && !(oc->flags & OFFSCREEN))
  247.         BltBitMap (ob -> bitmap, 0L, 0L, sbm, ex, ey, sizx, sizy,
  248.                0L, 0xffL, NULL);
  249.  
  250.     /*  Calculate new frame, if multiframed object  */
  251.     if (ob -> animseq)
  252.         yoff += (ob -> animseq)[oc -> frame];
  253.  
  254. frozen:
  255.     /*  Draw new guy  */
  256.     BltBitMap (ob -> bitmap, (long) oc -> xoff, yoff,
  257.            sbm, (long) oc -> x, (long) oc -> y,
  258.            (long) ob -> width, (long) ob -> height,
  259.            0xc0L, 0xffL, NULL);
  260.  
  261.     if (++oc -> frame >= ob -> nframes)
  262.         oc -> frame = 0;
  263.     oc -> flags &= ~OFFSCREEN;
  264. }
  265.  
  266. explode (oc)
  267. register struct obcontrol *oc;
  268. {
  269.     /*  Pray....  */
  270.     register struct object    *ob = oc -> ob;
  271.     register struct BitMap    *bm;
  272.     register long        y, by, high;
  273.     UWORD            bpr;
  274.  
  275.     if (oc -> frame < 0 || oc -> flags & OFFSCREEN)
  276.         return;
  277.  
  278.     if (!oc -> node.ln_Name)
  279.         /*  No explosion bitmap has been allocated, go get one.  */
  280.         if (!(oc -> node.ln_Name = (char *) getxpmap (oc)))
  281.             die ("Explosion allocation failed.\n");
  282.     bm = (struct BitMap *) oc -> node.ln_Name;
  283.  
  284.     /*  Clear previous instance of explosion from screen  */
  285.     high = oc -> frame * (ob -> height - 1) + 1;
  286.     y = oc->y - high/2 + ob->height/2;
  287.     if (y < topbound) {
  288.         by = -(y - topbound);
  289.         high -= by;
  290.         y = topbound;
  291.     } else
  292.         by = 0;
  293.  
  294.     if (y + high >= bottombound)
  295.         high -= y + high - bottombound;
  296.  
  297.     BltBitMap (bm, 0L, by,
  298.            sbm, (long) oc -> x, y,
  299.            (long) ob -> width, high,
  300.            0x20L, 0xffL, NULL);
  301.  
  302.     /*  Clear intermediate bitmap  */
  303.     BltBitMap (ob -> bitmap, 0L, 0L,
  304.            bm, 0L, 0L,
  305.            (long) ob -> width, (long) ob -> height * 10L,
  306.            0L, 0xffL, NULL);
  307.  
  308.     /*  Check to see if explosion is done  */
  309.     if ((oc->frame += oc->dir) > 10 || oc->frame < 1) {
  310.         oc -> frame = -1;
  311.         return;
  312.     }
  313.  
  314.     /*  Expand image vertically by raping intermediate BitMap  */
  315.     bpr = bm -> BytesPerRow;
  316.     bm -> BytesPerRow *= oc -> frame;    /*  Make it look wider  */
  317.     BltBitMap (ob -> bitmap, (long) oc -> xoff, (long) oc -> yoff,
  318.            bm, 0L, 0L,
  319.            (long) ob -> width, (long) ob -> height,
  320.            0xc0L, 0xffL, NULL);
  321.  
  322.     /*
  323.      * We have vertically expanded the bitmap.  We now copy it into
  324.      * the main screen bitmap.
  325.      */
  326.     bm -> BytesPerRow = bpr;    /*  Fix it  */
  327.     high = oc -> frame * (ob -> height - 1) + 1;
  328.     y = oc->y - high/2 + ob->height/2;
  329.     if (y < topbound) {
  330.         by = -(y - topbound);
  331.         high -= by;
  332.         y = topbound;
  333.     } else
  334.         by = 0;
  335.  
  336.     if (y + high >= bottombound)
  337.         high -= y + high - bottombound;
  338.  
  339.     BltBitMap (bm, 0L, by,
  340.            sbm, (long) oc -> x, y,
  341.            (long) ob -> width, high,
  342.            0xe0L, 0xffL, NULL);
  343. }
  344.  
  345. struct BitMap *
  346. getxpmap (oc)
  347. register struct obcontrol *oc;
  348. {
  349.     register struct object    *ob = oc -> ob;
  350.     register struct BitMap    *bm;
  351.     register UWORD        *planes;
  352.     int            high;
  353.  
  354.     high = ob -> height * 10;
  355.  
  356.     if (!(planes = AllocRaster ((long) ob -> width, high * 4L)))
  357.         return (0);
  358.  
  359.     if (!(bm = AllocMem ((long) sizeof (*bm), NULL)))
  360.         return (0);
  361.  
  362.     InitBitMap (bm, 4L, (long) ob -> width, (long) high);
  363.     high *= bm -> BytesPerRow >> 1;
  364.     bm -> Planes[0] = (PLANEPTR) planes;
  365.     bm -> Planes[1] = (PLANEPTR) (planes + high);
  366.     bm -> Planes[2] = (PLANEPTR) (planes + high + high);
  367.     bm -> Planes[3] = (PLANEPTR) (planes + high + high + high);
  368.  
  369.     /*  Clear this intermediate bitmap  */
  370.     BltBitMap (ob -> bitmap, 0L, 0L,
  371.            bm, 0L, 0L,
  372.            (long) ob -> width, ob -> height * 10L,
  373.            0L, 0xffL, NULL);
  374.  
  375.     /*  Return on-screen object to known state  */
  376.     if (oc -> dir > 0)    /*  Only if exploding positively  */
  377.         BltBitMap (ob->bitmap, (long) oc -> xoff, (long) oc -> yoff,
  378.                sbm, (long) oc -> x, (long) oc -> y,
  379.                (long) ob -> width, (long) ob -> height,
  380.                0xc0L, 0xffL, NULL);
  381.  
  382.     return (bm);
  383. }
  384.  
  385.  
  386. /*  Housekeeping  */
  387. openanim ()
  388. {
  389.     NewList (&guys);
  390.     opened = 1;
  391. }
  392.  
  393. closeanim ()
  394. {
  395.     register struct obcontrol    *oc;
  396.     register struct BitMap        *bm;
  397.     int                high;
  398.  
  399.     if (!opened)
  400.         return;
  401.  
  402.     while (oc = RemHead (&guys)) {
  403.         if (bm = (struct BitMap *) oc -> node.ln_Name) {
  404.             if (bm -> Planes[0])
  405. /*- - - - - - - - - - - - - - -*/
  406. FreeRaster (bm -> Planes[0], (long) oc->ob->width, oc->ob->height * 10 * 4L);
  407. /*- - - - - - - - - - - - - - -*/
  408.             FreeMem (bm, (long) sizeof (*bm));
  409.         }
  410.         FreeMem (oc, (long) sizeof (*oc));
  411.     }
  412. }
  413.