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

Because we use the stepping speed (set by the value of adjust) the program will always run the same speed. For example, if our stepping speed was 1 we would wait until the timer was greater than or equal to 2 (1*2). But if we increased the stepping speed to 2 (causing the player to move twice as many pixels at a time), the delay is increased to 4 (2*2). So even though we are moving twice as fast, the delay is twice as long, so the game still runs the same speed :)

One thing alot of people like to do is take the current time, and subtract the old time to find out how much time has passed. Then they move objects a certain distance based on the amount of time that has passed. Unfortunately I can't do that in this program because the fine movement has to be exact so that the player can line up with the lines on the grid. If the current fine x position was 59 and the computer decided the player needed to move two pixels, the player would never line up with the vertical line at position 60 on the grid.

   float start=TimerGetTime(); // Grab Timer Value Before We Draw

   // Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()

   if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?

   {

    done=TRUE; // ESC or DrawGLScene Signalled A Quit

   } else // Not Time To Quit, Update Screen

   {

    SwapBuffers(hDC); // Swap Buffers (Double Buffering)

   }

   while(TimerGetTime() < start+float(steps[adjust]*2.0f)) {}// Waste Cycles On Fast Systems

The following code hasn't really changed. I changed the title of the window to read "NeHe's Line Tutorial".

   if (keys[VK_F1]) // Is F1 Being Pressed?

   {

    keys[VK_F1]=FALSE; // If So Make Key FALSE

    KillGLWindow(); // Kill Our Current Window

    fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode

    // Recreate Our OpenGL Window

    if (!CreateGLWindow("NeHe's Line Tutorial", 640, 480, 16, fullscreen)) {

     return 0; // Quit If Window Was Not Created

    }

   }

This section of code checks to see if the A key is being pressed and not held. If 'A' is being pressed, ap becomes TRUE (telling our program that A is being held down), and anti is toggled from TRUE to FALSE or FALSE to TRUE. Remember that anti is checked in the drawing code to see if antialiasing is turned on or off.

If the 'A' key has been released (is FALSE) then ap is set to FALSE telling the program that the key is no longer being held down.

   if (keys['A'] && !ap) // If 'A' Key Is Pressed And Not Held

   {

    ap=TRUE; // ap Becomes TRUE

    anti=!anti; // Toggle Antialiasing

   }

   if (!keys['A']) // If 'A' Key Has Been Released

   {

    ap=FALSE; // ap Becomes FALSE

   }

Now to move the enemies. I wanted to keep this section of code really simple. There is very little logic. Basically, the enemies check to see where you are and they move in that direction. Because I'm checking the actual x and y position of the players and no the fine values, the players seem to have a little more intelligence. They may see that you are way at the top of the screen. But by the time they're fine value actually gets to the top of the screen, you could already be in a different location. This causes them to sometimes move past you, before they realize you are no longer where they thought you were. May sound like they're really dumb, but because they sometimes move past you, you might find yourself being boxed in from all directions.

We start off by checking to make sure the game isn't over, and that the window (if in windowed mode) is still active. By checking active the enemies wont move if the screen is minimized. This gives you a convenient pause feature when you need to take a break :)

After we've made sure the enemies should be moving, we create a loop. The loop will loop through all the visible enemies. Again we calculate how many enemies should be on the screen by multiplying the current stage by the current internal level.

   if (!gameover && active) // If Game Isn't Over And Programs Active Move Objects

   {

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

    {

Now we move the current enemy (enemy[loop1]). We start off by checking to see if the enemy's x position is less than the players x position and we make sure that the enemy's fine y position lines up with a horizontal line. We can't move the enemy left and right if it's not on a horizontal line. If we did, the enemy would cut right through the middle of the boxes, making the game even more difficult :)

If the enemy x position is less than the player x position, and the enemy's fine y position is lined up with a horizontal line, we move the enemy x position one block closer to the current player position.

We also do this to move the enemy left, down and up. When moving up and down, we need to make sure the enemy's fine x position lines up with a vertical line. We don't want the enemy cutting through the top or bottom of a box.

Note: changing the enemies x and y positions doesn't move the enemy on the screen. Remember that when we drew the enemies we used the fine positions to place the enemies on the screen. Changing the x and y positions just tells our program where we WANT the enemies to move.

     if ((enemy[loop1].x<player.x) && (enemy[loop1].fy==enemy[loop1].y*40)) {

      enemy[loop1].x++; // Move The Enemy Right

     }

     if ((enemy[loop1].x>player.x) && (enemy[loop1].fy==enemy[loop1].y*40)) {

      enemy[loop1].x--; // Move The Enemy Left

     }

     if ((enemy[loop1].y<player.y) && (enemy[loop1].fx==enemy[loop1].x*60)) {

      enemy[loop1].y++; // Move The Enemy Down

     }

     if ((enemy[loop1].y>player.y) && (enemy[loop1].fx==enemy[loop1].x*60)) {

      enemy[loop1].y--; // Move The Enemy Up

     }

This code does the actual moving. We check to see if the variable delay is greater than 3 minus the current internal level. That way if our current level is 1 the program will loop through 2 (3-1) times before the enemies actually move. On level 3 (the highest value that level can be) the enemies will move the same speed as the player (no delays). We also make sure that hourglass.fx isn't the same as 2. Remember, if hourglass.fx is equal to 2, that means the player has touched the hourglass. Meaning the enemies shouldn't be moving.

If delay is greater than 3-level and the player hasn't touched the hourglass, we move the enemies by adjusting the enemy fine positions (fx and fy). The first thing we do is set delay back to 0 so that we can start the delay counter again. Then we set up a loop that loops through all the visible enemies (stage times level).

     if (delay>(3-level) && (hourglass.fx!=2)) // If Our Delay Is Done And Player Doesn't Have Hourglass

     {

      delay=0; // Reset The Delay Counter Back To Zero

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