⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lesson32.cpp

📁 关于OpenGL的实例教程源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**************************************
*                                     *
*   Jeff Molofee's Picking Tutorial   *
*          nehe.gamedev.net           *
*                2001                 *
*                                     *
**************************************/

#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

#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

#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;

// 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
bool		game;												// Game Over?

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

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
};

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

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

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

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} };

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)										// Did 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?
	{
		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
}

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
}

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
}

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
}

GLvoid InitObject(int num)										// Initialize An Object
{
	object[num].rot=1;											// Clockwise Rotation
	object[num].frame=0;										// Reset The Explosion Frame To Zero
	object[num].hit=FALSE;										// Reset Object Has Been Hit Status To False
	object[num].texid=rand()%5;									// Assign A New Texture
	object[num].distance=-(float(rand()%4001)/100.0f);			// Random Distance
	object[num].y=-1.5f+(float(rand()%451)/100.0f);				// Random Y Position
	// Random Starting X Position Based On Distance Of Object And Random Amount For A Delay (Positive Value)
	object[num].x=((object[num].distance-15.0f)/2.0f)-(5*level)-float(rand()%(5*level));
	object[num].dir=(rand()%2);									// Pick A Random Direction

	if (object[num].dir==0)										// Is Random Direction Right
	{
		object[num].rot=2;										// Counter Clockwise Rotation
		object[num].x=-object[num].x;							// Start On The Left Side (Negative Value)
	}

	if (object[num].texid==0)									// Blue Face
		object[num].y=-2.0f;									// Always Rolling On The Ground

	if (object[num].texid==1)									// Bucket
	{
		object[num].dir=3;										// Falling Down
		object[num].x=float(rand()%int(object[num].distance-10.0f))+((object[num].distance-10.0f)/2.0f);
		object[num].y=4.5f;										// Random X, Start At Top Of The Screen
	}

	if (object[num].texid==2)									// Target
	{
		object[num].dir=2;										// Start Off Flying Up
		object[num].x=float(rand()%int(object[num].distance-10.0f))+((object[num].distance-10.0f)/2.0f);
		object[num].y=-3.0f-float(rand()%(5*level));			// Random X, Start Under Ground + Random Value
	}

	// Sort Objects By Distance:	Beginning Address Of Our object Array	*** MSDN CODE MODIFIED FOR THIS TUT ***
	//								Number Of Elements To Sort
	//								Size Of Each Element
	//								Pointer To Our Compare Function
	qsort((void *) &object, level, sizeof(struct objects), (compfn)Compare );
}

BOOL Initialize (GL_Window* window, Keys* keys)					// Any OpenGL Initialization Goes Here
{
	g_window	= window;
	g_keys		= keys;

	srand( (unsigned)time( NULL ) );							// Randomize Things

	if ((!LoadTGA(&textures[0],"Data/BlueFace.tga")) ||			// Load The BlueFace Texture
		(!LoadTGA(&textures[1],"Data/Bucket.tga")) ||			// Load The Bucket Texture
		(!LoadTGA(&textures[2],"Data/Target.tga")) ||			// Load The Target Texture
		(!LoadTGA(&textures[3],"Data/Coke.tga")) ||				// Load The Coke Texture
		(!LoadTGA(&textures[4],"Data/Vase.tga")) ||				// Load The Vase Texture
		(!LoadTGA(&textures[5],"Data/Explode.tga")) ||			// Load The Explosion Texture
		(!LoadTGA(&textures[6],"Data/Ground.tga")) ||			// Load The Ground Texture
		(!LoadTGA(&textures[7],"Data/Sky.tga")) ||				// Load The Sky Texture
		(!LoadTGA(&textures[8],"Data/Crosshair.tga")) ||		// Load The Crosshair Texture
		(!LoadTGA(&textures[9],"Data/Font.tga")))				// Load The Crosshair Texture
	{
		return FALSE;											// If Loading Failed, Return False
	}

	BuildFont();												// Build Our Font Display List

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);						// Black Background
	glClearDepth(1.0f);											// Depth Buffer Setup
	glDepthFunc(GL_LEQUAL);										// Type Of Depth Testing
	glEnable(GL_DEPTH_TEST);									// Enable Depth Testing
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);			// Enable Alpha Blending (disable alpha testing)
	glEnable(GL_BLEND);											// Enable Blending       (disable alpha testing)
//	glAlphaFunc(GL_GREATER,0.1f);								// Set Alpha Testing     (disable blending)
//	glEnable(GL_ALPHA_TEST);									// Enable Alpha Testing  (disable blending)
	glEnable(GL_TEXTURE_2D);									// Enable Texture Mapping
	glEnable(GL_CULL_FACE);										// Remove Back Face

	for (int loop=0; loop<30; loop++)							// Loop Through 30 Objects

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -