[Tux4kids-commits] r595 - tuxmath/branches/factroids/src

tholy-guest at alioth.debian.org tholy-guest at alioth.debian.org
Fri Aug 8 02:57:43 UTC 2008


Author: tholy-guest
Date: 2008-08-08 02:57:42 +0000 (Fri, 08 Aug 2008)
New Revision: 595

Modified:
   tuxmath/branches/factroids/src/factroids.c
Log:
Factroids: improve the detection of lasers hitting the asteroids.


Modified: tuxmath/branches/factroids/src/factroids.c
===================================================================
--- tuxmath/branches/factroids/src/factroids.c	2008-08-07 23:43:22 UTC (rev 594)
+++ tuxmath/branches/factroids/src/factroids.c	2008-08-08 02:57:42 UTC (rev 595)
@@ -197,7 +197,7 @@
 
 static int FF_add_laser(void);
 static int FF_add_asteroid(int x, int y, int xspeed, int yspeed, int size, int angle, int 				   angle_speed, int fact_num, int a, int b, int new_wave);
-static int FF_destroy_asteroid(int i, int xspeed, int yspeed);
+static int FF_destroy_asteroid(int i, float xspeed, float yspeed);
 
 static void FF_ShowMessage(char* str1, char* str2, char* str3, char* str4);
 
@@ -644,6 +644,14 @@
 
 }
 
