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

A follow up to this tutorial on Skeletal Animation can be found on Brett's homepage. Visit the link above!

Brett Porter
Jeff Molofee (NeHe)

* DOWNLOAD Visual C++ Code For This Lesson.

* DOWNLOAD Linux/GLX Code For This Lesson. (Conversion by Rodolphe Suescun)

Lesson 32

Welcome to Tutorial 32. This tutorial is probably the largest tutorial I have written to date. Over 1000 lines of Code and more than 1540 lines of HTML. This is also the first tutorial to use my new NeHeGL basecode. This tutorial took a long time to write, but I think it was worth the wait. Some of the topics I cover in this tutorial are: Alpha Blending, Alpha Testing, Reading The Mouse, Using Both Ortho And Perspective.

At The Same Time, Displaying A Custom Cursor, Manually Sorting Objects By Depth, Animating Frames From A Single Texture and most important, you will learn all about PICKING!

The original version of this tutorial displayed three objects on the screen that would change color when you clicked on them. How exciting is that!?! Not exciting at all! As always, I wanted to impress you guys with a super cool tutorial. I wanted the tutorial to be exciting, packed full of information and of course… nice to look at. So, after weeks of coding, the tutorials is done! Even if you don't code you might enjoy this tutorial. It's a complete game. The object of the game is to shoot as many targets as you can before your morale hits rock bottom or your hand cramps up and you can no longer click the mouse button.

I'm sure there will be critics, but I'm very happy with this tutorial! I've taken dull topics such as picking and sorting object by depth and turned them into something fun!

Some quick notes about the code. I will only discuss the code in lesson33.cpp. There have been a few minor changes in the NeHeGL code. The most important change is that I have added mouse support to WindowProc(). I also added int mouse_x, mouse_y to store mouse movement. In NeHeGL.h the following two lines of code were added: extern int mouse_x; & extern int mouse_y;

The textures used in this tutorial were made in Adobe Photoshop. Each .TGA file is a 32 bit image with an alpha channel. If you are not sure how to add an alpha channel to an image buy yourself a good book, browse the net or read the built in help in Adobe Photoshop. The entire process is very similar to the way I created masks in the masking tutorial. Load your object into Adobe Photoshop (or some other art program that supports the alpha channel). Use select by color range to select the area around your object. Copy that area. Create a new image. Paste the selection into the new image. Negate the image so the area where you image should be is black. Make the area around it white. Select the entire image and copy it. Go back to the original image and create an alpha channel. Paste the black and white mask that you just created into the alpha channel. Save the image as a 32 bit .TGA file. Make sure preserve transparency is checked, and make sure you save it uncompressed!

As always I hope you enjoy the tutorial. I'm interested to hear what you think of it. If you have any questions or you find any mistakes, let me know. I rushed though parts of the tutorial, so if you find any part really hard to understand, send me some email and I'll try to explain things differently or in more detail!

#include <windows.h> // Header File For Windows

#include <stdio.h> // Header File For Standard Input / Output

#include <stdarg.h> // Header File For Variable Argument Routines

#include <gl\gl.h> // Header File For The OpenGL32 Library

#include <gl\glu.h> // Header File For The GLu32 Library

#include <time.h> // For Random Seed

#include "NeHeGL.h" // Header File For NeHeGL

In lesson 1, I preached about the proper way to link to the OpenGL libraries. In Visual C++ click on project, settings and then the link tab. Move down to object/library modules and add OpenGL32.lib, GLu32.lib and GLaux.lib. Failing to include a required library will cause the compiler to spout out error after error. Something you don't want happening! To make matters worse, if you only include the libaries in debug mode, and someone tries to build your code in release mode… more errors. There are alot of people looking for code. Most of them are new to programming. They grab your code, and try to compile it. They get errors, delete the code and move on.

The code below tells the compiler to link to the required libraries. A little more typing, but alot less headache in the long run. For this tutorial, we will link to the OpenGL32 library, the GLu32 library and the WinMM library (for playing sound). In this tutorial we will be loading .TGA files so we don't need the GLaux library.

#pragma comment( lib, "opengl32.lib" ) // Search For OpenGL32.lib While Linking

#pragma comment( lib, "glu32.lib" ) // Search For GLu32.lib While Linking

#pragma comment( lib, "winmm.lib" ) // Search For WinMM Library While Linking

The 3 lines below check to see if CDS_FULLSCREEN has been defined by your compiler. If it has not been defined, we manually give CDS_FULLSCREEN a value of 4. For those of you that are completely lost right now… Some compilers do not give CDS_FULLSCREEN a value and will return an error message if CDS_FULLSCREEN is used! To prevent an error message, we check to see if CDS_FULLSCREEN has been defined and if not, we manually define it. Makes life easier for everyone.

We then declare DrawTargets, and set up variables for our window and keyboard handling. If you don't understand declarations, read through the MSDN glossary. Keep in mind, I'm not teaching C/C++, buy a good book if you need help with the NON GL code!

#ifndef CDS_FULLSCREEN // CDS_FULLSCREEN Is Not Defined By Some

#define CDS_FULLSCREEN 4 // Compilers. By Defining It This Way,

#endif // We Can Avoid Errors

void DrawTargets(); // Declaration

GL_Window* g_window;

Keys* g_keys;

The following section of code sets up our user defined variables. base will be used for our font display lists. roll will be used to move the ground and create the illusion of rolling clouds. level should be pretty straight forward (we start off on level 1). miss keeps track of how many objects were missed. It's also used to show the players morale (no misses means a high morale). kills keeps track of how many targets were hit each level. score will keep a running total of the number of objects hit, and game will be used to signal game over!

The last line lets us pass structures to our compare function. The qsort routine expects the last parameter to be type type (const *void, const *void).

// User Defined Variables

GLuint base; // Font Display List

GLfloat roll; // Rolling Clouds

GLint level=1; // Current Level

GLint miss; // Missed Targets

GLint kills; // Level Kill Counter

GLint score; // Current Score