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

bool game; // Game Over?

typedef int (*compfn)(const void*, const void*); // Typedef For Our Compare Function

Now for our objects structure. This structure holds all the information about an object. The direction it's rotating, if it's been hit, it's location on the screen, etc.

A quick rundown of the variables… rot specifies the direction we want to rotate the object. hit will be FALSE if the object has not yet been hit. If the object was hit or manually flagged as being hit, the value of hit will be TRUE.

The variable frame is used to cycle through the frames of animation for our explosion. As frame is increased the explosion texture changes. More on this later in the tutorial.

To keep track of which direction our object is moving, we have a variable called dir. dir can be one of 4 values: 0 — object is moving Left, 1 — object is moving right, 2 — object is moving up and finally 3 — object is moving down.

texid can be any number from 0 to 4. Zero represents the BlueFace texture, 1 is the Bucket texture, 2 is the Target texture, 3 is the Coke can texture and 4 is the Vase texture. Later in the load texture code, you will see that the first 5 textures are the target images.

Both x and y are used to position the object on the screen. x represents where the object is on the x-axis, and y the location of the object on the y-axis.

The objects rotate on the z-axis based on the value of spin. Later in the code, we will increase or decrease spin based on the direction the object is travelling.

Finally, distance keeps track of how far into the screen our object is. distance is an extremely important variable, we will use it to calculate the left and right sides of the screen, and to sort the objects so the objects in the distance are drawn before the objects up close.

struct objects {

 GLuint rot; // Rotation (0-None, 1-Clockwise, 2-Counter Clockwise)

 bool hit; // Object Hit?

 GLuint frame; // Current Explosion Frame

 GLuint dir; // Object Direction (0-Left, 1-Right, 2-Up, 3-Down)

 GLuint texid; // Object Texture ID

 GLfloat x; // Object X Position

 GLfloat y; // Object Y Position

 GLfloat spin; // Object Spin

 GLfloat distance; // Object Distance

};

No real reason to explain the code below. We are loading TGA images in this tutorial instead of bitmaps. The structure below is used to store image data, as well as information about the TGA image. Read the tutorial on loading TGA files if you need a detailed explanation of the code below.

typedef struct // Create A Structure

{

 GLubyte *imageData; // Image Data (Up To 32 Bits)

 GLuint bpp; // Image Color Depth In Bits Per Pixel.

 GLuint width; // Image Width

 GLuint height; // Image Height

 GLuint texID; // Texture ID Used To Select A Texture

} TextureImage; // Structure Name

The following code sets aside room for our 10 textures and 30 objects. If you plan to add more objects to the game make sure you increase the value from 30 to however many objects you want.

TextureImage textures[10]; // Storage For 10 Textures

objects object[30]; // Storage For 30 Objects

I didn't want to limit the size of each object. I wanted the vase to be taller than the can, I wanted the bucket to be wider than the vase. To make life easy, I create a structure that holds the objects width (w) and height (h).

I then set the width and height of each object in the last line of code. To get the coke cans width, I would check size[3].w. The Blueface is 0, the Bucket is 1, and the Target is 2, etc. The width is represented by w. Make sense?

struct dimensions { // Object Dimensions

 GLfloat w; // Object Width

 GLfloat h; // Object Height

};

// Size Of Each Object: Blueface, Bucket, Target, Coke, Vase

dimensions size[5] = { {1.0f,1.0f}, {1.0f,1.0f}, {1.0f,1.0f}, {0.5f,1.0f}, {0.75f,1.5f} };

The following large section of code loads our TGA images and converts them to textures. It's the same code I used in lesson 25 so if you need a detailed description go back and read lesson 25.

I use TGA images because they are capable of having an alpha channel. The alpha channel tells OpenGL which parts of the image are transparent and which parts are opaque. The alpha channel is created in an art program, and is saved inside the .TGA image. OpenGL loads the image, and uses the alpha channel to set the amount of transparency for each pixel in the image.

bool LoadTGA(TextureImage *texture, char *filename) // Loads A TGA File Into Memory

{

 GLubyte TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header

 GLubyte TGAcompare[12]; // Used To Compare TGA Header

 GLubyte header[6]; // First 6 Useful Bytes From The Header

 GLuint bytesPerPixel; // Holds Number Of Bytes Per Pixel Used In The TGA File

 GLuint imageSize; // Used To Store The Image Size When Setting Aside Ram

 GLuint temp; // Temporary Variable

 GLuint type=GL_RGBA; // Set The Default GL Mode To RBGA (32 BPP)

 FILE *file = fopen(filename, "rb"); // Open The TGA File

 if (file==NULL || // Does File Even Exist?

  fread(TGAcompare, 1, sizeof(TGAcompare), file) != sizeof(TGAcompare) || // Are There 12 Bytes To Read?

  memcmp(TGAheader, TGAcompare, sizeof(TGAheader)) != 0 || // Does The Header Match What We Want?

  fread(header, 1, sizeof(header), file) != sizeof(header)) // If So Read Next 6 Header Bytes

 {

  if (file == NULL) // Does The File Even Exist? *Added Jim Strong*

   return FALSE; // Return False

  else // Otherwise

  {

   fclose(file); // If Anything Failed, Close The File

   return FALSE; // Return False

  }

 }

 texture->width = header[1] * 256 + header[0]; // Determine The TGA Width (highbyte*256+lowbyte)

 texture->height = header[3] * 256 + header[2]; // Determine The TGA Height (highbyte*256+lowbyte)

 if (texture->width <=0 || // Is The Width Less Than Or Equal To Zero

  texture->height <=0 || // Is The Height Less Than Or Equal To Zero

  (header[4]!=24 && header[4]!=32)) // Is The TGA 24 or 32 Bit?

 {

  fclose(file); // If Anything Failed, Close The File

  return FALSE; // Return False

 }

 texture->bpp = header[4]; // Grab The TGA's Bits Per Pixel (24 or 32)

 bytesPerPixel = texture->bpp/8; // Divide By 8 To Get The Bytes Per Pixel

 imageSize = texture->width*texture->height*bytesPerPixel; // Calculate The Memory Required For The TGA Data

 texture->imageData=(GLubyte *)malloc(imageSize); // Reserve Memory To Hold The TGA Data

 if (texture->imageData==NULL || // Does The Storage Memory Exist?

  fread(texture->imageData, 1, imageSize, file) != imageSize) // Does The Image Size Match The Memory Reserved?

 {