home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 377a.lha / libraries / graphics / sprite_bob_anim / animtools / animtools.c < prev    next >
Encoding:
C/C++ Source or Header  |  1980-02-04  |  14.6 KB  |  491 lines

  1. /* Copyright (c) 1990 Commodore-Amiga, Inc.
  2.  *
  3.  * This example is provided in electronic form by Commodore-Amiga, Inc. for
  4.  * use with the 1.3 revisions of the Addison-Wesley Amiga reference manuals. 
  5.  * The 1.3 Addison-Wesley Amiga Reference Manual series contains additional
  6.  * information on the correct usage of the techniques and operating system
  7.  * functions presented in this example.  The source and executable code of
  8.  * this example may only be distributed in free electronic form, via bulletin
  9.  * board or as part of a fully non-commercial and freely redistributable
  10.  * diskette.  Both the source and executable code (including comments) must
  11.  * be included, without modification, in any copy.  This example may not be
  12.  * published in printed form or distributed with any commercial product.
  13.  * However, the programming techniques and support routines set forth in
  14.  * this example may be used in the development of original executable
  15.  * software products for Commodore Amiga computers.
  16.  * All other rights reserved.
  17.  * This example is provided "as-is" and is subject to change; no warranties
  18.  * are made.  All use is at your own risk.  No liability or responsibility
  19.  * is assumed.
  20.  */
  21.  
  22. /* animtools.c 19oct89 original code by Dave Lucas.
  23. ** rework by (CATS)
  24. **
  25. ** This file is a collection of tools which are used with the VSprite, Bob
  26. ** and Animation system software. It is intended as a useful EXAMPLE, and
  27. ** while it shows what must be done, it is not the only way to do it.
  28. ** If Not Enough Memory, or error return, each cleans up after itself
  29. ** before returning.
  30. **
  31. ** NOTE:  these routines assume a very specific structure to the
  32. ** gel lists.  make sure that you use the correct pairs together
  33. ** (i.e. makeOb()/freeOb(), etc.)
  34. **
  35. ** lattice c 5.04
  36. ** lc -b1 -cfist -v -y animtools.c
  37. */
  38.  
  39. #include <exec/types.h>
  40. #include <exec/memory.h>
  41. #include <graphics/gfx.h>
  42. #include <graphics/gels.h>
  43. #include <graphics/clip.h>
  44. #include <graphics/rastport.h>
  45. #include <graphics/view.h>
  46. #include <graphics/gfxbase.h>
  47.  
  48. #include "/animtools/animtools.h"
  49. #include "/animtools/animtools_proto.h"
  50.  
  51. #include <proto/all.h>
  52.  
  53. /*-------------------------------------------------------------
  54. ** setup the gels system.  After this call is made you can use
  55. ** vsprites, bobs, anim comps, and anim obs.
  56. **
  57. ** note that this links the GelsInfo structure into the rast port,
  58. ** and calls InitGels().
  59. **
  60. ** all resources are properly freed on failure.
  61. **
  62. ** It uses information in your RastPort structure to establish
  63. ** boundary collision defaults at the outer edges of the raster.
  64. **
  65. ** This routine sets up for everything - collision detection and all.
  66. **
  67. ** You must already have run LoadView before ReadyGelSys is called.
  68. */
  69. struct GelsInfo *setupGelSys(struct RastPort *rPort, BYTE reserved)
  70. {
  71. struct GelsInfo *gInfo;
  72. struct VSprite  *vsHead;
  73. struct VSprite  *vsTail;
  74.  
  75. if (NULL != (gInfo =
  76.     (struct GelsInfo *)AllocMem((LONG)sizeof(struct GelsInfo), MEMF_CLEAR)))
  77.     {
  78.     if (NULL != (gInfo->nextLine =
  79.         (WORD *)AllocMem((LONG)sizeof(WORD) * 8, MEMF_CLEAR)))
  80.         {
  81.         if (NULL != (gInfo->lastColor =
  82.             (WORD **)AllocMem((LONG)sizeof(LONG) * 8, MEMF_CLEAR)))
  83.             {
  84.             if (NULL != (gInfo->collHandler =
  85.                 (struct collTable *)AllocMem((LONG)sizeof(struct collTable),
  86.                     MEMF_CLEAR)))
  87.                 {
  88.                 if (NULL != (vsHead = (struct VSprite *)AllocMem(
  89.                     (LONG)sizeof(struct VSprite), MEMF_CLEAR)))
  90.                     {
  91.                     if (NULL != (vsTail = (struct VSprite *)AllocMem(
  92.                         (LONG)sizeof(struct VSprite), MEMF_CLEAR)))
  93.                         {
  94.                         gInfo->sprRsrvd      = reserved;
  95.                         gInfo->leftmost      = 1;
  96.                         gInfo->rightmost  =
  97.                             (rPort->BitMap->BytesPerRow << 3) - 1;
  98.                         gInfo->topmost      = 1;
  99.                         gInfo->bottommost = rPort->BitMap->Rows - 1;
  100.  
  101.                         rPort->GelsInfo = gInfo;
  102.  
  103.                         InitGels(vsHead, vsTail, gInfo);
  104.  
  105.                         return(gInfo);
  106.                         }
  107.                     FreeMem(vsHead, (LONG)sizeof(*vsHead));
  108.                     }
  109.                 FreeMem(gInfo->collHandler, (LONG)sizeof(struct collTable));
  110.                 }
  111.             FreeMem(gInfo->lastColor, (LONG)sizeof(LONG) * 8);
  112.             }
  113.         FreeMem(gInfo->nextLine, (LONG)sizeof(WORD) * 8);
  114.         }
  115.     FreeMem(gInfo, (LONG)sizeof(*gInfo));
  116.     }
  117. return(NULL);
  118. }
  119.  
  120. /*-------------------------------------------------------------
  121. ** free all of the stuff allocated by setupGelSys().
  122. ** only call this routine if setupGelSys() returned successfully.
  123. ** the GelsInfo structure is the one returned by setupGelSys().
  124. **
  125. ** It also unlinks the GelsInfo from the RastPort.
  126. */
  127. VOID cleanupGelSys(struct GelsInfo *gInfo, struct RastPort *rPort)
  128. {
  129. rPort->GelsInfo = NULL;
  130.  
  131. FreeMem(gInfo->collHandler, (LONG)sizeof(struct collTable));
  132. FreeMem(gInfo->lastColor, (LONG)sizeof(LONG) * 8);
  133. FreeMem(gInfo->nextLine, (LONG)sizeof(WORD) * 8);
  134. FreeMem(gInfo->gelHead, (LONG)sizeof(struct VSprite));
  135. FreeMem(gInfo->gelTail, (LONG)sizeof(struct VSprite));
  136. FreeMem(gInfo, (LONG)sizeof(*gInfo));
  137. }
  138.  
  139. /*-------------------------------------------------------------
  140. ** create a VSprite from the information given in nVSprite.
  141. ** use freeVSprite() to free this gel.
  142. */
  143. struct VSprite *makeVSprite(NEWVSPRITE *nVSprite)
  144. {
  145. struct VSprite *vsprite;
  146. LONG            line_size;
  147. LONG            plane_size;
  148.  
  149. line_size = (LONG)sizeof(WORD) * nVSprite->nvs_WordWidth;
  150. plane_size = line_size * nVSprite->nvs_LineHeight;
  151.  
  152. if (NULL != (vsprite =
  153.     (struct VSprite *)AllocMem((LONG)sizeof(struct VSprite), MEMF_CLEAR)))
  154.     {
  155.     if (NULL != (vsprite->BorderLine =
  156.         (WORD *)AllocMem(line_size, MEMF_CHIP)))
  157.         {
  158.         if (NULL != (vsprite->CollMask =
  159.             (WORD *)AllocMem(plane_size, MEMF_CHIP)))
  160.             {
  161.             vsprite->Y            = nVSprite->nvs_Y;
  162.             vsprite->X            = nVSprite->nvs_X;
  163.             vsprite->Flags        = nVSprite->nvs_Flags;
  164.             vsprite->Width        = nVSprite->nvs_WordWidth;
  165.             vsprite->Depth        = nVSprite->nvs_ImageDepth;
  166.             vsprite->Height        = nVSprite->nvs_LineHeight;
  167.             vsprite->MeMask        = nVSprite->nvs_MeMask;
  168.             vsprite->HitMask    = nVSprite->nvs_HitMask;
  169.             vsprite->ImageData    = nVSprite->nvs_Image;
  170.             vsprite->SprColors    = nVSprite->nvs_ColorSet;
  171.             vsprite->PlanePick    = 0x00;
  172.             vsprite->PlaneOnOff    = 0x00;
  173.  
  174.             InitMasks(vsprite);
  175.             return(vsprite);
  176.             }
  177.         FreeMem(vsprite->BorderLine, line_size);
  178.         }
  179.     FreeMem(vsprite, (LONG)sizeof(*vsprite));
  180.     }
  181. return(NULL);
  182. }
  183.  
  184. /*-------------------------------------------------------------
  185. ** create a Bob from the information given in nBob.
  186. ** use freeBob() to free this gel.
  187. **
  188. ** A VSprite is created for this bob.
  189. ** This routine properly allocates all double buffered information
  190. ** if it is required.
  191. */
  192. struct Bob *makeBob(NEWBOB *nBob)
  193. {
  194. struct Bob           *bob;
  195. struct VSprite       *vsprite;
  196. NEWVSPRITE            nVSprite ;
  197. LONG                rassize;
  198.  
  199. rassize = (LONG)sizeof(UWORD) *
  200.             nBob->nb_WordWidth * nBob->nb_LineHeight * nBob->nb_RasDepth;
  201.  
  202. if (NULL != (bob =
  203.     (struct Bob *)AllocMem((LONG)sizeof(struct Bob), MEMF_CLEAR)))
  204.     {
  205.     if (NULL != (bob->SaveBuffer = (WORD *)AllocMem(rassize, MEMF_CHIP)))
  206.         {
  207.         nVSprite.nvs_WordWidth    = nBob->nb_WordWidth;
  208.         nVSprite.nvs_LineHeight    = nBob->nb_LineHeight;
  209.         nVSprite.nvs_ImageDepth    = nBob->nb_ImageDepth;
  210.         nVSprite.nvs_Image        = nBob->nb_Image;
  211.         nVSprite.nvs_X            = nBob->nb_X;
  212.         nVSprite.nvs_Y            = nBob->nb_Y;
  213.         nVSprite.nvs_ColorSet    = NULL;
  214.         nVSprite.nvs_Flags        = nBob->nb_BFlags;
  215.         nVSprite.nvs_MeMask        = nBob->nb_MeMask;
  216.         nVSprite.nvs_HitMask    = nBob->nb_HitMask;
  217.  
  218.         if ((vsprite = makeVSprite(&nVSprite)) != NULL)
  219.             {
  220.             vsprite->PlanePick = nBob->nb_PlanePick;
  221.             vsprite->PlaneOnOff = nBob->nb_PlaneOnOff;
  222.  
  223.             vsprite->VSBob     = bob;
  224.             bob->BobVSprite     = vsprite;
  225.             bob->ImageShadow = vsprite->CollMask;
  226.             bob->Flags         = 0;
  227.             bob->Before         = NULL;
  228.             bob->After         = NULL;
  229.             bob->BobComp     = NULL;
  230.  
  231.             if (nBob->nb_DBuf)
  232.                 {
  233.                 if (NULL != (bob->DBuffer = (struct DBufPacket *)AllocMem(
  234.                     (LONG)sizeof(struct DBufPacket), MEMF_CLEAR)))
  235.                     {
  236.                     if (NULL != (bob->DBuffer->BufBuffer =
  237.                         (WORD *)AllocMem(rassize, MEMF_CHIP)))
  238.                         {
  239.                         return(bob);
  240.                         }
  241.                     FreeMem(bob->DBuffer, (LONG)sizeof(struct DBufPacket));
  242.                     }
  243.                 }
  244.             else
  245.                 {
  246.                 bob->DBuffer = NULL;
  247.                 return(bob);
  248.                 }
  249.  
  250.             freeVSprite(vsprite);
  251.             }
  252.         FreeMem(bob->SaveBuffer, rassize);
  253.         }
  254.     FreeMem(bob, (LONG)sizeof(*bob));
  255.     }
  256. return(NULL);
  257. }
  258.  
  259. /*-------------------------------------------------------------
  260. ** create a Animation Component from the information given in nAnimComp
  261. ** and nBob.
  262. ** use freeComp() to free this gel.
  263. **
  264. ** makeComp calls makeBob(), and links the bob into a AnimComp.
  265. */
  266. struct AnimComp *makeComp(NEWBOB *nBob, NEWANIMCOMP *nAnimComp)
  267. {
  268. struct Bob        *compBob;
  269. struct AnimComp    *aComp;
  270.  
  271. if ((aComp = AllocMem((LONG)sizeof(struct AnimComp),MEMF_CLEAR)) != NULL)
  272.     {
  273.     if ((compBob = makeBob(nBob)) != NULL)
  274.         {
  275.         compBob->After     = NULL;  /* Caller can deal with these later. */
  276.         compBob->Before     = NULL;
  277.         compBob->BobComp = aComp;   /* Link 'em up. */
  278.  
  279.         aComp->AnimBob        = compBob;
  280.         aComp->TimeSet        = nAnimComp->nac_Time; /* Num ticks active. */
  281.         aComp->YTrans        = nAnimComp->nac_Yt; /* Offset rel to HeadOb */
  282.         aComp->XTrans        = nAnimComp->nac_Xt;
  283.         aComp->AnimCRoutine    = nAnimComp->nac_Routine;
  284.         aComp->Flags        = nAnimComp->nac_CFlags;
  285.         aComp->Timer        = 0;
  286.         aComp->NextSeq        = NULL;
  287.         aComp->PrevSeq        = NULL;
  288.         aComp->NextComp        = NULL;
  289.         aComp->PrevComp        = NULL;
  290.         aComp->HeadOb        = NULL;
  291.  
  292.         return(aComp);
  293.         }
  294.     FreeMem(aComp, (LONG)sizeof(struct AnimComp));
  295.     }
  296. return(NULL);
  297. }
  298.  
  299. /*-------------------------------------------------------------
  300. ** create an Animation Sequence from the information given in nAnimSeq
  301. ** and nBob.
  302. ** use freeSeq() to free this gel.
  303. **
  304. ** this routine creates a linked list of animation components which
  305. ** make up the animation sequence.
  306. **
  307. ** It links them all up, making a circular list of the PrevSeq
  308. ** and NextSeq pointers. That is to say, the first component of the
  309. ** sequences' PrevSeq points to the last component; the last component of
  310. ** the sequences' NextSeq points back to the first component.
  311. **
  312. ** If dbuf is on, the underlying Bobs'll be set up for double buffering.
  313. ** If singleImage is non-zero, the pImages pointer is assumed to point to
  314. ** an array of only one image, instead of an array of 'count' images, and
  315. ** all Bobs will use the same image.
  316. */
  317. struct AnimComp *makeSeq(NEWBOB *nBob, NEWANIMSEQ *nAnimSeq)
  318. {
  319. int seq;
  320. struct AnimComp *firstCompInSeq = NULL;
  321. struct AnimComp *seqComp = NULL;
  322. struct AnimComp *lastCompMade = NULL;
  323. LONG image_size;
  324. NEWANIMCOMP    nAnimComp;
  325.  
  326. /* get the initial image.  this is the only image that is used
  327. ** if nAnimSeq->nas_SingleImage is non-zero.
  328. */
  329. nBob->nb_Image = nAnimSeq->nas_Images;
  330. image_size = nBob->nb_LineHeight * nBob->nb_ImageDepth * nBob->nb_WordWidth;
  331.  
  332. /* for each comp in the sequence */
  333. for (seq = 0; seq < nAnimSeq->nas_Count; seq++)
  334.     {
  335.     nAnimComp.nac_Xt        = *(nAnimSeq->nas_Xt + seq);
  336.     nAnimComp.nac_Yt        = *(nAnimSeq->nas_Yt + seq);
  337.     nAnimComp.nac_Time        = *(nAnimSeq->nas_Times + seq);
  338.     nAnimComp.nac_Routine    = nAnimSeq->nas_Routines[seq];
  339.     nAnimComp.nac_CFlags    = nAnimSeq->nas_CFlags;
  340.  
  341.     if ((seqComp = makeComp(nBob, &nAnimComp)) == NULL)
  342.         {
  343.         if (firstCompInSeq != NULL)
  344.             freeSeq(firstCompInSeq, (LONG)nBob->nb_RasDepth);
  345.         return(NULL);
  346.         }
  347.  
  348.     seqComp->HeadOb = nAnimSeq->nas_HeadOb;
  349.  
  350.     /* Make a note of where the first component is. */
  351.     if (firstCompInSeq == NULL)
  352.         firstCompInSeq = seqComp;
  353.  
  354.     /* link the component into the list */
  355.     if (lastCompMade != NULL)
  356.         lastCompMade->NextSeq = seqComp;
  357.  
  358.     seqComp->NextSeq = NULL;
  359.     seqComp->PrevSeq = lastCompMade;
  360.     lastCompMade = seqComp;
  361.  
  362.     /* If nAnimSeq->nas_SingleImage is zero,
  363.     ** the image array has nAnimSeq->nas_Count images.
  364.     */
  365.     if (!nAnimSeq->nas_SingleImage)
  366.         nBob->nb_Image += image_size;
  367.     }
  368. /* On The last component in the sequence, set Next/Prev to make
  369. ** the linked list a loop of components.
  370. */
  371. lastCompMade->NextSeq = firstCompInSeq;
  372. firstCompInSeq->PrevSeq = lastCompMade;
  373.  
  374. return(firstCompInSeq);
  375. }
  376.  
  377. /*-------------------------------------------------------------
  378. ** free the data created by makeVSprite()
  379. **
  380. ** assumes images deallocated elsewhere.
  381. */
  382. VOID freeVSprite(struct VSprite *vsprite)
  383. {
  384. LONG    line_size;
  385. LONG    plane_size;
  386.  
  387. line_size = (LONG)sizeof(WORD) * vsprite->Width;
  388. plane_size = line_size * vsprite->Height;
  389.  
  390. FreeMem(vsprite->BorderLine, line_size);
  391. FreeMem(vsprite->CollMask, plane_size);
  392.  
  393. FreeMem(vsprite, (LONG)sizeof(*vsprite));
  394. }
  395.  
  396. /*-------------------------------------------------------------
  397. ** free the data created by makeBob()
  398. **
  399. ** it's important that rasdepth match the depth you
  400. ** passed to makeBob() when this gel was made.
  401. ** assumes images deallocated elsewhere.
  402. */
  403. VOID freeBob(struct Bob *bob, LONG rasdepth)
  404. {
  405. LONG    rassize;
  406.  
  407. rassize =  (LONG)sizeof(UWORD) *
  408.         bob->BobVSprite->Width * bob->BobVSprite->Height * rasdepth;
  409.  
  410. if (bob->DBuffer != NULL)
  411.     {
  412.     FreeMem(bob->DBuffer->BufBuffer, rassize);
  413.     FreeMem(bob->DBuffer, (LONG)sizeof(struct DBufPacket));
  414.     }
  415. FreeMem(bob->SaveBuffer, rassize);
  416. freeVSprite(bob->BobVSprite);
  417. FreeMem(bob, (LONG)sizeof(*bob));
  418. }
  419.  
  420. /*-------------------------------------------------------------
  421. ** free the data created by makeComp()
  422. **
  423. ** it's important that rasdepth match the depth you
  424. ** passed to makeComp() when this gel was made.
  425. ** assumes images deallocated elsewhere.
  426. */
  427. VOID freeComp(struct AnimComp *myComp, LONG rasdepth)
  428. {
  429. freeBob(myComp->AnimBob, rasdepth);
  430. FreeMem(myComp, (LONG)sizeof(struct AnimComp));
  431. }
  432.  
  433. /*-------------------------------------------------------------
  434. ** free the data created by makeSeq()
  435. **
  436. ** Complimentary to makeSeq(), this routine goes through the NextSeq
  437. ** pointers and frees the Components
  438. **
  439. ** This routine only goes forward through the list, and so
  440. ** it must be passed the first component in the sequence, or the sequence
  441. ** must be circular (which is guaranteed if you use makeSeq()).
  442. **
  443. ** it's important that rasdepth match the depth you
  444. ** passed to makeSeq() when this gel was made.
  445. ** assumes images deallocated elsewhere.
  446. */
  447. VOID freeSeq(struct AnimComp *headComp, LONG rasdepth)
  448. {
  449. struct AnimComp *curComp;
  450. struct AnimComp *nextComp;
  451.  
  452. /* this is freeing a loop of AnimComps, hooked together by the
  453. ** NextSeq and PrevSeq pointers.
  454. */
  455.  
  456. /* break the NextSeq loop, so we get a NULL at the end of the list. */
  457. headComp->PrevSeq->NextSeq = NULL;
  458.  
  459. curComp = headComp;            /* get the start of the list */
  460. while (curComp != NULL)
  461.     {
  462.     nextComp = curComp->NextSeq;
  463.     freeComp(curComp, rasdepth);
  464.     curComp = nextComp;
  465.     }
  466. }
  467.  
  468. /*-------------------------------------------------------------
  469. ** free an animation object (list of sequences).
  470. **
  471. ** freeOb() goes through the NextComp pointers, starting at the AnimObs'
  472. ** HeadComp, and frees every sequence.
  473. ** it only goes forward. It then frees the Object itself.
  474. ** assumes images deallocated elsewhere.
  475. */
  476. VOID freeOb(struct AnimOb *headOb, LONG rasdepth)
  477. {
  478. struct AnimComp *curSeq;
  479. struct AnimComp *nextSeq;
  480.  
  481. curSeq = headOb->HeadComp;            /* get the start of the list */
  482. while (curSeq != NULL)
  483.     {
  484.     nextSeq = curSeq->NextComp;
  485.     freeSeq(curSeq, rasdepth);
  486.     curSeq = nextSeq;
  487.     }
  488.  
  489. FreeMem(headOb, (LONG)sizeof(struct AnimOb));
  490. }
  491.