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
Previous.h
#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;
}
Previous.cpp
#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
}
Main.cpp

Thanks for Nehe's tutorials, this is his home.

posted @ 2016-09-04 23:37  clairvoyant  阅读(206)  评论(0编辑  收藏  举报