home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / meteor.pak / SPRITE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  7.8 KB  |  312 lines

  1. //--------------------------------------------------------------------------
  2. // Turbo Meteor -- Copyright (c) 1995, Borland International
  3. //--------------------------------------------------------------------------
  4. #include "sprite.h"
  5.  
  6. // adjust - value to convert degrees to radians
  7. //
  8. //  pi can be computed as atan(1)*4,
  9. //
  10. //  and there are 2*pi radians in 360 degrees so:
  11. //
  12. //  adjust = 2*pi/360 = pi/180 = atan(1)*4/180 = atan(1)/45
  13. //
  14. const double adjust = atan(1)/45;
  15.  
  16. double sinTable[360];
  17. double cosTable[360];
  18.  
  19. double sind( int angle ) {
  20.   return sinTable[(angle+360)%360];
  21. }
  22. double cosd( int angle ) {
  23.   return cosTable[(angle+360)%360];
  24. }
  25.  
  26. void InitSinCosTables() {
  27.   int i;
  28.   for (i=0;i<360;i++) {
  29.     sinTable[i] = sin(adjust*i);
  30.     cosTable[i] = cos(adjust*i);
  31.   }
  32. }
  33.  
  34. #pragma startup InitSinCosTables
  35.  
  36. void SpriteList::Add( Sprite* sprite ) {
  37.   count++;
  38.   if (root==0) {
  39.     root = sprite;
  40.     sprite->next = 0;
  41.     sprite->owner = this;
  42.     return;
  43.   }
  44.   sprite->next = root;
  45.   sprite->owner = this;
  46.   root = sprite;
  47. }
  48.  
  49. void SpriteList::DrawAll( TMemoryDC& dc ) {
  50.   Sprite *temp = root;
  51.   while (temp!=0) {
  52.     temp->Draw( dc );
  53.     temp=temp->next;
  54.   }
  55. }
  56.  
  57. int SpriteList::UpdateAll() {
  58.   Sprite *previous,
  59.          *current = root;
  60.   int    points = 0;
  61.  
  62.   previous = 0;
  63.   while (current!=0) {
  64.   // if the object is not condemned, call it's update
  65.   // function
  66.     if (!(current->condemned)) {
  67.       points+=current->Update();
  68.       previous = current;
  69.       current=current->next;
  70.     }
  71.   // if the object is condemned, delete it from the
  72.   // list
  73.     else {
  74.       // special case if we're deleting the root node
  75.       if (previous==0) {
  76.         root = current->next;
  77.         delete current;
  78.         count--;
  79.         current = root;
  80.       }
  81.       else {
  82.         previous->next = current->next;
  83.         delete current;
  84.         count--;
  85.         current=current->next;
  86.       }
  87.     }
  88.   }
  89.   return points;
  90. }
  91.  
  92. // *BBK* should convert this over to use RTTI, this is cheezy
  93.  
  94. Sprite* SpriteList::CheckForHitMeteor( TPoint& p ) {
  95.   Sprite *temp = root;
  96.   while (temp!=0) {
  97.     if ((strncmp(temp->DebugInfo(),"Meteor",6)==0) &&  // *BBK* cheezy
  98.         (temp->boundingRect.Contains( p )))
  99.         return temp;
  100.     temp=temp->next;
  101.   }
  102.   return 0;
  103. }
  104.  
  105. Meteor::Meteor( TPoint& aOrigin, TSize& aMomentum, int aSize, int aSpawnCount ):
  106.   Sprite( TSize( 600,400 ) ) {
  107.   origin = aOrigin;
  108.   mx = aMomentum.cx;
  109.   my = aMomentum.cy;
  110.   size = aSize;
  111.   spawnCount = aSpawnCount;
  112.   for (int i=0;i<10;i++) {
  113.     angle[i] = (angle1[i]+random(20)-10)%360;
  114.     radius[i] = (radius1[i]+random(10)-5)/(4-size);
  115.   }
  116.   angularMomentum = random(7)-4;
  117.   currentAngle = 0;
  118.   count = count1;
  119. }
  120.  
  121. void Meteor::Hit() {
  122.   size--;
  123.   if (size>0) {
  124.     for (int i=0;i<spawnCount;i++)
  125.       owner->Add( new Meteor( origin, TSize( random(10)-5, random(10)-5 ),
  126.                               size, size ) );
  127.   }
  128.   condemned=true;
  129. }
  130.  
  131.  
  132. void Meteor::Draw( TMemoryDC& dc ) {
  133.   TPoint temp;
  134.   TPoint points[10];
  135.   int i;
  136.  
  137.  
  138.   temp =TPoint( radius[0]*sind(angle[0]+currentAngle),
  139.                 radius[0]*cosd(angle[0]+currentAngle) );
  140.   ResetBoundingRect();
  141.   ExpandBoundingRect( temp+origin );
  142.   points[0]=temp+origin;
  143. //  dc.MoveTo( origin+temp );
  144.   for (i=1;i<=count;i++) {
  145.     temp = TPoint( radius[i%count]*sind(angle[i%count]+currentAngle),
  146.                    radius[i%count]*cosd(angle[i%count]+currentAngle) );
  147.     ExpandBoundingRect( temp+origin );
  148.     points[i] = temp+origin;
  149. //    dc.LineTo( origin+temp );
  150.   }
  151.   points[count]=points[0];
  152.   dc.Polyline( points, count+1 );
  153. }
  154.  
  155. int Shot::Update() {
  156.   // shots die after a fixed amount of time
  157.  
  158.   if (timeToDie>0) {
  159.     origin+=TPoint(mx,my);
  160.     timeToDie--;
  161.     if (timeToDie==0)
  162.       condemned = true;
  163.   }
  164.  
  165.   Wrap();  // if the shot is off the screen, wrap to other side
  166.  
  167.   // check against all meteors in the list, to see if any are
  168.   // colliding with ourself
  169.  
  170.   Sprite* meteor = owner->CheckForHitMeteor( origin );
  171.  
  172.   // if so, tell the meteor it was hit, and mark ourself for
  173.   // deletion
  174.  
  175.   if (meteor) {
  176.     ((Meteor*)meteor)->Hit();
  177.     condemned = true;
  178.     int size = ((Meteor*)meteor)->GetSize();
  179.     switch (size) {
  180.       case 0:
  181.         return 500;
  182.       case 1:
  183.         return 50;
  184.       case 2:
  185.         return 5;
  186.     }
  187.   }
  188.   return 0;
  189. }
  190.  
  191. const char *Meteor::DebugInfo() {
  192.   static char temp[100];
  193.   wsprintf(temp,"Meteor(%d)",size);
  194.   return temp;
  195. }
  196.  
  197. const char *Message::DebugInfo() {
  198.   static char temp[100];
  199.   wsprintf(temp,"Message '%s'",text);
  200.   return temp;
  201. }
  202.  
  203. Message::Message( TPoint& aOrigin, int aBufferLen ):
  204.   Sprite( TSize(600,400) ) {
  205.   text = new char[ aBufferLen ];
  206.   bufferLen = aBufferLen;
  207.   origin = aOrigin;
  208. }
  209.  
  210. void Message::Draw( TMemoryDC& dc ) {
  211.   const tw = 6;          // text width
  212.   const th = 10;         // text height
  213.   TPoint temp = origin;
  214.   int i;
  215.   for (i=0;i<strlen(text);i++) {
  216.     switch (text[i]) {
  217.       case '0':
  218.         dc.MoveTo(temp);
  219.         dc.LineTo(temp+TPoint(tw,0));
  220.         dc.LineTo(temp+TPoint(tw,th));
  221.         dc.LineTo(temp+TPoint(0,th));
  222.         dc.LineTo(temp);
  223.         break;
  224.       case '1':
  225.         dc.MoveTo(temp+TPoint(tw/2,0));
  226.         dc.LineTo(temp+TPoint(tw/2,th+1));
  227.         break;
  228.       case '2':
  229.         dc.MoveTo(temp);
  230.         dc.LineTo(temp+TPoint(tw,0));
  231.         dc.LineTo(temp+TPoint(tw,th/2));
  232.         dc.LineTo(temp+TPoint(0,th/2));
  233.         dc.LineTo(temp+TPoint(0,th));
  234.         dc.LineTo(temp+TPoint(tw+1,th));
  235.         break;
  236.       case '3':
  237.         dc.MoveTo(temp);
  238.         dc.LineTo(temp+TPoint(tw,0));
  239.         dc.LineTo(temp+TPoint(tw,th));
  240.         dc.LineTo(temp+TPoint(0-1,th));
  241.         dc.MoveTo(temp+TPoint(tw,th/2));
  242.         dc.LineTo(temp+TPoint(0-1,th/2));
  243.         break;
  244.       case '4':
  245.         dc.MoveTo(temp);
  246.         dc.LineTo(temp+TPoint(0,th/2));
  247.         dc.LineTo(temp+TPoint(tw,th/2));
  248.         dc.MoveTo(temp+TPoint(tw,0));
  249.         dc.LineTo(temp+TPoint(tw,th+1));
  250.         break;
  251.       case '5':
  252.         dc.MoveTo(temp+TPoint(tw,0));
  253.         dc.LineTo(temp);
  254.         dc.LineTo(temp+TPoint(0,th/2));
  255.         dc.LineTo(temp+TPoint(tw,th/2));
  256.         dc.LineTo(temp+TPoint(tw,th));
  257.         dc.LineTo(temp+TPoint(0-1,th));
  258.         break;
  259.       case '6':
  260.         dc.MoveTo(temp+TPoint(tw,0));
  261.         dc.LineTo(temp);
  262.         dc.LineTo(temp+TPoint(0,th));
  263.         dc.LineTo(temp+TPoint(tw,th));
  264.         dc.LineTo(temp+TPoint(tw,th/2));
  265.         dc.LineTo(temp+TPoint(0-1,th/2));
  266.         break;
  267.       case '7':
  268.         dc.MoveTo(temp);
  269.         dc.LineTo(temp+TPoint(tw,0));
  270.         dc.LineTo(temp+TPoint(tw,th+1));
  271.         break;
  272.       case '8':
  273.         dc.MoveTo(temp);
  274.         dc.LineTo(temp+TPoint(tw,0));
  275.         dc.LineTo(temp+TPoint(tw,th));
  276.         dc.LineTo(temp+TPoint(0,th));
  277.         dc.LineTo(temp+TPoint(0,0));
  278.         dc.MoveTo(temp+TPoint(0,th/2));
  279.         dc.LineTo(temp+TPoint(tw,th/2));
  280.         break;
  281.       case '9':
  282.         dc.MoveTo(temp+TPoint(0,th));
  283.         dc.LineTo(temp+TPoint(tw,th));
  284.         dc.LineTo(temp+TPoint(tw,0));
  285.         dc.LineTo(temp+TPoint(0,0));
  286.         dc.LineTo(temp+TPoint(0,th/2));
  287.         dc.LineTo(temp+TPoint(tw,th/2));
  288.         break;
  289.       case '*':  // ship
  290.         dc.MoveTo(temp+TPoint(tw/2,0));
  291.         dc.LineTo(temp+TPoint(tw,th));
  292.         dc.LineTo(temp+TPoint(tw/2,th-(th/4)));
  293.         dc.LineTo(temp+TPoint(0,th));
  294.         dc.LineTo(temp+TPoint(tw/2,0));
  295.         break;
  296.     }
  297.     temp+=TPoint(tw+tw/2,0);
  298.   }
  299. }
  300.  
  301. Message::~Message() {
  302.     delete [] text;
  303. }
  304.  
  305. // values used to initialize meteors.  these values are randomly
  306. // tweaked, so each meteor looks different
  307. //
  308. int  angle1[10] = { 0,45,90,135,180,225,270,315,0,0 };
  309. int  radius1[10] = { 30,30,30,30,30,30,30,30,0,0 };
  310. int  count1 = 8;
  311.  
  312.