home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / tblt / tblt⁄anim.c next >
Encoding:
Text File  |  1986-09-08  |  7.3 KB  |  254 lines  |  [TEXT/MACA]

  1. /*
  2.  * anim.c - animation routines for Tablut.
  3.  *
  4.  */
  5.  
  6. #include <quickdraw.h>
  7. #include <window.h>
  8. #include <event.h>
  9. #include <desk.h>
  10. #include <toolutil.h>
  11. #define watchCursor 4    /* Should be in toolutil.h but isn't    */
  12. #include <memory.h>
  13. #include "tablut.h"
  14.  
  15. #define DRAGTICKS   4    /* number of ticks per drag animation frame */
  16. #define SWEEPTICKS  4    /* ticks per sweep animation frame    */
  17. #define VELOCITY   40    /* distance to cover per sweep frame    */
  18. #define FRAC     32    /* fraction of a pixel error in sweep delta */
  19. #define BLINKCOUNT  3    /* # of times to blink a thing    */
  20. #define BLINKTICKS 15    /* duration of 1/2 of a blink        */
  21.  
  22. #define CURSWHITE 129    /* Resource ID for the white cursor    */
  23. #define CURSBLACK 130    /* Resource ID for the black cursor    */
  24.  
  25. CursHandle curswhite;    /* the "it's white's move" cursor    */
  26. CursHandle cursblack;    /* the "it's black's move" cursor    */
  27. CursHandle cursnorm;    /* a placeholder for the normal cursor    */
  28.  
  29. /*
  30.  * dragpiece() - given a piece index & an initial mouse position,
  31.  *  follow the mouse with the piece until the mouse button is released.
  32.  */
  33. dragpiece(pidx, startp)
  34. int pidx;        /* index of point to drag        */
  35. Point *startp;        /* starting mouse position        */
  36. {
  37.     Point startc;        /* piece center starting point    */
  38.     Point minloc, maxloc;    /* bounds of the tracking        */
  39.     int horzhold;        /* if true, we are only moving vertically */
  40.     Point adelta;        /* absolute difference between two points */
  41.     Point mtocent;        /* offset from mouse to center of piece    */
  42.     Point loc;        /* current mouse location        */
  43.     long nexttick;        /* when to take another look at the mouse */
  44.     struct pieceimage *p;    /* pointer to the piece being dragged    */
  45.  
  46.     p = &piece[pidx];
  47.     horzhold = 0;
  48.     startc.h = p->prevlook.bounds.left;
  49.     startc.v = p->prevlook.bounds.top;
  50.     AddPt(pass(p->class->etoc), &startc);
  51.     mtocent.h = startc.h - startp->h;  mtocent.v = startc.v - startp->v;
  52.  
  53.     if (!insetup) {
  54.     findbounds(pidx, &minloc, &maxloc);
  55.     gridtopoint(&minloc);
  56.     gridtopoint(&maxloc);
  57.     }
  58.  
  59.     nexttick = TickCount();
  60.     while (StillDown()) {
  61.     GetMouse(&loc);
  62.     SystemTask();        /* give those desk accessories a moment    */
  63.     if (TickCount() >= nexttick) {
  64.         nexttick += DRAGTICKS;
  65.         AddPt(pass(mtocent), &loc);
  66.         if (!insetup) {
  67.         adelta.h = startc.h - loc.h;
  68.         adelta.v = startc.v - loc.v;
  69.         if (adelta.h < 0) adelta.h = -adelta.h;
  70.         if (adelta.v < 0) adelta.v = -adelta.v;
  71.         if ((horzhold && adelta.v <= p->class->etoc.v) ||
  72.           (!horzhold && adelta.h <= p->class->etoc.h)) {
  73.             horzhold = adelta.v > adelta.h;
  74.         }
  75.         if (horzhold) {
  76.             /* constrain the vertical */
  77.             loc.h = startc.h;
  78.             if (loc.v > maxloc.v) loc.v = maxloc.v;
  79.             if (loc.v < minloc.v) loc.v = minloc.v;
  80.         } else {
  81.             /* constrain the horizontal */
  82.             loc.v = startc.v;
  83.             if (loc.h > maxloc.h) loc.h = maxloc.h;
  84.             if (loc.h < minloc.h) loc.h = minloc.h;
  85.         }
  86.         }
  87.         drawpiece(pidx, loc.h, loc.v);
  88.     }
  89.     }
  90. }
  91.  
  92. /*
  93.  * sweeppiece() - sweep the given piece from its current position
  94.  *  to the given destination.
  95.  */
  96. sweeppiece(pidx, destp)
  97. int pidx;        /* index of the piece to move        */
  98. Point *destp;        /* where to move to            */
  99. {
  100.     struct pieceimage *p;
  101.     Point delta;    /* (signed) distance to cover (in some sense)*/
  102.     Point absdelta;    /* absolute distance (temporary)         */
  103.     int count;        /* number of updates remaining in the move   */
  104.     Point loc;        /* current location (as the move progresses) */
  105.     Point nxtloc;    /* next real location to move to         */
  106.     long nexttick;    /* when to make another part of the move     */
  107.  
  108.     p = &piece[pidx];
  109.     if (!onscreen(p)) {
  110.     drawpiece(pidx, destp->h, destp->v);
  111.     return;
  112.     }
  113.     loc.h = p->prevlook.bounds.left + p->class->etoc.h;
  114.     loc.v = p->prevlook.bounds.top + p->class->etoc.v;
  115.     delta.h = (destp->h - loc.h) * FRAC; /* fixed-point total delta */
  116.     delta.v = (destp->v - loc.v) * FRAC;
  117.     absdelta.h = (delta.h < 0) ? -delta.h : delta.h;
  118.     absdelta.v = (delta.v < 0) ? -delta.v : delta.v;
  119.     if (absdelta.h > absdelta.v) count = absdelta.h / (VELOCITY * FRAC);
  120.     else count = absdelta.v / (VELOCITY * FRAC);
  121.     if (count > 0) {
  122.     delta.h /= count;        /* fixed-point delta per frame */
  123.     delta.v /= count;
  124.     loc.h *= FRAC;
  125.     loc.v *= FRAC;
  126.     nexttick = TickCount();
  127.     while (count > 0) {
  128.         SystemTask();
  129.         if (TickCount() >= nexttick) {
  130.         nexttick += SWEEPTICKS;
  131.         --count;
  132.         AddPt(pass(delta), &loc);
  133.         nxtloc.h = loc.h / FRAC;
  134.         nxtloc.v = loc.v / FRAC;
  135.         drawpiece(pidx, nxtloc.h, nxtloc.v);
  136.         }
  137.     }
  138.     }
  139.     drawpiece(pidx, destp->h, destp->v);
  140. }
  141.  
  142. /*
  143.  * blinksquares() - given a list of board-squares, blink the set on and
  144.  *  off BLINKCOUNT times.
  145.  */
  146. blinksquares(first, last)
  147. Point *first, *last;    /* first and last squares (in an array) */
  148. {
  149.     int i,j;
  150.     Point *p;
  151.     Rect r;
  152.     long nexttick;
  153.  
  154.     nexttick = TickCount() + 1;
  155.     while (TickCount() < nexttick) {
  156.     SystemTask();
  157.     }
  158.     nexttick += BLINKTICKS;
  159.     for (i = 0; i < BLINKCOUNT; ++i) {
  160.     for (j = 0; j < 2; ++j) {
  161.         for (p = first; p <= last; ++p) {
  162.         gridtorect(p, &r);
  163.         lightrect(&r);
  164.         }
  165.         while (TickCount() < nexttick) {
  166.         SystemTask();
  167.         }
  168.         nexttick += BLINKTICKS;
  169.     }
  170.     }
  171. }
  172.  
  173. /*
  174.  * findbounds() - given a piece index and where to put the results,
  175.  *   find the grid-coordinate limits to the legal movement of that piece.
  176.  */
  177. findbounds(pidx, minp, maxp)
  178. int pidx;        /* index of the piece to examine        */
  179. Point *minp, *maxp;    /* where to put the min & max grid limits    */
  180. {
  181.     struct pieceimage *p;
  182.     struct pieceimage *tp;
  183.  
  184.     p = &piece[pidx];
  185.     SetPt(minp, -4, -4);  SetPt(maxp, 4, 4);    /* board boundaries    */
  186.     for (tp = &piece[0]; tp < &piece[NUMPIECES]; ++tp) {
  187.     if (!onboard(tp) || tp == p) {
  188.         continue;
  189.     }
  190.     if (tp->grid.h == p->grid.h) {  /* same column (vertical)    */
  191.         if (tp->grid.v < p->grid.v) {
  192.         if (tp->grid.v >= minp->v) minp->v = tp->grid.v + 1;
  193.         } else {
  194.         if (tp->grid.v <= maxp->v) maxp->v = tp->grid.v - 1;
  195.         }
  196.     } else if (tp->grid.v == p->grid.v) {  /* same row (horizontal) */
  197.         if (tp->grid.h < p->grid.h) {
  198.         if (tp->grid.h >= minp->h) minp->h = tp->grid.h + 1;
  199.         } else {
  200.         if (tp->grid.h <= maxp->h) maxp->h = tp->grid.h - 1;
  201.         }
  202.     }
  203.     }
  204. }
  205.  
  206. /*
  207.  * getcursors() - read the cursor resources for Tablut
  208.  */
  209. getcursors()
  210. {
  211.     curswhite = GetCursor(CURSWHITE);
  212.     cursblack = GetCursor(CURSBLACK);
  213.     cursnorm = (CursHandle) -1;
  214. }
  215.  
  216. /*
  217.  * fixcursor() - given the location of the mouse, set the cursor
  218.  * appropriately
  219.  * (assuming that the cursor hasn't been tampered with).
  220.  * GetPort() is used here rather than FrontWindow() because this routine
  221.  * can be called between events (when the newly-selected front window
  222.  * may not yet be active).
  223.  */
  224. fixcursor(wherep, keys)
  225. Point *wherep;    /* where the mouse currently is                */
  226. KeyMap keys;    /* what keys are down (e.g., option or command keys)    */
  227. {
  228.     static CursHandle prevc = (CursHandle) -1;    /* "normal" to start with */
  229.     CursHandle newc;                /* what the new cursor is */
  230.     WindowPtr whichwindow;        /* the currently active window    */
  231.  
  232.     GetPort(&whichwindow);
  233.     if (insetup || whichwindow != mywindow || 
  234.       !PtInRect(pass(*wherep), &boardrect)) {
  235.     newc = cursnorm;
  236.     } else {
  237.     if (blacksmove()) {
  238.         newc = cursblack;
  239.     } else {
  240.         newc = curswhite;
  241.     }
  242.     }
  243.     if (newc != prevc) {
  244.     if (newc == cursnorm) {
  245.         InitCursor();
  246.     } else {
  247.         HLock((Handle) newc);
  248.         SetCursor(*newc);
  249.         HUnlock((Handle) newc);
  250.     }
  251.     prevc = newc;
  252.     }
  253. }
  254.