Выбрать главу

  if (texture->imageData!=NULL) // Was Image Data Loaded

  free(texture->imageData); // If So, Release The Image Data

  fclose(file); // Close The File

  return FALSE; // Return False

 }

 for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel) // Loop Through The Image Data

 { // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)

  temp=texture->imageData[i]; // Temporarily Store The Value At Image Data 'i'

  texture->imageData[i] = texture->imageData[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte

  texture->imageData[i + 2] = temp; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)

 }

 fclose (file); // Close The File

 // Build A Texture From The Data

 glGenTextures(1, &texture[0].texID); // Generate OpenGL texture IDs

 glBindTexture(GL_TEXTURE_2D, texture[0].texID); // Bind Our Texture

 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Filtered

 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtered

 if (texture[0].bpp==24) // Was The TGA 24 Bits

 {

  type=GL_RGB; // If So Set The 'type' To GL_RGB

 }

 glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData);

 return true; // Texture Building Went Ok, Return True

}

The 2D texture font code is the same code I have used in previous tutorials. However, there are a few small changes. The thing you will notice is that we are only generating 95 display lists. If you look at the font texture, you will see there are only 95 characters counting the space at the top left of the image. The second thing you will notice is we divide by 16.0f for cx and we only divide by 8.0f for cy. The reason we do this is because the font texture is 256 pixels wide, but only half as tall (128 pixels). So to calculate cx we divide by 16.0f and to calculate cy we divide by half that (8.0f).

If you do not understand the code below, go back and read through Lesson 17. The font building code is explained in detail in lesson 17!

GLvoid BuildFont(GLvoid) // Build Our Font Display List

{

 base=glGenLists(95); // Creating 95 Display Lists

 glBindTexture(GL_TEXTURE_2D, textures[9].texID); // Bind Our Font Texture

 for (int loop=0; loop<95; loop++) // Loop Through All 95 Lists

 {

  float cx=float(loop%16)/16.0f; // X Position Of Current Character

  float cy=float(loop/16)/8.0f; // Y Position Of Current Character

  glNewList(base+loop,GL_COMPILE); // Start Building A List

  glBegin(GL_QUADS); // Use A Quad For Each Character

   glTexCoord2f(cx, 1.0f-cy-0.120f); glVertex2i(0,0); // Texture / Vertex Coord (Bottom Left)

   glTexCoord2f(cx+0.0625f, 1.0f-cy-0.120f); glVertex2i(16,0); // Texutre / Vertex Coord (Bottom Right)

   glTexCoord2f(cx+0.0625f, 1.0f-cy); glVertex2i(16,16); // Texture / Vertex Coord (Top Right)

   glTexCoord2f(cx, 1.0f-cy); glVertex2i(0,16); // Texture / Vertex Coord (Top Left)

  glEnd(); // Done Building Our Quad (Character)

  glTranslated(10,0,0); // Move To The Right Of The Character

  glEndList(); // Done Building The Display List

 } // Loop Until All 256 Are Built

}

The printing code is the code is also from lesson 17, but has been modified to allow us to print the score, level and morale to the screen (variables that continually change).

GLvoid glPrint(GLint x, GLint y, const char *string, …) // Where The Printing Happens

{

 char text[256]; // Holds Our String

 va_list ap; // Pointer To List Of Arguments

 if (string == NULL) // If There's No Text

  return; // Do Nothing

 va_start(ap, string); // Parses The String For Variables

 vsprintf(text, string, ap); // And Converts Symbols To Actual Numbers

 va_end(ap); // Results Are Stored In Text

 glBindTexture(GL_TEXTURE_2D, textures[9].texID); // Select Our Font Texture

 glPushMatrix(); // Store The Modelview Matrix

 glLoadIdentity(); // Reset The Modelview Matrix

 glTranslated(x,y,0); // Position The Text (0,0 – Bottom Left)

 glListBase(base-32); // Choose The Font Set

 glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Draws The Display List Text

 glPopMatrix(); // Restore The Old Projection Matrix

}

This code will be called later in the program by qsort. It compares the distance in two structures and return –1 if the first structures distance was less than the seconds structures distance, 1 if the first structures distance is greater than the second structures distance and 0 if the distance is the same in both structures.

int Compare(struct objects *elem1, struct objects *elem2) // Compare Function *** MSDN CODE MODIFIED FOR THIS TUT ***

{

 if (elem1->distance < elem2->distance) // If First Structure distance Is Less Than The Second

  return –1; // Return –1

 else if (elem1->distance > elem2->distance) // If First Structure distance Is Greater Than The Second

  return 1; // Return 1

 else // Otherwise (If The distance Is Equal)

  return 0; // Return 0

}

The InitObject() code is where we set up each object. We start off by setting rot to 1. This gives the object clockwise rotation. Then we set the explosion animation to frame 0 (we don't want the explosion to start halfway through the animation). Next we set hit to FALSE, meaning the object has not yet been hit or set to self destruct. To select an object texture, texid is assigned a random value from 0 to 4. Zero is the blueface texture and 4 is the vase texture. This gives us one of 5 random objects.

The variable distance will be a random number from –0.0f to –40.0f (4000/100 is 40). When we actually draw the object, we translate another 10 units into the screen. So when the object are drawn, they will be drawn from –10.0f to –50.0f units into the screen (not to close, and not too far). I divide the random number by 100.0f to get a more accurate floating point value.

After assigning a random distance, we then give the object a random y value. We don't want the object any lower than –1.5f, otherwise it will be under the ground, and we dont want the object any higher than 3.0f. So to stay in that range our random number can not be any higher than 4.5f (-1.5f+4.5f=3.0f).

To calculate the x position, we use some tricky math. We take our distance and we subtract 15.0f from it. Then we divide the result by 2 and subtract 5*level. Finally, we subtract a random amount from 0.0f to 5 multiplied by the current level. We subtract the 5*level and the random amount from 0.0f to 5*level so that our object appears further off the screen on higher levels. If we didn't, the objects would appear one after another, making it even more difficult to hit all the targets than it already is.

Finally we choose a random direction (dir) from 0 (left) to 1 (right).