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

📄 lesson21.cpp

📁 关于OpenGL的实例教程源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
 *		This Code Was Created By Jeff Molofee 2000
 *		If You've Found This Code Useful, Please Let Me Know.
 *		Visit My Site At nehe.gamedev.net
 */

#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 <gl\glaux.h>										// Header File For The Glaux Library

HDC			hDC=NULL;										// Private GDI Device Context
HGLRC		hRC=NULL;										// Permanent Rendering Context
HWND		hWnd=NULL;										// Holds Our Window Handle
HINSTANCE	hInstance;										// Holds The Instance Of The Application

bool	keys[256];											// Array Used For The Keyboard Routine
bool	vline[11][10];										// Keeps Track Of Verticle Lines
bool	hline[10][11];										// Keeps Track Of Horizontal Lines
bool	ap;													// 'A' Key Pressed?
bool	filled;												// Done Filling In The Grid?
bool	gameover;											// Is The Game Over?
bool	anti=TRUE;											// Antialiasing?
bool	active=TRUE;										// Window Active Flag Set To TRUE By Default
bool	fullscreen=TRUE;									// Fullscreen Flag Set To Fullscreen Mode By Default

int		loop1;												// Generic Loop1
int		loop2;												// Generic Loop2
int		delay;												// Enemy Delay
int		adjust=3;											// Speed Adjustment For Really Slow Video Cards
int		lives=5;											// Player Lives
int		level=1;											// Internal Game Level
int		level2=level;										// Displayed Game Level
int		stage=1;											// Game Stage

struct	object												// Create A Structure For Our Player
{
	int		fx, fy;											// Fine Movement Position
	int		x, y;											// Current Player Position
	float	spin;											// Spin Direction
};

struct	object player;										// Player Information
struct	object enemy[9];									// Enemy Information
struct	object hourglass;									// Hourglass Information

struct			 											// Create A Structure For The Timer Information
{
  __int64       frequency;									// Timer Frequency
  float         resolution;									// Timer Resolution
  unsigned long mm_timer_start;								// Multimedia Timer Start Value
  unsigned long mm_timer_elapsed;							// Multimedia Timer Elapsed Time
  bool			performance_timer;							// Using The Performance Timer?
  __int64       performance_timer_start;					// Performance Timer Start Value
  __int64       performance_timer_elapsed;					// Performance Timer Elapsed Time
} timer;													// Structure Is Named timer

int		steps[6]={ 1, 2, 4, 5, 10, 20 };					// Stepping Values For Slow Video Adjustment

GLuint	texture[2];											// Font Texture Storage Space
GLuint	base;												// Base Display List For The Font

LRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);		// Declaration For WndProc

void TimerInit(void)										// Initialize Our Timer (Get It Ready)
{
	memset(&timer, 0, sizeof(timer));						// Clear Our Timer Structure

	// Check To See If A Performance Counter Is Available
	// If One Is Available The Timer Frequency Will Be Updated
	if (!QueryPerformanceFrequency((LARGE_INTEGER *) &timer.frequency))
	{
		// No Performace Counter Available
		timer.performance_timer	= FALSE;					// Set Performance Timer To FALSE
		timer.mm_timer_start	= timeGetTime();			// Use timeGetTime() To Get Current Time
		timer.resolution		= 1.0f/1000.0f;				// Set Our Timer Resolution To .001f
		timer.frequency			= 1000;						// Set Our Timer Frequency To 1000
		timer.mm_timer_elapsed	= timer.mm_timer_start;		// Set The Elapsed Time To The Current Time
	}
	else
	{
		// Performance Counter Is Available, Use It Instead Of The Multimedia Timer
		// 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;
	}
}

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

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

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

AUX_RGBImageRec *LoadBMP(char *Filename)			        // Loads The Bitmap Images
{
		FILE *File=NULL;								    // File Handle
		if (!Filename)										// Make Sure A Filename Was Given
		{
			return NULL;									// If Not Return NULL
		}
		File=fopen(Filename,"r");							// Check To See If The File Exists
		if (File)											// Does The File Exist?
		{
			fclose(File);									// Close The Handle
			return auxDIBImageLoad(Filename);				// Load The Bitmap And Return A Pointer
		}
		return NULL;										// If Load Failed Return NULL
}

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
}