+static SDL_Surface* get_asteroid_image(int size,int angle)
+{
+  if (size == 0)
+    return IMG_asteroids1[angle/DEG_PER_ROTATION];
+  else
+    return IMG_asteroids2[angle/DEG_PER_ROTATION];
+}
+
 static void FF_draw(void){
   SDL_Rect dest;
   int i, offset;
@@ -678,9 +686,9 @@
 
   if(!tuxship.hurt || (tuxship.hurt && tuxship.hurt_count%2==0)){
      dest.x = (tuxship.x - (IMG_tuxship[tuxship.angle/DEG_PER_ROTATION]->w/2));
-     dest.y = (tuxship.y - (IMG_tuxship[tuxship.angle/DEG_PER_ROTATION]->h/2));
-     dest.w = IMG_tuxship[tuxship.angle/DEG_PER_ROTATION]->w;
-     dest.h = IMG_tuxship[tuxship.angle/DEG_PER_ROTATION]->h;
+     dest.y = (tuxship.y - (IMG_tuxship[tuxship.angle/DEG_PER_ROTATION]->h/2));
+     dest.w = IMG_tuxship[tuxship.angle/DEG_PER_ROTATION]->w;
+     dest.h = IMG_tuxship[tuxship.angle/DEG_PER_ROTATION]->h;
 	
      SDL_BlitSurface(IMG_tuxship[tuxship.angle/DEG_PER_ROTATION], NULL, screen, &dest);
   }
@@ -689,15 +697,7 @@
     if(asteroid[i].alive>0){
      dest.x=asteroid[i].x;
      dest.y=asteroid[i].y;
-     if(asteroid[i].size==0){
-        SDL_BlitSurface(IMG_asteroids1[asteroid[i].angle/DEG_PER_ROTATION], NULL, screen, &dest);
-     }
-     if(asteroid[i].size==1){
-        SDL_BlitSurface(IMG_asteroids2[asteroid[i].angle/DEG_PER_ROTATION], NULL, screen, &dest);
-     }
-     if(asteroid[i].size==2){
-        SDL_BlitSurface(IMG_asteroids2[asteroid[i].angle/DEG_PER_ROTATION], NULL, screen, &dest);
-     }
+     SDL_BlitSurface(get_asteroid_image(asteroid[i].size,asteroid[i].angle), NULL, screen, &dest);
      if(FF_game==FACTOROIDS_GAME)
      {   
        sprintf(str, "%.1d", asteroid[i].fact_number);
@@ -1100,242 +1100,96 @@
 
 /******************* LASER FUNCTIONS *********************/
 
-/*Return -1 if no laser is avable*/
+/*Return -1 if no laser is available*/
 int FF_add_laser(void)
 {
-  int i, j, k;
-  int dx,dy;
-  int xcount, ycount;
-  float m, b;
+  int i, k, zapIndex;
+  float ux, uy, s, smin,dx,dy,dx2, dy2, d2, thresh;
+  int screensize;
+  SDL_Surface *asteroid_image;
+
+  const float inside_factor = 0.9*0.9;
+
+  screensize = screen->w;
+  if (screensize < screen->h)
+    screensize = screen->h;
+
   for(i=0; i<=MAX_LASER; i++)
   {
     if(laser[i].alive==0)
     {
+      // Fire the laser
       laser[i].alive=1;
       laser[i].x=tuxship.centerx;
       laser[i].y=tuxship.centery;
       laser[i].angle=tuxship.angle;
       laser[i].count=15;
-
-      if(laser[i].angle>=0 && laser[i].angle<=360)
+      
+      ux = cos((float)laser[i].angle * DEG_TO_RAD);
+      uy = -sin((float)laser[i].angle * DEG_TO_RAD);
+      laser[i].destx = laser[i].x + (int)(ux * screensize);
+      laser[i].desty = laser[i].y + (int)(uy * screensize);
+      
+      // Check to see if it hits asteroids---we only check when it
+      // just starts firing, "drift" later doesn't count!
+      // We describe the laser path as p = p0 + s*u, where
+      //   p0 = (x0,y0) is the initial position vector (i.e., the ship)
+      //   u = (ux,uy) is the unit vector of the laser's direction
+      //   s (a scalar) is the distance along the laser (s >= 0)
+      // With this parametrization, it's easy to calculate the
+      // closest approach to the asteroid center, etc.
+      zapIndex = -1;  // keep track of the closest "hit" asteroid
+      smin = 10*screensize;
+      for (k=0; k<MAX_ASTEROIDS; k++)
       {
-	laser[i].m     = (int)sin((float)laser[i].angle * DEG_TO_RAD);
-	laser[i].destx = laser[i].x + (int)(cos((float)laser[i].angle * DEG_TO_RAD) * 1400);
-	laser[i].desty = laser[i].y - (int)(sin((float)laser[i].angle * DEG_TO_RAD) * 1400);
-	
-	xcount = laser[i].x;
-	ycount = laser[i].y;
-
-	dx = laser[i].destx - xcount;
-	dy = laser[i].desty - ycount;
-	if (dx != 0)
+	if (!asteroid[k].alive)
+	  continue;
+	asteroid_image = get_asteroid_image(asteroid[k].size,asteroid[k].angle);
+	dx = asteroid[k].x + asteroid_image->w/2 - laser[i].x;
+	dy = asteroid[k].y + asteroid_image->h/2 - laser[i].y;
+	// Find distance along laser of closest approach to asteroid center
+	s = dx*ux + dy*uy;
+	if (s >= 0)  // don't worry about it if it's in the opposite direction! (i.e., behind the ship)
 	{
-
-    	  m = ((float) dy) / ((float) dx);
-	  b = ycount  - m * xcount;
-
-	  if (laser[i].destx > xcount) dx = 1;
-	  else dx = -1;
-
-	  while (xcount != laser[i].destx)
+	  // Find the distance to the asteroid center at closest approach
+	  dx2 = dx - s*ux;
+	  dy2 = dy - s*uy;
+	  d2 = dx2*dx2 + dy2*dy2;
+	  thresh = (asteroid_image->h)/2;
+	  thresh = thresh*thresh*inside_factor;
+	  if (d2 < thresh)
 	  {
-            xcount = xcount + dx;
-	    ycount = m * xcount + b;
-	    for(k=0; k<MAX_ASTEROIDS; k++)
+	    // The laser intersects the asteroid. Check to see if
+	    // the answer works
+	    if((asteroid[k].isprime && ((num==asteroid[k].fact_number)||(num==0))) ||
+	       (FF_game==FACTOROIDS_GAME && num > 1 && ((asteroid[k].fact_number%num)==0) && (num!=asteroid[k].fact_number)) ||
+	       (FF_game==FRACTIONS_GAME && num > 1 && ((asteroid[k].a%num)==0) && ((asteroid[k].a%num)==0) && (num!=asteroid[k].fact_number)))
 	    {
-		if(xcount<asteroid[k].x+70 && 
-                   xcount>asteroid[k].x && 
-                   ycount<asteroid[k].y+70 && 
-                   ycount>asteroid[k].y &&
-                   asteroid[k].alive)
-	        {
-                   if(asteroid[k].isprime && ((num==asteroid[k].fact_number)||(num==0)))
- 		   {
-		     isdead=1;
-		     xdead=asteroid[k].x;
-		     ydead=asteroid[k].y;
-		     if(tuxship.x<asteroid[k].x)
-		       FF_destroy_asteroid(k, m, m);
-		     if(tuxship.x>=asteroid[k].x)
-		       FF_destroy_asteroid(k, -m, m);
-
-		     laser[i].destx=xcount;
-		     laser[i].desty=ycount;
-		     return 1;
-		   }
-                   if (num!=0)
-		   {  
-		     if(FF_game==FACTOROIDS_GAME)
-		     {
-                        if(((asteroid[k].fact_number%num)==0) && (num!=asteroid[k].fact_number))
-		        {
-		          isdead=1;
-		          xdead=asteroid[k].x;
-		          ydead=asteroid[k].y;
-
-		          if(tuxship.x<asteroid[k].x)
-		            FF_destroy_asteroid(k, m, m);
-		          if(tuxship.x>=asteroid[k].x)
-		            FF_destroy_asteroid(k, -m, m);
-		          /*
-			  if(tuxship.x<asteroid[k].x)
-			     if(tuxship.y<asteroid[k].y)
-		                FF_destroy_asteroid(k, 2, -2);
-			     else if(tuxship.y>asteroid[k].y)
-				FF_destroy_asteroid(k, 2, 2);
-			  else if (tuxship.x>asteroid[k].x)
-			     if(tuxship.y<asteroid[k].y)
-		                FF_destroy_asteroid(k, -2, -2);
-			     else if(tuxship.y>asteroid[k].y)
-				FF_destroy_asteroid(k, -2, 2);*/
-			      
-			  // Lives per 100 points
-			  for(j=score;j<(score+num);j++){
-			      if((score%100)==0){
-				 tuxship.lives++;
-			      }
-			  }
-			  score=j;
-		          //laser[i].destx=xcount;
-		          //laser[i].desty=ycount;
-		          return 1;
-			}
-		     }
-		     else if (FF_game==FRACTIONS_GAME)
-		     {
-			if(((asteroid[k].a%num)==0) &&
-			   ((asteroid[k].a%num)==0) &&
-			   (num!=asteroid[k].fact_number))
-		        {
-			  isdead=1;
-		          xdead=asteroid[k].x;
-		          ydead=asteroid[k].y;
-		          if(tuxship.x<asteroid[k].x)
-		            FF_destroy_asteroid(k, m, m);
-		          if(tuxship.x>=asteroid[k].x)
-		            FF_destroy_asteroid(k, -m, m);
-
-			  // Lives per 100 points
-			  for(j=score;j<(score+num);j++){
-			      if((score%100)==0){
-				 tuxship.lives++;
-			      }
-			  }
-			  score=j;
-
-		          laser[i].destx=xcount;
-		          laser[i].desty=ycount;
-		          return 1; 
-			}  
-		     }
-		     
-		   }
-	         } 
-               }
+	      // It's valid, check to see if it's closest
+	      if (s < smin)
+	      {
+		// It's the closest yet examined
+		smin = s;
+		zapIndex = k;
+	      }
 	    }
 	  }
-	  else
-	  {
- 	   while (ycount != laser[i].desty)
-	   {
-   	     if (laser[i].desty > ycount) dy = 1;
-	     else dy = -1;
-             ycount=ycount+dy;
-  	     for(k=0; k<MAX_ASTEROIDS; k++)
-	     {
-                 if(xcount<asteroid[k].x+70 && 
-                   xcount>asteroid[k].x && 
-                   ycount<asteroid[k].y+70 && 
-                   ycount>asteroid[k].y &&
-                   asteroid[k].alive)
-	         {
-
-                   if(asteroid[k].isprime && ((num==asteroid[k].fact_number)||(num==0)))
- 		   {
-		     isdead=1;
-		     xdead=asteroid[k].x;
-		     ydead=asteroid[k].y;
-		     if(tuxship.x<asteroid[k].x)
-		       FF_destroy_asteroid(k, m, m);
-		     if(tuxship.x>=asteroid[k].x)
-		       FF_destroy_asteroid(k, -m, m);
-
-		     //laser[i].destx=xcount;
-		     //laser[i].desty=ycount;
-		     return 1;
-		   }
-
-		  if(FF_game==FACTOROIDS_GAME)
-		  {
-
-
-                  if (num!=0)
-		  {  
-		   if(((asteroid[k].fact_number%num)==0) && (num!=asteroid[k].fact_number))
-		   {
-
-		     isdead=1;
-		     xdead=asteroid[k].x;
-		     ydead=asteroid[k].y;
-		     if(tuxship.x<asteroid[k].x)
-		       FF_destroy_asteroid(k, m, m);
-		     if(tuxship.x>=asteroid[k].x)
-		       FF_destroy_asteroid(k, -m, m);
-
-			  // Lives per 100 points
-			  for(j=score;j<(score+num);j++){
-			      if((score%100)==0){
-				 tuxship.lives++;
-			      }
-			  }
-			  score=j;
-
-		     //laser[i].destx=xcount;
-		     //laser[i].desty=ycount;
-		     return 1;
-		   }
-                  }
-	        }
-		else if (FF_game==FRACTIONS_GAME)
-		{
-                  if (num!=0)
-		  {  
-		    if(((asteroid[k].a%num)==0) &&
-		       ((asteroid[k].a%num)==0) &&
-		       (num!=asteroid[k].fact_number))
-		    {
-
-		     isdead=1;
-		     xdead=asteroid[k].x;
-		     ydead=asteroid[k].y;
-		     if(tuxship.x<asteroid[k].x)
-		       FF_destroy_asteroid(k, m, m);
-		     if(tuxship.x>=asteroid[k].x)
-		       FF_destroy_asteroid(k, -m, m);
-
-			  // Lives per 100 points
-
-			  for(j=score;j<(score+num);j++){
-			      if((score%100)==0){
-				 tuxship.lives++;
-			      }
-			  }
-			  score=j;
-
-		     //laser[i].destx=xcount;
-		     //laser[i].desty=ycount;
-		     return 1;
-		   }
-                  }
-		}
-	      }
-            }
-	  }
+	}
       }
-
+      
+      // Handle the destruction, score, and extra lives
+      if (zapIndex >= 0)  // did we zap one?
+      {
+	isdead = 1;
+	laser[i].destx = laser[i].x + (int)(ux * smin);
+	laser[i].desty = laser[i].y + (int)(uy * smin);
+	FF_destroy_asteroid(zapIndex,2*ux,2*uy);
+	if (floor((float)score/100) < floor((float)(score+num)/100))
+	  tuxship.lives++;
+	score += num;
+      }
       return 1;
     }
-   }
   }
   fprintf(stderr, "Laser could't be created!\n");
   return -1;
@@ -1345,8 +1199,7 @@
 
 
 
-static int FF_add_asteroid(int x, int y, int xspeed, int yspeed, int size, int angle, int
-                           angle_speed, int fact_number, int a, int b, int new_wave)
+static int FF_add_asteroid(int x, int y, int xspeed, int yspeed, int size, int angle, int angle_speed, int fact_number, int a, int b, int new_wave)
 {
   int i;
   for(i=0; i<MAX_ASTEROIDS; i++){
@@ -1418,9 +1271,12 @@
   return -1;
 }
 
-int FF_destroy_asteroid(int i, int xspeed, int yspeed)
+int FF_destroy_asteroid(int i, float xspeed, float yspeed)
 {
   if(asteroid[i].alive==1){
+    isdead=1;
+    xdead=asteroid[i].x;
+    ydead=asteroid[i].y;
      if(asteroid[i].size>0){
       /* Break the rock into two smaller ones! */
       if(num!=0){
@@ -1432,8 +1288,8 @@
         if(FF_game==FACTOROIDS_GAME){
           FF_add_asteroid(asteroid[i].x,
 	  	          asteroid[i].y,
-	  	          ((asteroid[i].xspeed + xspeed) / 2),
-	  	          (asteroid[i].yspeed + yspeed),
+	  	          asteroid[i].xspeed + (xspeed - yspeed)/2,
+	  	          asteroid[i].yspeed + (yspeed + xspeed)/2,
 	  	          0,
 	  	          rand()%360, rand()%3, (int)(asteroid[i].fact_number/num),
 		          0, 0,
@@ -1441,8 +1297,8 @@
       
           FF_add_asteroid(asteroid[i].x,
 	  	          asteroid[i].y,
-	  	          (asteroid[i].xspeed + xspeed),
-	  	          ((asteroid[i].yspeed + yspeed) / 2),
+	  	          asteroid[i].xspeed + (xspeed + yspeed)/2,
+	  	          asteroid[i].yspeed + (yspeed - xspeed)/2,
 	  	          0,
 	  	          rand()%360, rand()%3, num,
                           0, 0,




More information about the Tux4kids-commits mailing list