home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #9 / Amiga Plus CD - 2004 - No. 09.iso / amigaplus / games / saga / source / animtools.c next >
Encoding:
C/C++ Source or Header  |  2004-08-03  |  14.4 KB  |  348 lines

  1. /* animtools.c
  2. **
  3. ** This file is a collection of tools which are used with the VSprite, Bob and Animation
  4. ** system software. It is intended as a useful EXAMPLE, and while it shows what must be
  5. ** done, it is not the only way to do it.  If Not Enough Memory, or error return, each
  6. ** cleans up after itself before returning.  NOTE that these routines assume a very specific
  7. ** structure to the GEL lists.  Make sure that you use the correct pairs together
  8. ** (i.e. makeOb()/freeOb(), etc.)
  9. **
  10. ** Compile with SAS/C 5.10b: lc -b1 -cfist -v -y -oanimtools.o animtools.c
  11. */
  12. #include <exec/types.h>
  13. #include <exec/memory.h>
  14. #include <graphics/gfx.h>
  15. #include <graphics/gels.h>
  16. #include <graphics/clip.h>
  17. #include <graphics/rastport.h>
  18. #include <graphics/view.h>
  19. #include <graphics/gfxbase.h>
  20. #include "animtools.h"
  21.  
  22.  
  23. /* Setup the GELs system.  After this call is made you can use VSprites, Bobs, AnimComps
  24. ** and AnimObs.  Note that this links the GelsInfo structure into the RastPort, and calls
  25. ** InitGels().  It uses information in your RastPort structure to establish boundary collision
  26. ** defaults at the outer edges of the raster.  This routine sets up for everything - collision
  27. ** detection and all. You must already have run LoadView before ReadyGelSys is called.
  28. */
  29. struct GelsInfo *setupGelSys(struct RastPort *rPort, BYTE reserved)
  30. {
  31. struct GelsInfo *gInfo;
  32. struct VSprite  *vsHead;
  33. struct VSprite  *vsTail;
  34.  
  35. if (NULL != (gInfo = (struct GelsInfo *)AllocMem(sizeof(struct GelsInfo), MEMF_CLEAR)))
  36.         {
  37.         if (NULL != (gInfo->nextLine = (WORD *)AllocMem(sizeof(WORD) * 8, MEMF_CLEAR)))
  38.             {
  39.             if (NULL != (gInfo->lastColor = (WORD **)AllocMem(sizeof(LONG) * 8, MEMF_CLEAR)))
  40.                 {
  41.                 if (NULL != (gInfo->collHandler = (struct collTable *)
  42.                         AllocMem(sizeof(struct collTable),MEMF_CLEAR)))
  43.                     {
  44.                     if (NULL != (vsHead = (struct VSprite *)
  45.                             AllocMem((LONG)sizeof(struct VSprite), MEMF_CLEAR)))
  46.                         {
  47.                         if (NULL != (vsTail = (struct VSprite *)
  48.                                 AllocMem(sizeof(struct VSprite), MEMF_CLEAR)))
  49.                             {
  50.                             gInfo->sprRsrvd   = reserved;
  51.                             /* Set left- and top-most to 1 to better keep items */
  52.                             /* inside the display boundaries.                   */
  53.                             gInfo->leftmost   = gInfo->topmost    = 1;
  54.                             gInfo->rightmost  = (rPort->BitMap->BytesPerRow << 3) - 1;
  55.                             gInfo->bottommost = rPort->BitMap->Rows - 1;
  56.                             rPort->GelsInfo = gInfo;
  57.                             InitGels(vsHead, vsTail, gInfo);
  58.                             return(gInfo);
  59.                             }
  60.                         FreeMem(vsHead, (LONG)sizeof(*vsHead));
  61.                         }
  62.                     FreeMem(gInfo->collHandler, (LONG)sizeof(struct collTable));
  63.                     }
  64.                 FreeMem(gInfo->lastColor, (LONG)sizeof(LONG) * 8);
  65.                 }
  66.             FreeMem(gInfo->nextLine, (LONG)sizeof(WORD) * 8);
  67.             }
  68.         FreeMem(gInfo, (LONG)sizeof(*gInfo));
  69.         }
  70. return(NULL);
  71. }
  72.  
  73.  
  74. /* Free all of the stuff allocated by setupGelSys().  Only call this routine if
  75. ** setupGelSys() returned successfully.  The GelsInfo structure is the one returned
  76. ** by setupGelSys().   It also unlinks the GelsInfo from the RastPort.
  77. */
  78. VOID cleanupGelSys(struct GelsInfo *gInfo, struct RastPort *rPort)
  79. {
  80. rPort->GelsInfo = NULL;
  81. FreeMem(gInfo->collHandler, (LONG)sizeof(struct collTable));
  82. FreeMem(gInfo->lastColor, (LONG)sizeof(LONG) * 8);
  83. FreeMem(gInfo->nextLine, (LONG)sizeof(WORD) * 8);
  84. FreeMem(gInfo->gelHead, (LONG)sizeof(struct VSprite));
  85. FreeMem(gInfo->gelTail, (LONG)sizeof(struct VSprite));
  86. FreeMem(gInfo, (LONG)sizeof(*gInfo));
  87. }
  88.  
  89.  
  90. /* Create a VSprite from the information given in nVSprite.  Use freeVSprite()
  91. ** to free this GEL.
  92. */
  93. struct VSprite *makeVSprite(NEWVSPRITE *nVSprite)
  94. {
  95. struct VSprite *vsprite;
  96. LONG            line_size;
  97. LONG            plane_size;
  98.  
  99. line_size = sizeof(WORD) * nVSprite->nvs_WordWidth;
  100. plane_size = line_size * nVSprite->nvs_LineHeight;
  101.  
  102. if (NULL != (vsprite = (struct VSprite *)AllocMem((LONG)sizeof(struct VSprite), MEMF_CLEAR)))
  103.         {
  104.         if (NULL != (vsprite->BorderLine = (WORD *)AllocMem(line_size, MEMF_CHIP)))
  105.             {
  106.             if (NULL != (vsprite->CollMask = (WORD *)AllocMem(plane_size, MEMF_CHIP)))
  107.                 {
  108.                 vsprite->Y          = nVSprite->nvs_Y;
  109.                 vsprite->X          = nVSprite->nvs_X;
  110.                 vsprite->Flags      = nVSprite->nvs_Flags;
  111.                 vsprite->Width      = nVSprite->nvs_WordWidth;
  112.                 vsprite->Depth      = nVSprite->nvs_ImageDepth;
  113.                 vsprite->Height     = nVSprite->nvs_LineHeight;
  114.                 vsprite->MeMask     = nVSprite->nvs_MeMask;
  115.                 vsprite->HitMask    = nVSprite->nvs_HitMask;
  116.                 vsprite->ImageData  = nVSprite->nvs_Image;
  117.                 vsprite->SprColors  = nVSprite->nvs_ColorSet;
  118.                 vsprite->PlanePick  = vsprite->PlaneOnOff = 0x00;
  119.                 InitMasks(vsprite);
  120.                 return(vsprite);
  121.                 }
  122.             FreeMem(vsprite->BorderLine, line_size);
  123.             }
  124.         FreeMem(vsprite, (LONG)sizeof(*vsprite));
  125.         }
  126. return(NULL);
  127. }
  128.  
  129. /* Create a Bob from the information given in nBob.  Use freeBob() to free this GEL.
  130. ** A VSprite is created for this bob.  This routine properly allocates all double
  131. ** buffered information if it is required.
  132. */
  133. struct Bob *makeBob(NEWBOB *nBob)
  134. {   struct Bob*     bob;
  135.     struct VSprite* vsprite;
  136.     NEWVSPRITE      nVSprite;
  137.     LONG            rassize;
  138.  
  139.     rassize = (LONG)sizeof(UWORD) * nBob->nb_WordWidth * nBob->nb_LineHeight * nBob->nb_RasDepth;
  140.  
  141.     if (NULL != (bob = (struct Bob *)AllocMem((LONG)sizeof(struct Bob), MEMF_CLEAR)))
  142.     {   if (NULL != (bob->SaveBuffer = (WORD *)AllocMem(rassize, MEMF_CHIP)))
  143.         {   nVSprite.nvs_WordWidth  = nBob->nb_WordWidth;
  144.             nVSprite.nvs_LineHeight = nBob->nb_LineHeight;
  145.             nVSprite.nvs_ImageDepth = nBob->nb_ImageDepth;
  146.             nVSprite.nvs_Image      = nBob->nb_Image;
  147.             nVSprite.nvs_X          = nBob->nb_X;
  148.             nVSprite.nvs_Y          = nBob->nb_Y;
  149.             nVSprite.nvs_ColorSet   = NULL;
  150.             nVSprite.nvs_Flags      = nBob->nb_BFlags;
  151.             /* Push the values into the NEWVSPRITE structure for use in makeVSprite(). */
  152.             nVSprite.nvs_MeMask     = nBob->nb_MeMask;
  153.             nVSprite.nvs_HitMask    = nBob->nb_HitMask;
  154.  
  155.             if ((vsprite = makeVSprite(&nVSprite)) != NULL)
  156.             {   vsprite->PlanePick  = nBob->nb_PlanePick;
  157.                 vsprite->PlaneOnOff = nBob->nb_PlaneOnOff;
  158.                 vsprite->VSBob      = bob;
  159.                 bob->BobVSprite     = vsprite;
  160.                 bob->ImageShadow    = vsprite->CollMask;
  161.                 bob->Flags          = 0;
  162.                 bob->Before         = NULL;
  163.                 bob->After          = NULL;
  164.                 bob->BobComp        = NULL;
  165.  
  166.                 if (nBob->nb_DBuf)
  167.                 {   if (NULL != (bob->DBuffer = (struct DBufPacket *) AllocMem((LONG)sizeof(struct DBufPacket), MEMF_CLEAR)))
  168.                     {   if (NULL != (bob->DBuffer->BufBuffer = (WORD *)AllocMem(rassize, MEMF_CHIP)))
  169.                             return(bob);
  170.                         FreeMem(bob->DBuffer, (LONG)sizeof(struct DBufPacket));
  171.                 }   }
  172.                 else
  173.                 {   bob->DBuffer = NULL;
  174.                     return(bob);
  175.                 }
  176.                 freeVSprite(vsprite);
  177.             }
  178.             FreeMem(bob->SaveBuffer, rassize);
  179.         }
  180.         FreeMem(bob, (LONG)sizeof(*bob));
  181.     }
  182.     return(NULL);
  183. }
  184.  
  185. /*
  186. ** Create a Animation Component from the information given in nAnimComp and nBob.  Use
  187. ** freeComp() to free this GEL.  makeComp() calls makeBob(), and links the Bob into an AnimComp.
  188. */
  189. struct AnimComp *makeComp(NEWBOB *nBob, NEWANIMCOMP *nAnimComp)
  190. {   struct Bob      *compBob;
  191.     struct AnimComp *aComp;
  192.  
  193.     if ((aComp = AllocMem((LONG)sizeof(struct AnimComp),MEMF_CLEAR)) != NULL)
  194.     {   if ((compBob = makeBob(nBob)) != NULL)
  195.         {   compBob->After      = compBob->Before  = NULL;
  196.             compBob->BobComp    = aComp;               /* Link 'em up               */
  197.             aComp->AnimBob      = compBob;
  198.             aComp->TimeSet      = nAnimComp->nac_Time; /* Num ticks active          */
  199.             aComp->YTrans       = nAnimComp->nac_Yt;   /* Offset relative to HeadOb */
  200.             aComp->XTrans       = nAnimComp->nac_Xt;
  201.             aComp->AnimCRoutine = nAnimComp->nac_Routine;
  202.             aComp->Flags        = nAnimComp->nac_CFlags;
  203.             aComp->Timer        = 0;
  204.             aComp->NextSeq      = aComp->PrevSeq  = NULL;
  205.             aComp->NextComp     = aComp->PrevComp = NULL;
  206.             aComp->HeadOb       = NULL;
  207.             return(aComp);
  208.         }
  209.         FreeMem(aComp, (LONG)sizeof(struct AnimComp));
  210.     }
  211.     return(NULL);
  212. }
  213.  
  214. /* Create an Animation Sequence from the information given in nAnimSeq and nBob.  Use
  215. ** freeSeq() to free this GEL.  This routine creates a linked list of animation components
  216. ** which make up the animation sequence.  It links them all up, making a circular list of
  217. ** the PrevSeq and NextSeq pointers. That is to say, the first component of the sequences'
  218. ** PrevSeq points to the last component; the last component of * the sequences' NextSeq
  219. ** points back to the first component.  If dbuf is on, the underlying Bobs will be set up
  220. ** for double buffering.  If singleImage is non-zero, the pImages pointer is assumed to
  221. ** point to an array of only one image, instead of an array of 'count' images, and all
  222. ** Bobs will use the same image.
  223. */
  224. struct AnimComp *makeSeq(NEWBOB *nBob, NEWANIMSEQ *nAnimSeq)
  225. {
  226. int seq;
  227. struct AnimComp *firstCompInSeq = NULL;
  228. struct AnimComp *seqComp /* = NULL */ ;
  229. struct AnimComp *lastCompMade = NULL;
  230. LONG image_size;
  231. NEWANIMCOMP nAnimComp;
  232.  
  233. /* get the initial image.  this is the only image that is used
  234. ** if nAnimSeq->nas_SingleImage is non-zero.
  235. */
  236. nBob->nb_Image = nAnimSeq->nas_Images;
  237. image_size = nBob->nb_LineHeight * nBob->nb_ImageDepth * nBob->nb_WordWidth;
  238.  
  239. /* for each comp in the sequence */
  240. for (seq = 0; seq < nAnimSeq->nas_Count; seq++)
  241.         {
  242.         nAnimComp.nac_Xt        = *(nAnimSeq->nas_Xt + seq);
  243.         nAnimComp.nac_Yt        = *(nAnimSeq->nas_Yt + seq);
  244.         nAnimComp.nac_Time      = *(nAnimSeq->nas_Times + seq);
  245.         nAnimComp.nac_Routine   = nAnimSeq->nas_Routines[seq];
  246.         nAnimComp.nac_CFlags    = nAnimSeq->nas_CFlags;
  247.         if ((seqComp = makeComp(nBob, &nAnimComp)) == NULL)
  248.             {
  249.             if (firstCompInSeq != NULL)
  250.                 freeSeq(firstCompInSeq, (LONG)nBob->nb_RasDepth);
  251.             return(NULL);
  252.             }
  253.         seqComp->HeadOb = nAnimSeq->nas_HeadOb;
  254.         /* Make a note of where the first component is. */
  255.         if (firstCompInSeq == NULL) firstCompInSeq = seqComp;
  256.         /* link the component into the list */
  257.         if (lastCompMade != NULL) lastCompMade->NextSeq = seqComp;
  258.         seqComp->NextSeq = NULL;
  259.         seqComp->PrevSeq = lastCompMade;
  260.         lastCompMade = seqComp;
  261.         /* If nAnimSeq->nas_SingleImage is zero, the image array has nAnimSeq->nas_Count images. */
  262.         if (!nAnimSeq->nas_SingleImage)
  263.             nBob->nb_Image += image_size;
  264.         }
  265. /* On The last component in the sequence, set Next/Prev to make */
  266. /* the linked list a loop of components.                        */
  267. lastCompMade->NextSeq = firstCompInSeq;
  268. firstCompInSeq->PrevSeq = lastCompMade;
  269.  
  270. return(firstCompInSeq);
  271. }
  272.  
  273.  
  274. /* Free the data created by makeVSprite().  Assumes images deallocated elsewhere. */
  275. VOID freeVSprite(struct VSprite *vsprite)
  276. {
  277. LONG    line_size;
  278. LONG    plane_size;
  279.  
  280. line_size = (LONG)sizeof(WORD) * vsprite->Width;
  281. plane_size = line_size * vsprite->Height;
  282. FreeMem(vsprite->BorderLine, line_size);
  283. FreeMem(vsprite->CollMask, plane_size);
  284. FreeMem(vsprite, (LONG)sizeof(*vsprite));
  285. }
  286.  
  287. /* Free the data created by makeBob().  It's important that rasdepth match the depth you */
  288. /* passed to makeBob() when this gel was made. Assumes images deallocated elsewhere.     */
  289. VOID freeBob(struct Bob *bob, LONG rasdepth)
  290. {   LONG rassize = sizeof(UWORD) * bob->BobVSprite->Width * bob->BobVSprite->Height * rasdepth;
  291.  
  292.     if (bob->DBuffer != NULL)
  293.     {   FreeMem(bob->DBuffer->BufBuffer, rassize);
  294.         FreeMem(bob->DBuffer, (LONG)sizeof(struct DBufPacket));
  295.     }
  296.     FreeMem(bob->SaveBuffer, rassize);
  297.     freeVSprite(bob->BobVSprite);
  298.     FreeMem(bob, (LONG)sizeof(*bob));
  299. }
  300.  
  301. /* Free the data created by makeComp().  It's important that rasdepth match the depth you */
  302. /* passed to makeComp() when this GEL was made. Assumes images deallocated elsewhere.    */
  303. VOID freeComp(struct AnimComp *myComp, LONG rasdepth)
  304. {
  305. freeBob(myComp->AnimBob, rasdepth);
  306. FreeMem(myComp, (LONG)sizeof(struct AnimComp));
  307. }
  308.  
  309.  
  310. /* Free the data created by makeSeq().  Complimentary to makeSeq(), this routine goes through
  311. ** the NextSeq pointers and frees the Components.  This routine only goes forward through the
  312. ** list, and so it must be passed the first component in the sequence, or the sequence must
  313. ** be circular (which is guaranteed if you use makeSeq()).  It's important that rasdepth match
  314. ** the depth you passed to makeSeq() when this gel was made.   Assumes images deallocated elsewhere!
  315. */
  316. VOID freeSeq(struct AnimComp *headComp, LONG rasdepth)
  317. {   struct AnimComp *curComp,
  318.                     *nextComp;
  319.  
  320.     /* Break the NextSeq loop, so we get a NULL at the end of the list. */
  321.     headComp->PrevSeq->NextSeq = NULL;
  322.  
  323.     curComp = headComp; /* get the start of the list */
  324.     while (curComp != NULL)
  325.     {   nextComp = curComp->NextSeq;
  326.         freeComp(curComp, rasdepth);
  327.         curComp = nextComp;
  328. }   }
  329.  
  330. /* Free an animation object (list of sequences).  freeOb() goes through the NextComp
  331. ** pointers, starting at the AnimObs' HeadComp, and frees every sequence.  It only
  332. ** goes forward. It then frees the Object itself.  Assumes images deallocated elsewhere!
  333. */
  334. VOID freeOb(struct AnimOb *headOb, LONG rasdepth)
  335. {
  336. struct AnimComp *curSeq;
  337. struct AnimComp *nextSeq;
  338.  
  339. curSeq = headOb->HeadComp;          /* get the start of the list */
  340. while (curSeq != NULL)
  341.         {
  342.         nextSeq = curSeq->NextComp;
  343.         freeSeq(curSeq, rasdepth);
  344.         curSeq = nextSeq;
  345.         }
  346. FreeMem(headOb, sizeof(struct AnimOb));
  347. }
  348.