GLvoid BuildFont(GLvoid)									// Build Our Font Display List
{
	base=glGenLists(256);									// Creating 256 Display Lists
	glBindTexture(GL_TEXTURE_2D, texture[0]);				// Select Our Font Texture
	for (loop1=0; loop1<256; loop1++)						// Loop Through All 256 Lists
	{
		float cx=float(loop1%16)/16.0f;						// X Position Of Current Character
		float cy=float(loop1/16)/16.0f;						// Y Position Of Current Character

		glNewList(base+loop1,GL_COMPILE);					// Start Building A List
			glBegin(GL_QUADS);								// Use A Quad For Each Character
				glTexCoord2f(cx,1.0f-cy-0.0625f);			// Texture Coord (Bottom Left)
				glVertex2d(0,16);							// Vertex Coord (Bottom Left)
				glTexCoord2f(cx+0.0625f,1.0f-cy-0.0625f);	// Texture Coord (Bottom Right)
				glVertex2i(16,16);							// Vertex Coord (Bottom Right)
				glTexCoord2f(cx+0.0625f,1.0f-cy);			// Texture Coord (Top Right)
				glVertex2i(16,0);							// Vertex Coord (Top Right)
				glTexCoord2f(cx,1.0f-cy);					// Texture Coord (Top Left)
				glVertex2i(0,0);							// Vertex Coord (Top Left)
			glEnd();										// Done Building Our Quad (Character)
			glTranslated(15,0,0);							// Move To The Right Of The Character
		glEndList();										// Done Building The Display List
	}														// Loop Until All 256 Are Built
}

GLvoid KillFont(GLvoid)										// Delete The Font From Memory
{
	glDeleteLists(base,256);								// Delete All 256 Display Lists
}

GLvoid glPrint(GLint x, GLint y, int set, const char *fmt, ...)	// Where The Printing Happens
{
	char		text[256];									// Holds Our String
	va_list		ap;											// Pointer To List Of Arguments

	if (fmt == NULL)										// If There's No Text
		return;												// Do Nothing

	va_start(ap, fmt);										// Parses The String For Variables
	    vsprintf(text, fmt, ap);							// And Converts Symbols To Actual Numbers
	va_end(ap);												// Results Are Stored In Text

	if (set>1)												// Did User Choose An Invalid Character Set?
	{
		set=1;												// If So, Select Set 1 (Italic)
	}
	glEnable(GL_TEXTURE_2D);								// Enable Texture Mapping
	glLoadIdentity();										// Reset The Modelview Matrix
	glTranslated(x,y,0);									// Position The Text (0,0 - Bottom Left)
	glListBase(base-32+(128*set));							// Choose The Font Set (0 or 1)

	if (set==0)												// If Set 0 Is Being Used Enlarge Font
	{
		glScalef(1.5f,2.0f,1.0f);							// Enlarge Font Width And Height
	}

	glCallLists(strlen(text),GL_UNSIGNED_BYTE, text);		// Write The Text To The Screen
	glDisable(GL_TEXTURE_2D);								// Disable Texture Mapping
}

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)			// Resize And Initialize The GL Window
{
	if (height==0)											// Prevent A Divide By Zero By
	{
		height=1;											// Making Height Equal One
	}

	glViewport(0,0,width,height);							// Reset The Current Viewport

	glMatrixMode(GL_PROJECTION);							// Select The Projection Matrix
	glLoadIdentity();										// Reset The Projection Matrix

	glOrtho(0.0f,width,height,0.0f,-1.0f,1.0f);				// Create Ortho 640x480 View (0,0 At Top Left)

	glMatrixMode(GL_MODELVIEW);								// Select The Modelview Matrix
	glLoadIdentity();										// Reset The Modelview Matrix
}

