outdated: 32.Picking, Alpha Blending, Alpha Testing, Sorting
一个射击类的小demo。分为三个文件,Previous.h、Previous.cpp和Main.cpp。
在Previous.cpp的CreateWindowGL中新增了AdjustWindowRectEx()函数,可以根据客户端的期望大小计算窗口大小,矩形通过函数创建一个理想大小的窗口。
ChoosePixelFormat()函数试图匹配一个最接近的像素格式通过上下文给的像素格式规格。
在Mian.cpp文件的Selection()函数中,glGetIntegerv()函数返回一个选定后的参数的值。glSelectBuffer()函数建立了选择缓存模式值的缓冲区。glRenderMode()函数设置光栅化模型。gluPickMatrix()函数创建一个矩阵放大在鼠标处的部分。
下面为代码,
#ifndef GL_FRAMEWORK_INCLUDED #define GL_FRAMEWORK_INCLUDED #include <windows.h> typedef struct { // Structure for keyboard stuff BOOL keyDown[256]; } Keys; typedef struct { // Contains information vital to applications HMODULE hInstance; // Application Instance const char* className; } Application; typedef struct { // Window creation info Application* application; char* title; int width; int height; int bitsPerPixel; BOOL isFullScreen; } GL_WindowInit; typedef struct { // Contains information vital to a window Keys* keys; HWND hWnd; // Windows handle HDC hDC; // Device context HGLRC hRC; // Rendering context GL_WindowInit init; BOOL isVisible; // Window visiable? DWORD lastTickCount; // Tick counter } GL_Window; void TerminateApplication(GL_Window* window); // Terminate the application void ToggleFullscreen(GL_Window* window); // Toggle fullscreen / Windowed mode BOOL Initialize(GL_Window* window, Keys* keys); void Deinitialize(void); void Update(DWORD milliseconds); void Draw(void); void Selection(void); extern int mouse_x; extern int mouse_y; #endif
#include <Windows.h> #include <GL\glew.h> #include <GL\glut.h> #include "Previous.h" #define WM_TOGGLEFULLSCREEN (WM_USER+1) // Application define message for toggling // between fulscreen / windowed mode static BOOL g_isProgramLooping; // Window creation loop, for fullscreen / windowed mode static BOOL g_createFullScreen; // If true, then create window int mouse_x, mouse_y; // The current position of the mouse void TerminateApplication(GL_Window* window) // Terminate the application { PostMessage(window->hWnd, WM_QUIT, 0, 0); // Send a WM_QUIT message g_isProgramLooping = FALSE; // Stop looping of the program } void ToggleFullscreen(GL_Window* window) // Toggle fullscreen /windowed mode { PostMessage(window->hWnd, WM_TOGGLEFULLSCREEN, 0, 0); // Send a WM_TOGGLEFULLSCREEN message } void ReshapeGL(int width, int height) // Reshape the window when it's moved or resized { glViewport(0, 0, (GLsizei)(width), (GLsizei)(height)); // Reset the current viewport glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Calcutate the aspect ratio of the window gluPerspective(45.0f, (GLfloat)(width) / (GLfloat)(height), 1.0, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } BOOL ChangeScreenResolution(int width, int height, int bitsPerPixel) // Change the screen resolution { DEVMODE dmScreenSettings; // Device mode ZeroMemory(&dmScreenSettings, sizeof(DEVMODE)); // Make sure memory is cleared dmScreenSettings.dmSize = sizeof(DEVMODE); // Size of the devmode structure dmScreenSettings.dmPelsWidth = width; dmScreenSettings.dmPelsHeight = height; dmScreenSettings.dmBitsPerPel = bitsPerPixel; dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { return FALSE; // Display change failed } return TRUE; } BOOL CreateWindowGL(GL_Window* window) { DWORD windowStyle = WS_OVERLAPPEDWINDOW; // Define window style DWORD windowExtendedStyle = WS_EX_APPWINDOW; // Define the window's extended style ShowCursor(FALSE); PIXELFORMATDESCRIPTOR pdf = { sizeof(PIXELFORMATDESCRIPTOR), // Size of this pixel format descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format must support window PFD_SUPPORT_OPENGL | // Format must support openGL PFD_DOUBLEBUFFER, // Must support double buffering PFD_TYPE_RGBA, // Request an RGBA format window->init.bitsPerPixel, // Select color depth 0, 0, 0, 0, 0, 0, // Color bits ignored 0, // No alpha buffer 0, // Shift bit ignored 0, // No accumulation buffer 0, 0, 0, 0, // Accumulation bits ignored 16, // 16bits Z-buffer (depth buffer) 0, // No stencil buffer 0, // No auxiliary buffer PFD_MAIN_PLANE, // Main drawing layer 0, // Reserved 0, 0, 0 // Layer masks ignored }; RECT windowRect = { 0, 0, window->init.width, window->init.height }; // Window coordiantes GLuint PixelFormat; if (window->init.isFullScreen == TRUE) { if (ChangeScreenResolution(window->init.width, window->init.height, window->init.bitsPerPixel) == FALSE) { // Fullscreen mode failed, run in windowed mode instead MessageBox(HWND_DESKTOP, "Mode Switch Failed.\nRuning In Windowed Mode.", "Error", MB_OK | MB_ICONEXCLAMATION); window->init.isFullScreen = FALSE; } else { windowStyle = WS_POPUP; // Popup window windowExtendedStyle |= WS_EX_TOPMOST; } } else { // Adjust window, account for window borders AdjustWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle); } // Create Opengl window window->hWnd = CreateWindowEx(windowExtendedStyle, // Extended style window->init.application->className, // Class name window->init.title, // Window title windowStyle, // Window style 0, 0, // Window X,Y position windowRect.right - windowRect.left, // Window width windowRect.bottom - windowRect.top, // Window height HWND_DESKTOP, // Desktop is window's parent 0, // No menu window->init.application->hInstance, // Pass the window instance window); if (window->hWnd == 0) { // Was window creation a success? return FALSE; } window->hDC = GetDC(window->hWnd); if (window->hDC == 0) { DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } PixelFormat = ChoosePixelFormat(window->hDC, &pdf); // Find a compatible pixel format if (PixelFormat == 0) { ReleaseDC(window->hWnd, window->hDC); // Release device context window->hDC = 0; DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } if (SetPixelFormat(window->hDC, PixelFormat, &pdf) == FALSE) { // Try to set the pixel format ReleaseDC(window->hWnd, window->hDC); window->hDC = 0; DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } window->hRC = wglCreateContext(window->hDC); // Try to get a rendering context if (window->hRC == 0) { ReleaseDC(window->hWnd, window->hDC); window->hDC = 0; DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } // Make the rendering context our current rendering context if (wglMakeCurrent(window->hDC, window->hRC) == FALSE) { wglDeleteContext(window->hRC); // Delete the rendering context window->hRC = 0; ReleaseDC(window->hWnd, window->hDC); window->hDC = 0; DestroyWindow(window->hWnd); window->hWnd = 0; return FALSE; } ShowWindow(window->hWnd, SW_NORMAL); // Make the window visiable window->isVisible = TRUE; ReshapeGL(window->init.width, window->init.height); // Reshape our GL window ZeroMemory(window->keys, sizeof(Keys)); // Clear all keys window->lastTickCount = GetTickCount(); return TRUE; } BOOL DestoryWindowGL(GL_Window* window) { if (window->hWnd != 0) { if (window->hDC != 0) { wglMakeCurrent(window->hDC, 0); // Setting current active rendering context to zero if (window->hRC != 0) { wglDeleteContext(window->hRC); window->hRC = 0; } ReleaseDC(window->hWnd, window->hDC); window->hDC = 0; } DestroyWindow(window->hWnd); window->hWnd = 0; } if (window->init.isFullScreen) { ChangeDisplaySettings(NULL, 0); // Switch back to desktop resolution } ShowCursor(TRUE); return TRUE; } // Process window message callback LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Get the window context GL_Window* window = (GL_Window*)(GetWindowLong(hWnd, GWL_USERDATA)); switch (uMsg) { // Evaluate window message case WM_SYSCOMMAND: // Intercept system commands { switch (wParam) { // Check system calls case SC_SCREENSAVE: // Screensaver trying to start? case SC_MONITORPOWER: // Mointer trying to enter powersave? return 0; // Prevent form happening } break; } return 0; case WM_CREATE: { CREATESTRUCT* creation = (CREATESTRUCT*)(lParam); // Store window structure pointer window = (GL_Window*)(creation->lpCreateParams); SetWindowLong(hWnd, GWL_USERDATA, (LONG)(window)); } return 0; case WM_CLOSE: TerminateApplication(window); return 0; case WM_SIZE: switch (wParam) { case SIZE_MINIMIZED: // Was window minimized? window->isVisible = FALSE; return 0; case SIZE_MAXIMIZED: window->isVisible = TRUE; ReshapeGL(LOWORD(lParam), HIWORD(lParam)); return 0; case SIZE_RESTORED: window->isVisible = TRUE; ReshapeGL(LOWORD(lParam), HIWORD(lParam)); return 0; } break; case WM_KEYDOWN: if ((wParam >= 0) && (wParam <= 255)) { window->keys->keyDown[wParam] = TRUE; // Set the selected key(wParam) to true return 0; } break; case WM_KEYUP: if ((wParam >= 0) && (wParam <= 255)) { window->keys->keyDown[wParam] = FALSE; return 0; } break; case WM_TOGGLEFULLSCREEN: g_createFullScreen = (g_createFullScreen == TRUE) ? FALSE : TRUE; PostMessage(hWnd, WM_QUIT, 0, 0); break; case WM_LBUTTONDOWN: { mouse_x = LOWORD(lParam); mouse_y = HIWORD(lParam); Selection(); } break; case WM_MOUSEMOVE: { mouse_x = LOWORD(lParam); mouse_y = HIWORD(lParam); } break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); // Pass unhandle message to DefWindowProc } BOOL RegisterWindowClass(Application* application) { WNDCLASSEX windowClass; ZeroMemory(&windowClass, sizeof(WNDCLASSEX)); // Make sure memory is cleared windowClass.cbSize = sizeof(WNDCLASSEX); // Size of the windowClass structure windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraws the window for any movement / resizing windowClass.lpfnWndProc = (WNDPROC)(WindowProc); // WindowProc handles message windowClass.hInstance = application->hInstance; // Set the instance windowClass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE);// Class background brush color windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the arrow pointer windowClass.lpszClassName = application->className; // Sets the application className if (RegisterClassEx(&windowClass) == 0) { MessageBox(HWND_DESKTOP, "RegisterClassEx Failed!", "Error", MB_OK | MB_ICONEXCLAMATION); return FALSE; } return TRUE; } int WINAPI WinMain(HINSTANCE hIstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { Application application; GL_Window window; Keys keys; BOOL isMessagePumpActive; MSG msg; DWORD tickCount; application.className = "OpenGL"; application.hInstance = hIstance; ZeroMemory(&window, sizeof(GL_Window)); window.keys = &keys; // Window key structure window.init.application = &application; // Window application window.init.title = "Picking"; // Window title window.init.width = 640; // Window width window.init.height = 480; // Window height window.init.bitsPerPixel = 16; // Bits per pixel window.init.isFullScreen = TRUE; // Fullscreen? (set to TRUE) ZeroMemory(&keys, sizeof(Keys)); if (MessageBox(HWND_DESKTOP, "Would You Like To Run In Fullscreen Mode?", "Start FullScreen?", MB_YESNO | MB_ICONQUESTION) == IDNO) { window.init.isFullScreen = FALSE; } if (RegisterWindowClass(&application) == FALSE) { MessageBox(HWND_DESKTOP, "Error Registering Window Class!", "Error", MB_OK | MB_ICONEXCLAMATION); return -1; } g_isProgramLooping = TRUE; g_createFullScreen = window.init.isFullScreen; while (g_isProgramLooping) { // Loop until WM_QUIT is received window.init.isFullScreen = g_createFullScreen; // Set init param of window creation to fullscreen? if (CreateWindowGL(&window) == TRUE) { // Was window creation successful? // At this point we should have a window that is setup to render OpenGL if (Initialize(&window, &keys) == FALSE) { TerminateApplication(&window); // Close window, this will handle the shutdown } else { isMessagePumpActive = TRUE; while (isMessagePumpActive == TRUE) { // Success creating window. Check for window messages if (PeekMessage(&msg, window.hWnd, 0, 0, PM_REMOVE) != 0) { if (msg.message != WM_QUIT) { DispatchMessage(&msg); } else { isMessagePumpActive = FALSE; // Terminate the message pump } } else { if (window.isVisible == FALSE) { WaitMessage(); // Application is minimized wait for a message } else { // Process application loop tickCount = GetTickCount(); // Get the tick count Update(tickCount - window.lastTickCount); // Update the counter window.lastTickCount = tickCount;// Set last count to current count Draw(); // Draw screen SwapBuffers(window.hDC); } } } } // Application is finished Deinitialize(); DestoryWindowGL(&window); } else { MessageBox(HWND_DESKTOP, "Error Creating OpenGL Window", "Error", MB_OK | MB_ICONEXCLAMATION); g_isProgramLooping = FALSE; } } UnregisterClass(application.className, application.hInstance); // UnRegister window class return 0; }
#include <windows.h> #include <math.h> #include <stdio.h> #include <stdarg.h> #include <gl/glew.h> #include <GL\glut.h> #include <time.h> #include "Previous.h" #pragma comment( lib, "winmm.lib" ) // Search for winMM library while linking #pragma comment(lib, "legacy_stdio_definitions.lib") #ifndef CDS_FULLSCREEN #define CDS_FULLSCREEN 4 #endif void DrawTargets(); GL_Window* g_window; Keys* g_keys; GLuint base; // Front display list GLuint 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 compare function struct objects { GLuint rot; // Rotation bool hit; // Object hit GLuint frame; // Current explosion fram GLuint dir; // Object Direction GLuint texid; // Texture ID GLfloat x; // Object X position GLfloat y; // Object Y position GLfloat spin; // Object spin GLfloat distance; // Object distance }; typedef struct { GLubyte* imageData; GLuint bpp; // Image color depth in bits per pixel GLuint width; GLuint height; GLuint texID; } TextureImage; TextureImage textures[10]; objects object[30]; struct dimension { GLfloat w; // Width GLfloat h; // Height }; // Size of each object : Blueface, Bucket, Targets, Coke, Vase dimension 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) { 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 RGBA (32 bpp) FILE* file = fopen(filename, "rb"); if (file == NULL || fread(TGAcompare, 1, sizeof(TGAcompare), file) != sizeof(TGAcompare) || memcmp(TGAheader, TGAcompare, sizeof(TGAheader)) != 0 || fread(header, 1, sizeof(header), file) != sizeof(header)) { if (file == NULL) { return FALSE; } else { fclose(file); return FALSE; } } texture->width = header[1] * 256 + header[0]; texture->height = header[3] * 256 + header[2]; if (texture->width <= 0 || texture->height <= 0 || (header[4] != 24 && header[4] != 32)) { fclose(file); return FALSE; } texture->bpp = header[4]; bytesPerPixel = texture->bpp / 8; imageSize = texture->width * texture->height * bytesPerPixel; texture->imageData = (GLubyte*)malloc(imageSize); if (texture->imageData == NULL || fread(texture->imageData, 1, imageSize, file) != imageSize) { if (texture->imageData != NULL) { free(texture->imageData); } fclose(file); return FALSE; } for (GLuint i = 0; i < int(imageSize); i += bytesPerPixel) { temp = texture->imageData[i]; texture->imageData[i] = texture->imageData[i + 2]; texture->imageData[i + 2] = temp; } fclose(file); glGenTextures(1, &texture[0].texID); glBindTexture(GL_TEXTURE_2D, texture[0].texID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (texture[0].bpp == 24) { type = GL_RGB; } glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData); return true; } GLvoid BuildFont(GLvoid) { base = glGenLists(95); glBindTexture(GL_TEXTURE_2D, textures[9].texID); for (int loop = 0; loop < 95; ++loop) { float cx = float(loop % 16) / 16.0f; float cy = float(loop / 16) / 8.0f; glNewList(base + loop, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2f(cx, 1.0f - cy - 0.120f); glVertex2i(0, 0); glTexCoord2f(cx + 0.0625f, 1.0f - cy - 0.120f); glVertex2i(16, 0); glTexCoord2f(cx + 0.0625f, 1.0f - cy); glVertex2i(16, 16); glTexCoord2f(cx, 1.0f - cy); glVertex2i(0, 16); glEnd(); glTranslated(10, 0, 0); glEndList(); } } GLvoid glPrint(GLint x, GLint y, const char *string, ...) { char text[256]; va_list ap; // Pointer to list of arguments if (string == NULL) { return; } 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); glPushMatrix(); glLoadIdentity(); glTranslated(x, y, 0); glListBase(base - 32); glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Draws the display list text glPopMatrix(); } int Compare(struct objects* elem1, struct objects* elem2) { if (elem1->distance < elem2->distance) { return -1; } else if (elem1->distance > elem2->distance) { return 1; } else { return 0; } } GLvoid InitObject(int num) { object[num].rot = 1; // Clockwise rotation object[num].frame = 0; // Reset the explosion fram object[num].hit = FALSE; // Reset object hit status object[num].texid = rand() % 5; object[num].distance = -(float(rand() % 4001) / 100.0f); object[num].y = -1.5f + (float(rand() % 451) / 100.0f); object[num].x = ((object[num].distance - 15.0f) / 2.0f) - (5 * level) - float(rand() % (5 * level)); object[num].dir = (rand() % 2); if (object[num].dir == 0) { object[num].rot = 2; object[num].x = -object[num].x; } if (object[num].texid == 0) { // Blue face object[num].y = -2.0f; } if (object[num].texid == 1) { // Bucket object[num].dir = 3; object[num].x = float(rand() % int(object[num].distance - 10.0f)) + ((object[num].distance - 10.0f) / 2.0f); object[num].y = 4.5f; } if (object[num].texid == 2) { // Target object[num].dir = 2; 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)); } qsort((void*)&object, level, sizeof(struct objects), (compfn)Compare); } BOOL Initialize(GL_Window* window, Keys* keys) { g_window = window; g_keys = keys; srand((unsigned)time(NULL)); 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; } BuildFont(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Enable alpha blending glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glEnable(GL_CULL_FACE); for (int loop = 0; loop < 30; ++loop) { InitObject(loop); } return TRUE; } void Deinitialize(void) { glDeleteLists(base, 95); } void Selection(void) { GLuint buffer[512]; // Set up a selection buffer GLint hits; // The number of objects that we selected if (game) { return; } PlaySound("data/shot.wav", NULL, SND_ASYNC); GLint viewport[4]; // x, y, length, width // This sets the array <viewport> to the size and location of the screen relative to the window glGetIntegerv(GL_VIEWPORT, viewport); glSelectBuffer(512, buffer); // Tell opengl to use our array for selection // Puts opengl in selection mode. Nothing will be draw. Object ID's and extents are stored in the buffer (void)glRenderMode(GL_SELECT); glInitNames(); // Name stack glPushName(0); glMatrixMode(GL_PROJECTION); // Selects the projection matrix glPushMatrix(); glLoadIdentity(); // This create a matrix that will zoom up to a small portion of the screen, where the mouse is. gluPickMatrix((GLdouble)mouse_x, (GLdouble)(viewport[3] - mouse_y), 1.0f, 1.0f, viewport); // Apply the perspective matrix gluPerspective(45.0f, (GLfloat)(viewport[2] - viewport[0]) / (GLfloat)(viewport[3] - viewport[1]), 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); DrawTargets(); // Render the targets to the selection buffer glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); hits = glRenderMode(GL_RENDER); if (hits > 0) { int choose = buffer[3]; int depth = buffer[1]; for (int loop = 1; loop < hits; ++loop) { if (buffer[loop * 4 + 1] < GLuint(depth)) { choose = buffer[loop * 4 + 3]; depth = buffer[loop * 4 + 1]; } } if (!object[choose].hit) { object[choose].hit = TRUE; score += 1; kills += 1; if (kills > level * 5) { miss = 0; kills = 0; level += 1; if (level > 30) { level = 30; } } } } } void Update(DWORD milliseconds) { if (g_keys->keyDown[VK_ESCAPE]) { TerminateApplication(g_window); } if (g_keys->keyDown[' '] && game) { for (int loop = 0; loop < 30; ++loop) { InitObject(loop); } game = FALSE; score = 0; level = 1; kills = 0; miss = 0; } if (g_keys->keyDown[VK_F1]) { ToggleFullscreen(g_window); } roll -= milliseconds * 0.00005f; // Roll the clouds for (int loop = 0; loop < level; ++loop) { if (object[loop].rot == 1) // If Rotation is clockwise object[loop].spin -= 0.2f * (float(loop + milliseconds)); // Spin clockwise if (object[loop].rot == 2) // If rotation is counter clockwise object[loop].spin += 0.2f * (float(loop + milliseconds)); // Spin counter clockwise if (object[loop].dir == 1) // If direction is right object[loop].x += 0.012f * float(milliseconds); // Move right if (object[loop].dir == 0) // If direction is left object[loop].x -= 0.012f * float(milliseconds); // Move left if (object[loop].dir == 2) // If direction is up object[loop].y += 0.012f * float(milliseconds); // Move up if (object[loop].dir == 3) // If direction isdown object[loop].y -= 0.0025f * float(milliseconds); // Move down // If we are to far left, direction is left and the object was not hit if ((object[loop].x < (object[loop].distance - 15.0f) / 2.0f) && (object[loop].dir == 0) && !object[loop].hit) { miss += 1; // Increase miss object[loop].hit = TRUE; } if ((object[loop].x > -(object[loop].distance - 15.0f) / 2.0f) && (object[loop].dir == 1) && !object[loop].hit) { miss += 1; object[loop].hit = TRUE; } if ((object[loop].y < -2.0f) && (object[loop].dir == 3) && !object[loop].hit) { miss += 1; object[loop].hit = TRUE; } if ((object[loop].y > 4.5f) && (object[loop].dir == 2)) { object[loop].dir = 3; } } } void Object(float width, float height, GLuint texid) { glBindTexture(GL_TEXTURE_2D, textures[texid].texID); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-width, -height, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(width, -height, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(width, height, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-width, height, 0.0f); glEnd(); } void Explosion(int num) { float ex = (float)((object[num].frame / 4) % 4) / 4.0f; float ey = (float)((object[num].frame / 4) / 4) / 4.0f; glBindTexture(GL_TEXTURE_2D, textures[5].texID); glBegin(GL_QUADS); glTexCoord2f(ex, 1.0f - (ey)); glVertex3f(-1.0f, -1.0f, 0.0f); glTexCoord2f(ex + 0.25f, 1.0f - (ey)); glVertex3f(1.0f, -1.0f, 0.0f); glTexCoord2f(ex + 0.25f, 1.0f - (ey + 0.25f)); glVertex3f(1.0f, 1.0f, 0.0f); glTexCoord2f(ex, 1.0f - (ey + 0.25f)); glVertex3f(-1.0f, 1.0f, 0.0f); glEnd(); object[num].frame += 1; if (object[num].frame > 63) { InitObject(num); } } void DrawTargets(void) { glLoadIdentity(); glTranslatef(0.0f, 0.0f, -10.0f); for (int loop = 0; loop < level; ++loop) { glLoadName(loop); // Assign object a name (ID) glPushMatrix(); glTranslatef(object[loop].x, object[loop].y, object[loop].distance); if (object[loop].hit) { Explosion(loop); } else { glRotatef(object[loop].spin, 0.0f, 0.0f, 1.0f); Object(size[object[loop].texid].w, size[object[loop].texid].h, object[loop].texid); } glPopMatrix(); } } void Draw(void) // Draw scene { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glPushMatrix(); glBindTexture(GL_TEXTURE_2D, textures[7].texID); glBegin(GL_QUADS); glTexCoord2f(1.0f, roll / 1.5f + 1.0f); glVertex3f(28.0f, +7.0f, -50.0f); glTexCoord2f(0.0f, roll / 1.5f + 1.0f); glVertex3f(-28.0f, +7.0f, -50.0f); glTexCoord2f(0.0f, roll / 1.5f + 0.0f); glVertex3f(-28.0f, -3.0f, -50.0f); glTexCoord2f(1.0f, roll / 1.5f + 0.0f); glVertex3f(28.0f, -3.0f, -50.0f); glTexCoord2f(1.5f, roll + 1.0f); glVertex3f(28.0f, +7.0f, -50.0f); glTexCoord2f(0.5f, roll + 1.0f); glVertex3f(-28.0f, +7.0f, -50.0f); glTexCoord2f(0.5f, roll + 0.0f); glVertex3f(-28.0f, -3.0f, -50.0f); glTexCoord2f(1.5f, roll + 0.0f); glVertex3f(28.0f, -3.0f, -50.0f); glTexCoord2f(1.0f, roll / 1.5f + 1.0f); glVertex3f(28.0f, +7.0f, 0.0f); glTexCoord2f(0.0f, roll / 1.5f + 1.0f); glVertex3f(-28.0f, +7.0f, 0.0f); glTexCoord2f(0.0f, roll / 1.5f + 0.0f); glVertex3f(-28.0f, +7.0f, -50.0f); glTexCoord2f(1.0f, roll / 1.5f + 0.0f); glVertex3f(28.0f, +7.0f, -50.0f); glTexCoord2f(1.5f, roll + 1.0f); glVertex3f(28.0f, +7.0f, 0.0f); glTexCoord2f(0.5f, roll + 1.0f); glVertex3f(-28.0f, +7.0f, 0.0f); glTexCoord2f(0.5f, roll + 0.0f); glVertex3f(-28.0f, +7.0f, -50.0f); glTexCoord2f(1.5f, roll + 0.0f); glVertex3f(28.0f, +7.0f, -50.0f); glEnd(); glBindTexture(GL_TEXTURE_2D, textures[6].texID); glBegin(GL_QUADS); glTexCoord2f(7.0f, 4.0f - roll); glVertex3f(27.0f, -3.0f, -50.0f); glTexCoord2f(0.0f, 4.0f - roll); glVertex3f(-27.0f, -3.0f, -50.0f); glTexCoord2f(0.0f, 0.0f - roll); glVertex3f(-27.0f, -3.0f, 0.0f); glTexCoord2f(7.0f, 0.0f - roll); glVertex3f(27.0f, -3.0f, 0.0f); glEnd(); DrawTargets(); glPopMatrix(); // Crosshair (In Ortho View) RECT window; // Storage For Window Dimensions GetClientRect(g_window->hWnd, &window); // Get Window Dimensions glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, window.right, 0, window.bottom, -1, 1); glMatrixMode(GL_MODELVIEW); glTranslated(mouse_x, window.bottom - mouse_y, 0.0f); Object(16, 16, 8); // Crosshair glPrint(240, 450, "Productions"); glPrint(10, 10, "Level: %i", level); glPrint(250, 10, "Score: %i", score); if (miss > 9) { miss = 9; game = TRUE; } if (game) { glPrint(490, 10, "GAME OVER"); } else { glPrint(490, 10, "Morale: %i/10", 10 - miss); } glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glFlush(); // Flush the GL rendering pipeline }
Thanks for Nehe's tutorials, this is his home.