home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 February / macformat-047.iso / Shareware Plus / Developers / Flame / flames.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-20  |  13.4 KB  |  505 lines  |  [TEXT/CWIE]

  1. #include "flame.h"
  2.  
  3. #define maxColors    256
  4.  
  5. short Rand(short max);
  6. long Abs(long theLong);
  7.  
  8. OSErr SetUpFlames(CTabHandle flamePalette, CTabHandle destPalette,
  9.                     Rect *bounds, char speed, FlamePtr *theFlame)
  10. {
  11. short    i,
  12.         j,
  13.         closest;
  14. long     tempRed,
  15.         tempGreen,
  16.         tempBlue,
  17.         currentTotal,
  18.         closestTotal;    
  19. Rect    tempRect;
  20. long    height, width;
  21.  
  22. *theFlame = (FlamePtr) NewPtr(sizeof(Flame) + sizeof(IndexNum) * ((*flamePalette)->ctSize));
  23. tempRect = *bounds;
  24. tempRect.right = tempRect.right - tempRect.left;
  25. tempRect.bottom = tempRect.bottom - tempRect.top;
  26. tempRect.left = tempRect.top = 0;
  27.  
  28. height = (*flamePalette)->ctSize / 4;
  29. if (height < tempRect.bottom || speed % 2 == 1)
  30.     height = tempRect.bottom;
  31. width =  tempRect.right;
  32.  
  33. if (speed == lowRes2)
  34. {
  35.     width = (width + 1) >> 1;
  36.     height = (height + 1) >> 1;
  37. }
  38.  
  39. if (speed == lowRes4)
  40. {
  41.     width = (width + 1) >> 2;
  42.     height = (height + 1) >> 2;
  43. }
  44.  
  45. (**theFlame).speedUp = speed;
  46. (**theFlame).baseAddr = NewPtrClear(width * (height + 3));
  47. if ((**theFlame).baseAddr == nil)
  48. {
  49.     return MemError();
  50. }
  51.  
  52. tempRect.right = width;
  53. tempRect.bottom = height;
  54. (**theFlame).bounds = tempRect;
  55. (**theFlame).topLine = tempRect.bottom + 1;
  56. (**theFlame).rowBytes = tempRect.right;
  57. (**theFlame).fColSize = (*flamePalette)->ctSize;
  58. for (i = 0; i < (**theFlame).fColSize; i++)
  59. {
  60.     for(j = 0; j < (**destPalette).ctSize; j++)
  61.     {
  62.         tempRed = (**destPalette).ctTable[j].rgb.red - (**flamePalette).ctTable[i].rgb.red;
  63.         tempGreen = (**destPalette).ctTable[j].rgb.green - (**flamePalette).ctTable[i].rgb.green;
  64.         tempBlue = (**destPalette).ctTable[j].rgb.blue - (**flamePalette).ctTable[i].rgb.blue;
  65.         currentTotal = Abs(tempRed) + Abs(tempGreen) + Abs(tempBlue);
  66.         if (j == 0 || currentTotal < closestTotal)
  67.         {
  68.             closestTotal = currentTotal;
  69.             closest = j;
  70.         }
  71.     }
  72.     (**theFlame).flameColors[i].ctabNum = closest;
  73. }
  74. return noErr;
  75. }
  76.  
  77. void KillFlames(FlamePtr *theFlame)
  78. {
  79. if (*theFlame != nil)
  80. {
  81.     DisposePtr((Ptr)(*theFlame)->baseAddr);
  82. }
  83. }
  84.  
  85. void Spark(short x, short y, unsigned char heat, FlamePtr theFlame)
  86. {
  87. unsigned char    *currentPtr;
  88.  
  89. if (x > theFlame->bounds.left && x < theFlame->bounds.right &&
  90.     y > theFlame->bounds.top && y < theFlame->bounds.bottom)
  91. {
  92. if(y < theFlame->topLine) theFlame->topLine = y;
  93. currentPtr = (unsigned char *)(theFlame->baseAddr + 
  94.             (((long)theFlame->bounds.top + y) * (long)theFlame->rowBytes)) + x;
  95. *currentPtr = heat;
  96. }
  97. }
  98.  
  99.  
  100. void ChuckInFire(short x, short y, PixMapPtr victim, FlamePtr theFlame)
  101. {
  102. short    curX, curY, endX, endY, tempY, tempX;
  103. long    total;
  104. unsigned char    colVal[maxColors],
  105.                 i, ave;
  106. unsigned char    *srcPtr,
  107.                 *destPtr;
  108.                 
  109. short            srcRowBytes, destRowBytes;
  110.  
  111.  
  112. i = 0;
  113. if (victim->pixelSize != 8)        //I don't do thousands of colors
  114.     return;
  115.  
  116.  
  117. curY = 0;
  118. theFlame->topLine = y;
  119. srcRowBytes = victim->rowBytes & 0x3FFF;
  120. destRowBytes = theFlame->rowBytes;
  121. do{
  122.     srcPtr = (unsigned char *)victim->baseAddr + ((long)srcRowBytes * (long)curY);
  123.     destPtr = (unsigned char *)theFlame->baseAddr + ((long)destRowBytes * ((long)curY + y)) + x;
  124.     curX = 0;
  125.     do{
  126.         *destPtr = *srcPtr + *destPtr;
  127.         destPtr++;
  128.         srcPtr++;
  129.         curX++;
  130.     } while (curX < victim->bounds.right && curX + x < theFlame->bounds.right);
  131.     curY++;
  132. }while (curY < victim->bounds.bottom && curX + x < theFlame->bounds.bottom);
  133. }
  134.  
  135.  
  136. void SetUpBurn(unsigned char odds, unsigned char max, unsigned char min, FlamePtr theFlame)
  137. {
  138. long     x = theFlame->bounds.left + 1,
  139.         tempX,
  140.         lenght;
  141. unsigned char    *currentPtr,
  142.                 *tempPtr2,
  143.                 *tempPtr3,
  144.                 randVal = max - min;
  145.  
  146.  
  147. currentPtr = (unsigned char *)(theFlame->baseAddr + 
  148.             (((long)theFlame->bounds.bottom) * (long)theFlame->rowBytes));
  149. tempPtr2 =  (unsigned char *)(theFlame->baseAddr + 
  150.             (((long)theFlame->bounds.bottom + 1) * (long)theFlame->rowBytes));
  151. tempPtr3 =  (unsigned char *)(theFlame->baseAddr + 
  152.             (((long)theFlame->bounds.bottom + 2) * (long)theFlame->rowBytes));
  153.             
  154. do{
  155.     if (odds > Rand(255))
  156.     {
  157.         tempX = 0;
  158.         lenght = Rand(randVal);
  159.         lenght += min;
  160.         do{
  161.             *currentPtr = theFlame->fColSize;
  162.             *tempPtr2 = theFlame->fColSize;
  163.             *tempPtr3 = theFlame->fColSize;
  164.             tempX++;
  165.             x++;
  166.             currentPtr++;
  167.             tempPtr2++;
  168.             tempPtr3++;
  169.         }while(tempX < lenght && x < theFlame->bounds.right - 1);
  170.     } else {
  171.         tempX = 0;
  172.         lenght = Rand(max);
  173.         do{
  174.             *currentPtr = 0;
  175.             *tempPtr2 = 0;
  176.             *tempPtr3 = 0;
  177.             tempX++;
  178.             x++;
  179.             currentPtr++;
  180.             tempPtr2++;
  181.             tempPtr3++;
  182.         }while(tempX < lenght && x < theFlame->bounds.right - 1);
  183.     }
  184. }while (x < theFlame->bounds.right);
  185. }
  186.  
  187.  
  188. void Burn (FlamePtr theFlame, unsigned char takeOff, Boolean fuzz)
  189. {
  190. long    x,y;
  191. unsigned char    *currentPtr,
  192.                 *destPtr;
  193. unsigned char     temp1,
  194.         temp2,
  195.         temp3,
  196.         temp4,
  197.         temp5;
  198. short    res,    
  199.         lastLine;
  200. long     top;
  201. unsigned char    rArray[100],
  202.                 i;
  203. Boolean            fireOnLine = false;
  204.  
  205. if (fuzz)
  206.     for (i = 0; i < 100; i++) rArray[ i] = Rand(takeOff);
  207.  
  208. y = theFlame->bounds.bottom + 2;
  209. do {
  210.     currentPtr = (unsigned char *)(theFlame->baseAddr + ((long)y * (long)theFlame->rowBytes) +
  211.                 theFlame->bounds.left + 1);
  212.     destPtr = (unsigned char *) (currentPtr - ((long)theFlame->rowBytes * 2));
  213.     fireOnLine = false;
  214.     for(x = theFlame->bounds.left + 1 ; x < theFlame->bounds.right - 1; x++)
  215.     {
  216.         temp1 = (*(currentPtr));
  217.         temp2 = (*(currentPtr - 1L));
  218.         temp3 = (*(currentPtr + 1L));
  219.         temp4 = (*(currentPtr - (long)theFlame->rowBytes));
  220.         temp5 = *destPtr;
  221.         res = (temp1 + temp2 + temp3 + temp4) >> 2;
  222.         res += *destPtr;
  223.         if (fuzz)
  224.         {
  225.             res -= rArray[i];
  226.             i++;
  227.             if (i == 100) i = 0;
  228.         } else
  229.             res -= takeOff;
  230.         res = res >> 1;
  231.         if (res > theFlame->fColSize)
  232.             res = theFlame->fColSize - 1;
  233.         if (res < 0)
  234.             res = 0;
  235.         if (res > 0)
  236.             fireOnLine = true;
  237.         *destPtr = res;
  238.         destPtr++;
  239.         currentPtr++;
  240.     }
  241.     if (fireOnLine)
  242.     {
  243.         lastLine = y;
  244.         if (y == theFlame->topLine) theFlame->topLine--;
  245.     }
  246.     y--;
  247. }while(y > theFlame->bounds.top + 2 && y >= theFlame->topLine);
  248. if (lastLine < theFlame->topLine) theFlame->topLine = lastLine;
  249. }
  250.  
  251.  
  252. short Rand(short max)
  253. {
  254.     return (Random() & 0x7fff) % max;
  255. }
  256.  
  257. long Abs(long theLong)
  258. {
  259. if (theLong < 0)
  260. {
  261.     return -theLong;
  262. } else {
  263.     return theLong;
  264. }
  265. }
  266.  
  267. void CopyFlame(short x, short y, FlamePtr theFlame, PixMapPtr dest)
  268. {
  269. short rowBytes;
  270. long    curX,curY;
  271. unsigned char        *srcPtr,
  272.         *destPtr,
  273.         *destPtr2,
  274.         *destPtr3,
  275.         *destPtr4;
  276.         
  277.  
  278. rowBytes = dest->rowBytes & 0x3FFF;
  279. if (theFlame->speedUp == noSpeedUp)
  280. {
  281.     curY = theFlame->bounds.top;
  282.     do {
  283.         destPtr =(unsigned char *) dest->baseAddr + ((long)(y + curY) * (long)rowBytes) + 
  284.                 (long)dest->bounds.left + x;
  285.         srcPtr = (unsigned char *) theFlame->baseAddr + (theFlame->rowBytes * (long)curY);
  286.         curX = theFlame->bounds.left;
  287.         do{
  288.             *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  289.             destPtr++;
  290.             srcPtr++;
  291.             curX++;
  292.         } while (curX < theFlame->bounds.right && curX + x < dest->bounds.right);
  293.         curY++;
  294.     }while (curY < theFlame->bounds.bottom && curY + y < dest->bounds.bottom);
  295. }
  296. if (theFlame->speedUp == lowRes2)
  297. {
  298.     curY = theFlame->bounds.top;
  299.     do {
  300.         destPtr = (unsigned char *)dest->baseAddr + (((long)(y + curY) * 2) * (long)rowBytes) + 
  301.                 (long)dest->bounds.left + x ;
  302.         destPtr2 = (unsigned char *)dest->baseAddr + ( ((long)(y + curY) * 2 + 1) *(long)rowBytes) + 
  303.                 (long)dest->bounds.left + x;  
  304.         srcPtr = (unsigned char *)theFlame->baseAddr + (theFlame->rowBytes * (long)curY);
  305.         curX = theFlame->bounds.left;
  306.         do{
  307.             *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  308.             *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  309.             destPtr++;
  310.             destPtr2++;
  311.             *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  312.             *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  313.             destPtr++;
  314.             destPtr2++;
  315.             srcPtr++;
  316.         curX++;
  317.         }while (curX < theFlame->bounds.right && curX + x < dest->bounds.right);
  318.     curY++;
  319.     }while (curY < theFlame->bounds.bottom && curY + y < dest->bounds.bottom);
  320. }
  321.  
  322. if (theFlame->speedUp == lowRes4)
  323. {
  324.     curY = theFlame->bounds.top;
  325.     do {
  326.         destPtr = (unsigned char *)dest->baseAddr + (((long)(y + curY) * 4) *(long)rowBytes) + 
  327.                 (long)dest->bounds.left + x;
  328.         destPtr2 = (unsigned char *)dest->baseAddr + ( ((long)(y + curY) * 4 + 1) *(long)rowBytes) + 
  329.                 (long)dest->bounds.left + x;  
  330.         destPtr3 = (unsigned char *)dest->baseAddr + (((long)(y + curY) * 4 + 2) *(long)rowBytes) + 
  331.                 (long)dest->bounds.left + x;
  332.         destPtr4 = (unsigned char *)dest->baseAddr + ( ((long)(y + curY) * 4 + 3) *(long)rowBytes) + 
  333.                 (long)dest->bounds.left + x;  
  334.         srcPtr = (unsigned char *)theFlame->baseAddr + (theFlame->rowBytes * (long)curY);
  335.         curX = theFlame->bounds.left;
  336.         do{
  337.             *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  338.             *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  339.             *destPtr3 = theFlame->flameColors[*srcPtr].ctabNum;
  340.             *destPtr4 = theFlame->flameColors[*srcPtr].ctabNum;
  341.             destPtr++;
  342.             destPtr2++;
  343.             destPtr3++;
  344.             destPtr4++;
  345.             *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  346.             *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  347.             *destPtr3 = theFlame->flameColors[*srcPtr].ctabNum;
  348.             *destPtr4 = theFlame->flameColors[*srcPtr].ctabNum;
  349.             destPtr++;
  350.             destPtr2++;
  351.             destPtr3++;
  352.             destPtr4++;
  353.             *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  354.             *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  355.             *destPtr3 = theFlame->flameColors[*srcPtr].ctabNum;
  356.             *destPtr4 = theFlame->flameColors[*srcPtr].ctabNum;
  357.             destPtr++;
  358.             destPtr2++;
  359.             destPtr3++;
  360.             destPtr4++;
  361.             *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  362.             *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  363.             *destPtr3 = theFlame->flameColors[*srcPtr].ctabNum;
  364.             *destPtr4 = theFlame->flameColors[*srcPtr].ctabNum;
  365.             destPtr++;
  366.             destPtr2++;
  367.             destPtr3++;
  368.             destPtr4++;
  369.             srcPtr++;
  370.             curX++;
  371.         } while (curX < theFlame->bounds.right && curX + x < dest->bounds.right);
  372.         curY++;
  373.     }while (curY < theFlame->bounds.bottom && curY + y < dest->bounds.bottom);
  374. }
  375.  
  376. }
  377.  
  378. void MaskFlame(short x, short y, FlamePtr theFlame, PixMapPtr dest)
  379. {
  380. short rowBytes;
  381. long    curX,curY;
  382. unsigned char    *destPtr,
  383.         *srcPtr,
  384.         *destPtr2,
  385.         *destPtr3,
  386.         *destPtr4;
  387.         
  388. rowBytes = dest->rowBytes & 0x3FFF;
  389. if (theFlame->speedUp == noSpeedUp)
  390. {
  391.     curY = theFlame->bounds.top;
  392.     do {
  393.         destPtr = (unsigned char *)dest->baseAddr + ((long)(y + curY) * (long)rowBytes) + 
  394.                 (long)dest->bounds.left + x;
  395.         srcPtr = (unsigned char *)theFlame->baseAddr + (theFlame->rowBytes * (long)curY);
  396.         curX = theFlame->bounds.left;
  397.         do{
  398.             if (*srcPtr != 0)
  399.                 *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  400.             destPtr++;
  401.             srcPtr++;
  402.             curX++;
  403.         } while (curX < theFlame->bounds.right && curX + x < dest->bounds.right);
  404.         curY++;
  405.     }while (curY < theFlame->bounds.bottom && curY + y < dest->bounds.bottom);
  406. }
  407. if (theFlame->speedUp == lowRes2)
  408. {
  409.     curY = theFlame->bounds.top;
  410.     do {
  411.         destPtr = (unsigned char *)dest->baseAddr + (((long)(curY + y) * 2) *(long)rowBytes) + 
  412.                 (long)dest->bounds.left + x;
  413.         destPtr2 = (unsigned char *)dest->baseAddr + ( ((long)(curY + y) * 2 + 1) *(long)rowBytes) + 
  414.                 (long)dest->bounds.left + x;  
  415.         srcPtr =(unsigned char *) theFlame->baseAddr + (theFlame->rowBytes * (long)curY);
  416.         curX = theFlame->bounds.left;
  417.         do{
  418.             if (*srcPtr != 0)
  419.             {
  420.                 *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  421.                 *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  422.             }
  423.             destPtr++;
  424.             destPtr2++;
  425.             if (*srcPtr != 0)
  426.             {
  427.                 *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  428.                 *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  429.             }
  430.             destPtr++;
  431.             destPtr2++;
  432.             srcPtr++;
  433.             curX++;
  434.         } while (curX < theFlame->bounds.right && curX + x < dest->bounds.right);
  435.         curY++;
  436.     }while (curY < theFlame->bounds.bottom && curY + y < dest->bounds.bottom);
  437. }
  438.  
  439. if (theFlame->speedUp == lowRes4)
  440. {
  441.     curY = theFlame->bounds.top;
  442.     do {
  443.         destPtr = (unsigned char *)dest->baseAddr + (((long)(curY + y) * 4) *(long)rowBytes) + 
  444.                 (long)dest->bounds.left + x;
  445.         destPtr2 = (unsigned char *)dest->baseAddr + ( ((long)(curY + y) * 4 + 1) *(long)rowBytes) + 
  446.                 (long)dest->bounds.left + x;  
  447.         destPtr3 = (unsigned char *)dest->baseAddr + (((long)(curY + y) * 4 + 2) *(long)rowBytes) + 
  448.                 (long)dest->bounds.left + x;
  449.         destPtr4 = (unsigned char *)dest->baseAddr + ( ((long)(curY + y) * 4 + 3) *(long)rowBytes) + 
  450.                 (long)dest->bounds.left + x;  
  451.         srcPtr = (unsigned char *)theFlame->baseAddr + (theFlame->rowBytes * (long)curY);
  452.         curX = theFlame->bounds.left;
  453.         do{
  454.             if (*srcPtr != 0)
  455.             {
  456.                 *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  457.                 *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  458.                 *destPtr3 = theFlame->flameColors[*srcPtr].ctabNum;
  459.                 *destPtr4 = theFlame->flameColors[*srcPtr].ctabNum;
  460.             }
  461.             destPtr++;
  462.             destPtr2++;
  463.             destPtr3++;
  464.             destPtr4++;
  465.             if (*srcPtr != 0)
  466.             {
  467.                 *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  468.                 *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  469.                 *destPtr3 = theFlame->flameColors[*srcPtr].ctabNum;
  470.                 *destPtr4 = theFlame->flameColors[*srcPtr].ctabNum;
  471.             }
  472.             destPtr++;
  473.             destPtr2++;
  474.             destPtr3++;
  475.             destPtr4++;
  476.             if (*srcPtr != 0)
  477.             {
  478.                 *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  479.                 *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  480.                 *destPtr3 = theFlame->flameColors[*srcPtr].ctabNum;
  481.                 *destPtr4 = theFlame->flameColors[*srcPtr].ctabNum;
  482.             }
  483.             destPtr++;
  484.             destPtr2++;
  485.             destPtr3++;
  486.             destPtr4++;
  487.             if (*srcPtr != 0)
  488.             {
  489.                 *destPtr = theFlame->flameColors[*srcPtr].ctabNum;
  490.                 *destPtr2 = theFlame->flameColors[*srcPtr].ctabNum;
  491.                 *destPtr3 = theFlame->flameColors[*srcPtr].ctabNum;
  492.                 *destPtr4 = theFlame->flameColors[*srcPtr].ctabNum;
  493.             }
  494.             destPtr++;
  495.             destPtr2++;
  496.             destPtr3++;
  497.             destPtr4++;
  498.             srcPtr++;
  499.             curX++;
  500.         } while (curX < theFlame->bounds.right && curX + x < dest->bounds.right);
  501.         curY++;
  502.     }while (curY < theFlame->bounds.bottom && curY + y < dest->bounds.bottom);
  503. }
  504. }
  505.