int InitGL(GLvoid)											// All Setup For OpenGL Goes Here
{
	if (!LoadGLTextures())									// Jump To Texture Loading Routine
	{
		return FALSE;										// If Texture Didn't Load Return FALSE
	}

	BuildFont();											// Build The Font

	glShadeModel(GL_SMOOTH);								// Enable Smooth Shading
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);					// Black Background
	glClearDepth(1.0f);										// Depth Buffer Setup
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);					// Set Line Antialiasing
	glEnable(GL_BLEND);										// Enable Blending
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);		// Type Of Blending To Use
	return TRUE;											// Initialization Went OK
}

int DrawGLScene(GLvoid)										// Here's Where We Do All The Drawing
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// Clear Screen And Depth Buffer
	glBindTexture(GL_TEXTURE_2D, texture[0]);				// Select Our Font Texture
	glColor3f(1.0f,0.5f,1.0f);								// Set Color To Purple
	glPrint(207,24,0,"GRID CRAZY");							// Write GRID CRAZY On The Screen
	glColor3f(1.0f,1.0f,0.0f);								// Set Color To Yellow
	glPrint(20,20,1,"Level:%2i",level2);					// Write Actual Level Stats
	glPrint(20,40,1,"Stage:%2i",stage);						// Write Stage Stats

	if (gameover)											// Is The Game Over?
	{
		glColor3ub(rand()%255,rand()%255,rand()%255);		// Pick A Random Color
		glPrint(472,20,1,"GAME OVER");						// Write GAME OVER To The Screen
		glPrint(456,40,1,"PRESS SPACE");					// Write PRESS SPACE To The Screen
	}

	for (loop1=0; loop1<lives-1; loop1++)					// Loop Through Lives Minus Current Life
	{
		glLoadIdentity();									// Reset The View
		glTranslatef(490+(loop1*40.0f),40.0f,0.0f);			// Move To The Right Of Our Title Text
		glRotatef(-player.spin,0.0f,0.0f,1.0f);				// Rotate Counter Clockwise
		glColor3f(0.0f,1.0f,0.0f);							// Set Player Color To Light Green
		glBegin(GL_LINES);									// Start Drawing Our Player Using Lines
			glVertex2d(-5,-5);								// Top Left Of Player
			glVertex2d( 5, 5);								// Bottom Right Of Player
			glVertex2d( 5,-5);								// Top Right Of Player
			glVertex2d(-5, 5);								// Bottom Left Of Player
		glEnd();											// Done Drawing The Player
		glRotatef(-player.spin*0.5f,0.0f,0.0f,1.0f);		// Rotate Counter Clockwise
		glColor3f(0.0f,0.75f,0.0f);							// Set Player Color To Dark Green
		glBegin(GL_LINES);									// Start Drawing Our Player Using Lines
			glVertex2d(-7, 0);								// Left Center Of Player
			glVertex2d( 7, 0);								// Right Center Of Player
			glVertex2d( 0,-7);								// Top Center Of Player
			glVertex2d( 0, 7);								// Bottom Center Of Player
		glEnd();											// Done Drawing The Player
	}

	filled=TRUE;											// Set Filled To True Before Testing
	glLineWidth(2.0f);										// Set Line Width For Cells To 2.0f
	glDisable(GL_LINE_SMOOTH);								// Disable Antialiasing
	glLoadIdentity();										// Reset The Current Modelview Matrix
	for (loop1=0; loop1<11; loop1++)						// Loop From Left To Right
	{
		for (loop2=0; loop2<11; loop2++)					// Loop From Top To Bottom
		{
			glColor3f(0.0f,0.5f,1.0f);						// Set Line Color To Blue
			if (hline[loop1][loop2])						// Has The Horizontal Line Been Traced
			{
				glColor3f(1.0f,1.0f,1.0f);					// If So, Set Line Color To White
			}

			if (loop1<10)									// Dont Draw To Far Right
			{
				if (!hline[loop1][loop2])					// If A Horizontal Line Isn't Filled
				{
					filled=FALSE;							// filled Becomes False
				}
				glBegin(GL_LINES);							// Start Drawing Horizontal Cell Borders
					glVertex2d(20+(loop1*60),70+(loop2*40));// Left Side Of Horizontal Line
					glVertex2d(80+(loop1*60),70+(loop2*40));// Right Side Of Horizontal Line

⌨️ 快捷键说明

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