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

  // Get The Current Time And Store It In performance_timer_start

  QueryPerformanceCounter((LARGE_INTEGER *) &timer.performance_timer_start);

  timer.performance_timer = TRUE; // Set Performance Timer To TRUE

  // Calculate The Timer Resolution Using The Timer Frequency

  timer.resolution = (float) (((double)1.0f)/((double)timer.frequency));

  // Set The Elapsed Time To The Current Time

  timer.performance_timer_elapsed = timer.performance_timer_start;

 }

}

The section of code above sets up the timer. The code below reads the timer and returns the amount of time that has passed in milliseconds.

The first thing we do is set up a 64 bit variable called time. We will use this variable to grab the current counter value. The next line checks to see if we have a performance counter. If we do, timer.performance_timer will be TRUE and the code right after will run.

The first line of code inside the { }'s grabs the counter value and stores it in the variable we created called time. The second line takes the time we just grabbed (time and subtracts the start time that we got when we initialized the timer. This way our timer should start out pretty close to zero. We then multiply the results by the resolution to find out how many seconds have passed. The last thing we do is multiply the result by 1000 to figure out how many milliseconds have passed. After the calculation is done, our results are sent back to the section of code that called this procedure. The results will be in floating point format for greater accuracy.

If we are not using the peformance counter, the code after the else statement will be run. It does pretty much the same thing. We grab the current time with timeGetTime() and subtract our starting counter value. We multiply it by our resolution and then multiply the result by 1000 to convert from seconds into milliseconds.

float TimerGetTime() // Get Time In Milliseconds

{

 __int64 time; // time Will Hold A 64 Bit Integer

 if (timer.performance_timer) // Are We Using The Performance Timer?

 {

  QueryPerformanceCounter((LARGE_INTEGER *) &time); // Grab The Current Performance Time

  // Return The Current Time Minus The Start Time Multiplied By The Resolution And 1000 (To Get MS)

  return ( (float) ( time – timer.performance_timer_start) * timer.resolution)*1000.0f;

 } else {

  // Return The Current Time Minus The Start Time Multiplied By The Resolution And 1000 (To Get MS)

  return( (float) ( timeGetTime() – timer.mm_timer_start) * timer.resolution)*1000.0f;

 }

}

The following section of code resets the player to the top left corner of the screen, and gives the enemies a random starting point.

The top left of the screen is 0 on the x-axis and 0 on the y-axis. So by setting the player.x value to 0 we move the player to the far left side of the screen. By setting the player.y value to 0 we move our player to the top of the screen.

The fine positions have to be equal to the current player position, otherwise our player would move from whatever value it's at on the fine position to the top left of the screen. We don't want to player to move there, we want it to appear there, so we set the fine positions to 0 as well.

void ResetObjects(void) // Reset Player And Enemies

{

 player.x=0; // Reset Player X Position To Far Left Of The Screen

 player.y=0; // Reset Player Y Position To The Top Of The Screen

 player.fx=0; // Set Fine X Position To Match

 player.fy=0; // Set Fine Y Position To Match

Next we give the enemies a random starting location. The number of enemies displayed on the screen will be equal to the current (internal) level value multiplied by the current stage. Remember, the maximum value that level can equal is 3 and the maximum number of stages per level is 3. So we can have a total of 9 enemies.

To make sure we give all the viewable enemies a new position, we loop through all the visible enemies (stage times level). We set each enemies x position to 5 plus a random value from 0 to 5. (the maximum value rand can be is always the number you specify minus 1). So the enemy can appear on the grid, anywhere from 5 to 10. We then give the enemy a random value on the y axis from 0 to 10.

We don't want the enemy to move from it's old position to the new random position so we make sure the fine x (fx) and y (fy) values are equal to the actual x and y values multiplied by width and height of each tile on the screen. Each tile has a width of 60 and a height of 40.

 for (loop1=0; loop1<(stage*level); loop1++) // Loop Through All The Enemies

 {

  enemy[loop1].x=5+rand()%6; // Select A Random X Position

  enemy[loop1].y=rand()%11; // Select A Random Y Position

  enemy[loop1].fx=enemy[loop1].x*60; // Set Fine X To Match

  enemy[loop1].fy=enemy[loop1].y*40; // Set Fine Y To Match

 }

}

The AUX_RGBImageRec code hasn't changed so I'm skipping over it. In LoadGLTextures() we will load in our two textures. First the font bitmap (Font.bmp) and then the background image (Image.bmp). We'll convert both the images into textures that we can use in our game. After we have built the textures we clean up by deleting the bitmap information. Nothing really new. If you've read the other tutorials you should have no problems understanding the code.

int LoadGLTextures() // Load Bitmaps And Convert To Textures

{

 int Status=FALSE; // Status Indicator

 AUX_RGBImageRec *TextureImage[2]; // Create Storage Space For The Textures

 memset(TextureImage, 0, sizeof(void *)*2); // Set The Pointer To NULL

 if ((TextureImage[0]=LoadBMP("Data/Font.bmp")) && // Load The Font

  (TextureImage[1]=LoadBMP("Data/Image.bmp"))) // Load Background Image

 {

  Status=TRUE; // Set The Status To TRUE

  glGenTextures(2, &texture[0]); // Create The Texture

  for (loop1=0; loop1<2; loop1++) // Loop Through 2 Textures

  {

   glBindTexture(GL_TEXTURE_2D, texture[loop1]);

   glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop1]->sizeX, TextureImage[loop1]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop1]->data);

   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

  }

  for (loop1=0; loop1<2; loop1++) // Loop Through 2 Textures

  {

   if (TextureImage[loop1]) // If Texture Exists

   {

    if (TextureImage[loop1]->data) // If Texture Image Exists

    {

     free(TextureImage[loop1]->data); // Free The Texture Image Memory

    }

    free(TextureImage[loop1]); // Free The Image Structure

   }

  }

 }

 return Status; // Return The Status

}

The code below builds our font display list. I've already done a tutorial on bitmap texture fonts. All the code does is divides the Font.bmp image into 16×16 cells (256 characters). Each 16×16 cell will become a character. Because I've set the y-axis up so that positive goes down instead of up, it's necessary to subtract our y-axis values from 1.0f. Otherwise the letters will all be upside down :) If you don't understand what's going on, go back and read the bitmap texture font tutorial.