zoukankan      html  css  js  c++  java
  • outdated: 21.Lines, Antialiasing, Timing, Ortho View And Simple Sounds

    这是一个简单的小游戏,类型相当于amidar,不过也有1000行,手困眼花......UPDOWNLEFTRIGHT控制,SPACE重新开始。

    在TimerInit()函数中,QueryPerformanceFrequency()函数查询性能计数器的频率。QueryPerformanceCounter()函数查询性能计数器的当前值。两个函数的参数都用到了LARGE_INTEGER的强制转换。以前写过一篇介绍的文章

    在glPrint()函数里,新添了glScalef()函数(用缩放矩阵乘以当前矩阵),此处用来扩大字体矩阵的宽和高。glOrtho()函数(用投影矩阵乘以当前矩阵),此处用来创建一个680X480矩阵。

    enmey对于player的追踪,代码如下。

     1 if ((enemy[loop1].x < player.x) && (enemy[loop1].fy == enemy[loop1].y * 40)) {
     2     enemy[loop1].x++;                 // Move the enemy right
     3 }
     4 if ((enemy[loop1].x > player.x) && (enemy[loop1].fy == enemy[loop1].y * 40)) {
     5     enemy[loop1].x--;                 // Move the enemy left
     6 }
     7 if ((enemy[loop1].y < player.y) && (enemy[loop1].fx == enemy[loop1].x * 60)) {
     8     enemy[loop1].y++;                 // Move the enemy down
     9 }
    10 if ((enemy[loop1].y > player.y) && (enemy[loop1].fx == enemy[loop1].x * 60)) {
    11     enemy[loop1].y--;                 // Move the enemy up
    12 }

    enemy每次走一个像素点,player在y轴上走每次40个像素点,在x轴上每次走60个像素点。按照每个方块的边角值fx、fy(游戏窗口的大小)来判定是否相等,如果过按照x、y来判定是否相遇,那enemy就吃炫迈了。

    代码如下,同样修改部分位于双行星号内,但基本是重写了一遍。

       1 #include <windows.h>
       2 #include <stdio.h>
       3 #include <math.h>
       4 #include <gl/glew.h>
       5 #include <gl/glut.h>
       6 #include <GL/GLUAX.H>
       7 #pragma comment(lib, "legacy_stdio_definitions.lib")
       8 /*
       9  *  Every OpenGL program is linked to a Rendering Context.
      10  *  A Rendering Context is what links OpenGL calls to the Device Context.
      11  *  In order for your program to draw to a Window you need to create a Device Context.
      12  *  The DC connects the Window to the GDI (Graphics Device Interface).
      13  */
      14 
      15 HGLRC     hRC = NULL;         // Permanent rendering context
      16 HDC       hDC = NULL;         // Private GDI device context
      17 HWND      hWnd = NULL;        // Holds our window handle
      18 HINSTANCE hInstance;          // Holds the instance of the application
      19 
      20 /*
      21  *  It's important to make this global so that each procedure knows if 
      22  *  the program is running in fullscreen mode or not.
      23  */
      24 
      25 bool keys[256];         // Array used for the keyboard routine
      26 bool active = TRUE;     // Window active flag set to TRUE by default
      27 bool fullscreen = TRUE; // Fullscreen flag set to fullscreen mode by default
      28 
      29 /******************************************************************************************************************************************/
      30 /******************************************************************************************************************************************/
      31 bool vline[11][10];                 // Verticle lines
      32 bool hline[10][11];                 // Horizontal lines
      33 bool ap;                            // 'A' key press
      34 bool filled;                        // Done filling in the grid
      35 bool gameover;
      36 bool anti = TRUE;                   // Antialiasing
      37 
      38 int loop1;
      39 int loop2;
      40 int delay;                          // Enemy delay
      41 int adjust = 3;                     // Speed adjustment for really slow video cards
      42 int lives = 5;                      // Player lives
      43 int level = 1;                      // Internal game level
      44 int level2 = level;                 // Display game level
      45 int stage = 1;                      // Game stage
      46 
      47 struct object {                     // Player
      48     int fx, fy;                     // Fine Movement position
      49     int x, y;                       // Current player position
      50     float spin;                     // Spin direction
      51 };
      52 struct object player;
      53 struct object enemy[9];
      54 struct object hourglass;
      55 
      56 struct {                                      // Timer information
      57     __int64 frequency;
      58     float resolution;
      59     unsigned long mm_timer_start;             // Multimedia timer start value
      60     unsigned long mm_timer_elapsed;           // Multimedia timer elspsed time
      61     bool performance_timer;                   // Using the performance timer ?
      62     __int64 performance_timer_start;          // Performance timer start value
      63     __int64 performance_timer_elapsed;        // Performance timer elspsed value
      64 } timer;
      65 
      66 int steps[6] = { 1, 2, 4, 5, 10, 20 };        // Stepping values for slow video adjustment
      67 
      68 GLuint texture[2];                   // Font texture storage space
      69 GLuint base;                         // Base display list for the font
      70 
      71 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc
      72 
      73 void TimerInit(void)                                  // Initialize timer
      74 {
      75     memset(&timer, 0, sizeof(timer));
      76     // Check to see if a performance counter is available
      77     // If one is available the timer frequency will be updated
      78     if (!QueryPerformanceFrequency((LARGE_INTEGER *)&timer.frequency)) {
      79         // No performance counter available
      80         timer.performance_timer = FALSE;
      81         timer.mm_timer_start = timeGetTime();            // To get current time
      82         timer.resolution = 1.0f / 1000.0f;
      83         timer.frequency = 1000;
      84         timer.mm_timer_elapsed = timer.mm_timer_start;
      85     }
      86     else {
      87         // Performance counter is available, use it instead of the multimedia timer
      88         // Get the current time and store it in performance_timer_start
      89         QueryPerformanceCounter((LARGE_INTEGER *)&timer.performance_timer_start);
      90         timer.performance_timer = TRUE;
      91         timer.resolution = (float)(((double)1.0f) / ((double)timer.frequency));
      92         timer.performance_timer_elapsed = timer.performance_timer_start;
      93     }
      94 }
      95 
      96 float TimerGetTime()                      // Get time in milliseconds
      97 {
      98     __int64 time;
      99 
     100     if (timer.performance_timer) {
     101         QueryPerformanceCounter((LARGE_INTEGER *)&time);
     102         return ((float)(time - timer.performance_timer_start) * timer.resolution) * 1000.0f;
     103     }
     104     else {
     105         return ((float)(timeGetTime() - timer.mm_timer_start) * timer.resolution) * 1000.0f;
     106     }
     107 }
     108 
     109 void ResetObjects(void)                      // Reset player and enemies
     110 {
     111     player.x = 0;
     112     player.y = 0;
     113     player.fx = 0;
     114     player.fy = 0;
     115 
     116     for (loop1 = 0; loop1 < (stage * level); ++loop1) {
     117         enemy[loop1].x = 5 + rand() % 6;
     118         enemy[loop1].y = rand() % 11;
     119         enemy[loop1].fx = enemy[loop1].x * 60;
     120         enemy[loop1].fy = enemy[loop1].y * 40;
     121     }
     122 }
     123 
     124 AUX_RGBImageRec* LoadBMP(char* Filename)
     125 {
     126     FILE* File = NULL;
     127     
     128     if (!Filename) {
     129         return NULL;
     130     }
     131 
     132     File = fopen(Filename, "r");
     133     if (File) {
     134         fclose(File);
     135         return auxDIBImageLoad(Filename);
     136     }
     137 
     138     return NULL;
     139 }
     140 
     141 int LoadGLTextures()
     142 {
     143     int Status = FALSE;
     144 
     145     AUX_RGBImageRec* TextureImage[2];
     146     
     147     memset(TextureImage, 0, sizeof(void*) * 2);
     148 
     149     if ((TextureImage[0] = LoadBMP("Font.bmp")) &&
     150         (TextureImage[1] = LoadBMP("Image.bmp")))
     151     {
     152         Status = TRUE;
     153         glGenTextures(2, &texture[0]);
     154 
     155         for (loop1 = 0; loop1 < 2; ++loop1) {
     156             glBindTexture(GL_TEXTURE_2D, texture[loop1]);
     157             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     158             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     159             glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop1]->sizeX, TextureImage[loop1]->sizeY,
     160                 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop1]->data);
     161         }
     162     }
     163 
     164     for (loop1 = 0; loop1 < 2; ++loop1) {
     165         if (TextureImage[loop1]) {
     166             if (TextureImage[loop1]->data) {
     167                 free(TextureImage[loop1]->data);
     168             }
     169             free(TextureImage[loop1]);
     170         }
     171     }
     172     return Status;
     173 }
     174 
     175 GLvoid BuildFont(GLvoid)
     176 {
     177     base = glGenLists(256);
     178     glBindTexture(GL_TEXTURE_2D, texture[0]);
     179     for (loop1 = 0; loop1 < 256; ++loop1) {
     180         float cx = float(loop1 % 16) / 16.0f;                        // X position of current character
     181         float cy = float(loop1 / 16) / 16.0f;                        // Y position of current character
     182 
     183         glNewList(base + loop1, GL_COMPILE);
     184             glBegin(GL_QUADS);
     185                 glTexCoord2f(cx, 1.0f - cy - 0.0625f);               // Bottom left
     186                 glVertex2d(0, 16);
     187                 glTexCoord2f(cx + 0.0625f, 1.0f - cy - 0.0625f);     // Bottom right
     188                 glVertex2d(16, 16);
     189                 glTexCoord2f(cx + 0.0625f, 1.0f - cy);               // Top right
     190                 glVertex2d(16, 0);
     191                 glTexCoord2f(cx, 1.0f - cy);                         // Top left
     192                 glVertex2d(0, 0);
     193             glEnd();
     194             glTranslated(15, 0, 0);
     195         glEndList();
     196     }
     197 }
     198 
     199 GLvoid KillFont(GLvoid)
     200 {
     201     glDeleteLists(base, 256);
     202 }
     203 
     204 GLvoid glPrint(GLint x, GLint y, int set, const char* fmt, ...)
     205 {
     206     char text[256];
     207     va_list ap;                             // Pointer to listof arguments
     208 
     209     if (fmt == NULL) {
     210         return;
     211     }
     212 
     213     va_start(ap, fmt);                      // Parses the string for variables
     214         vsprintf(text, fmt, ap);            // And converts symbols ot actual numbers
     215     va_end(ap);                             // Results are stoed in text
     216 
     217     if (set > 1) {                          // Did user choose an invalid character set
     218         set = 1;
     219     }
     220     glEnable(GL_TEXTURE_2D);
     221     glLoadIdentity();
     222     glTranslated(x, y, 0);                  // Position the text (0, 0, -Bottom left)
     223     glListBase(base - 32 + (128 * set));    // Choose the font set (0 or 1)
     224 
     225     if (set == 0) {
     226         glScalef(1.5f, 2.0f, 1.0f);         // Enlarge font width and height
     227     }
     228     glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);    // Write the text to the screen
     229     glDisable(GL_TEXTURE_2D);
     230 }
     231 
     232 GLvoid ReSizeGLScene(GLsizei width, GLsizei height)   // Resize and initialize the GL window
     233 {
     234     if (height == 0) {                                // Prevent a divide by zero by
     235         height = 1;                                   // Making height equal one
     236     }
     237     
     238     glViewport(0, 0, width, height);                  // Reset the current viewport
     239 
     240     /*
     241      *  The following lines set the screen up for a perspective view. 
     242      *  Meaning things in the distance get smaller. This creates a realistic looking scene. 
     243      *  The perspective is calculated with a 45 degree viewing angle based on 
     244      *  the windows width and height. The 0.1f, 100.0f is the starting point and 
     245      *  ending point for how deep we can draw into the screen.
     246      *
     247      *  The projection matrix is responsible for adding perspective to our scene.
     248      *  glLoadIdentity() restores the selected matrix to it's original state.
     249      *  The modelview matrix is where our object information is stored.
     250      *   Lastly we reset the modelview matrix.
     251      */
     252 
     253     glMatrixMode(GL_PROJECTION);                      // Select the projection matrix
     254     glLoadIdentity();                                 // Reset the projection matrix
     255     
     256                                                       // Calculate the aspect ratio of the window
     257     //gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
     258     glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f);  // Create orhto 640X480 view (0, 0, at the top)
     259 
     260     glMatrixMode(GL_MODELVIEW);                       // Seclet the modelview matrix
     261     glLoadIdentity();                                 // Reset the modelview matrix
     262 }
     263 
     264 int InitGL(GLvoid)                                    // All setup for OpenGL goes here
     265 {
     266     /*
     267      *  Smooth shading blends colors nicely across a polygon, and smoothes out lighting.
     268      */
     269 
     270     if (!LoadGLTextures()) {
     271         return FALSE;
     272     }
     273     BuildFont();
     274 
     275     glShadeModel(GL_SMOOTH);                          // Enables smooth shading
     276     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);             // Black background
     277 
     278     glClearDepth(1.0f);                               // Depth buffer setup
     279 
     280     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);           // Set line antialiasing
     281     glEnable(GL_BLEND);
     282     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     283 
     284     return TRUE;
     285 }
     286 
     287 /*
     288  *  For now all we will do is clear the screen to the color we previously decided on,
     289  *  clear the depth buffer and reset the scene. We wont draw anything yet.
     290  */
     291 int DrawGLScene(GLvoid)                                  // Here's where we do all the drawing
     292 {
     293     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // Clear the screen and the depth buffer
     294     glBindTexture(GL_TEXTURE_2D, texture[0]);
     295 
     296     glColor3f(1.0f, 0.5f, 1.0f);                         // Set color to purple
     297     glPrint(207, 24, 0, "GRID CRAZY");
     298     glColor3f(1.0f, 1.0f, 0.0f);
     299     glPrint(20, 20, 1, "Level:%2i", level2);             // Write actual level stats
     300     glPrint(20, 40, 1, "Stage:2%i", stage);              // Write stage stats
     301 
     302     if (gameover) {
     303         glColor3ub(rand() % 255, rand() % 255, rand() % 255);    // Pick A random color
     304         glPrint(456, 20, 1, "GAME  OVER");
     305         glPrint(456, 35, 1, "PRESS SPACE");
     306     }
     307 
     308     for (loop1 = 0; loop1 < lives - 1; ++loop1) {                 // Draw liver counter
     309         glLoadIdentity();
     310         glTranslatef(490 + (loop1 * 40.0f), 40.0f, 0.0f);         // Move to the right of our title text
     311         glRotatef(-player.spin, 0.0f, 0.0f, 1.0f);                // Rotate counter clockwise
     312         glColor3f(0.0f, 1.0f, 0.0f);                              // Light green
     313         glBegin(GL_LINES);                                        // Start drawing our player using lines
     314             glVertex2d(-5, -5);
     315             glVertex2d(5, 5);
     316             glVertex2d(5, -5);
     317             glVertex2d(-5, 5);
     318         glEnd();
     319 
     320         glRotatef(-player.spin * 0.5f, 0.0f, 0.0f, 1.0f);
     321         glColor3f(0.0f, 0.75f, 0.0f);                             // Dark green
     322         glBegin(GL_LINES);                                        // Start drawing our player using lines
     323             glVertex2d(-7, 0);
     324             glVertex2d(7, 0);
     325             glVertex2d(0, -7);
     326             glVertex2d(0, 7);
     327         glEnd();
     328     }
     329 
     330     filled = TRUE;                                       // Set filled to true before testing
     331     glLineWidth(1.0f);                                   // Set line width for celld to 2.0f
     332     glDisable(GL_LINE_SMOOTH);                           // Disable antialiasing
     333     glLoadIdentity();
     334     for (loop1 = 0; loop1 < 11; ++loop1) {               // Left to right
     335         for (loop2 = 0; loop2 < 11; ++loop2) {           // Top to bottom
     336             glColor3f(0.0f, 0.5f, 1.0f);
     337             if (hline[loop1][loop2]) {                   // Has the horizontal line been traced
     338                 glColor3f(1.0f, 1.0f, 1.0f);
     339             }
     340             if (loop1 < 10) {                            // Don't draw to far right
     341                 if (!hline[loop1][loop2]) {              // If a horizontal line isn't filled
     342                     filled = FALSE;
     343                 }
     344                 glBegin(GL_LINES);                       // Start drwaing horizontal cell borders
     345                     glVertex2d(20 + (loop1 * 60), 70 + (loop2 * 40));
     346                     glVertex2d(80 + (loop1 * 60), 70 + (loop2 * 40));
     347                 glEnd();
     348             }
     349             glColor3f(0.0f, 0.5f, 1.0f);
     350             if (vline[loop1][loop2]) {                   // Has the horizontal line been trace
     351                 glColor3f(1.0f, 1.0f, 1.0f);
     352             }
     353             if (loop2 < 10) {
     354                 if (!vline[loop1][loop2]) {              // If a verticle line isn't filled
     355                     filled = FALSE;
     356                 }
     357                 glBegin(GL_LINES);                       // Start drwaing verticle cell borders
     358                     glVertex2d(20 + (loop1 * 60), 70 + (loop2 * 40));
     359                     glVertex2d(20 + (loop1 * 60), 110 + (loop2 * 40));
     360                 glEnd();
     361             }
     362             glEnable(GL_TEXTURE_2D);
     363             glColor3f(1.0f, 1.0f, 1.0f);
     364             glBindTexture(GL_TEXTURE_2D, texture[1]);
     365             if ((loop1 < 10) && (loop2 < 10)) {           // If in bounds, fill in traced boxes
     366                 if (hline[loop1][loop2] && hline[loop1][loop2 + 1] && 
     367                     vline[loop1][loop2] && vline[loop1 + 1][loop2])
     368                 {
     369                     glBegin(GL_QUADS);
     370                         glTexCoord2f(float(loop1 / 10.0f) + 0.1f, 1.0f - (float(loop2 / 10.0f)));
     371                         glVertex2d(20 + (loop1 * 60) + 59, (70 + loop2 * 40 + 1));   // Top right
     372                         glTexCoord2f(float(loop1 / 10.0f), 1.0f - (float(loop2 / 10.0f)));
     373                         glVertex2d(20 + (loop1 * 60) + 1, (70 + loop2 * 40 + 1));   // Top left
     374                         glTexCoord2f(float(loop1 / 10.0f), 1.0f - (float(loop2 / 10.0f) + 0.1f));
     375                         glVertex2d(20 + (loop1 * 60) + 1, (70 + loop2 * 40 + 39));   // Botttom left
     376                         glTexCoord2f(float(loop1 / 10.0f) + 0.1f, 1.0f - (float(loop2 / 10.0f) + 0.1f));
     377                         glVertex2d(20 + (loop1 * 60) + 59, (70 + loop2 * 40 + 39));   // Bottom right
     378                     glEnd();
     379                 }
     380             }
     381             glDisable(GL_TEXTURE_2D);
     382         }    
     383     }
     384     glLineWidth(1.0f);
     385 
     386     if (anti) {
     387         glEnable(GL_LINE_SMOOTH);                         // Enable antialiasing
     388     }
     389 
     390     if (hourglass.fx == 1) {
     391         glLoadIdentity();
     392         glTranslatef(20.0f + (hourglass.x * 60), 70.0f + (hourglass.y * 40), 0.0f);
     393         glRotatef(hourglass.spin, 0.0f, 0.0f, 1.0f);
     394         glColor3ub(rand() % 255, rand() % 255, rand() % 255);
     395         glBegin(GL_LINES);                                 // Hourglass
     396             glVertex2d(-5, -5);
     397             glVertex2d(5, 5);
     398             glVertex2d(5, -5);
     399             glVertex2d(-5, 5);
     400             glVertex2d(-5, 5);
     401             glVertex2d(5, 5);
     402             glVertex2d(-5, -5);
     403             glVertex2d(5, -5);
     404         glEnd();
     405     }
     406 
     407     glLoadIdentity();
     408     glTranslatef(player.fx + 20.0f, player.fy + 70.0f, 0.0f);     // Player
     409     glRotatef(player.spin, 0.0f, 0.0f, 1.0f);
     410     glColor3f(0.0f, 1.0f, 0.0f);
     411     glBegin(GL_LINES);                           // Player using lines
     412         glVertex2d(-5, -5);
     413         glVertex2d(5, 5);
     414         glVertex2d(5, -5);
     415         glVertex2d(-5, 5);
     416     glEnd();
     417 
     418     glRotatef(player.spin * 0.5f, 0.0f, 0.0f, 1.0f);
     419     glColor3f(0.0f, 0.75f, 0.0f);
     420     glBegin(GL_LINES);                           // Player using lines
     421         glVertex2d(-7, 0);
     422         glVertex2d(7, 0);
     423         glVertex2d(0, -7);
     424         glVertex2d(0, 7);
     425     glEnd();
     426 
     427     for (loop1 = 0; loop1 < (stage * level); ++loop1) {             // Enemies
     428         glLoadIdentity();
     429         glTranslatef(enemy[loop1].fx + 20.0f, enemy[loop1].fy + 70.0f, 0.0f);
     430         glColor3f(1.0f, 0.5f, 0.5f);                     // Pink
     431         glBegin(GL_LINES);
     432             glVertex2d(0, -7);
     433             glVertex2d(-7, 0);
     434             glVertex2d(-7, 0);
     435             glVertex2d(0, 7);
     436             glVertex2d(0, 7);
     437             glVertex2d(7, 0);
     438             glVertex2d(7, 0);
     439             glVertex2d(0, -7);
     440         glEnd();
     441 
     442         glRotatef(enemy[loop1].spin, 0.0f, 0.0f, 1.0f);
     443         glColor3f(1.0f, 0.0f, 0.0f);
     444         glBegin(GL_LINES);
     445             glVertex2d(-7, -7);
     446             glVertex2d(7, 7);
     447             glVertex2d(-7, 7);
     448             glVertex2d(7, -7);
     449         glEnd();
     450     }
     451     return TRUE;                                         // everthing went OK
     452 }
     453 /******************************************************************************************************************************************/
     454 /******************************************************************************************************************************************/
     455 /*
     456  *  The job of KillGLWindow() is to release the Rendering Context, 
     457  *  the Device Context and finally the Window Handle. 
     458  */
     459 
     460 GLvoid KillGLWindow(GLvoid)                              // Properly kill the window
     461 {
     462     if (fullscreen) {                                    // Are we in fullscreen mode
     463         
     464         /*
     465          *  We use ChangeDisplaySettings(NULL,0) to return us to our original desktop.
     466          *  After we've switched back to the desktop we make the cursor visible again.
     467          */
     468 
     469         ChangeDisplaySettings(NULL, 0);                  // if so switch back to the desktop
     470         ShowCursor(TRUE);                                // Show mouse pointer
     471     }
     472 
     473     if (hRC) {                                           // Do we have a rendering context
     474         if (!wglMakeCurrent(NULL, NULL)) {                // Are we able to release the DC and RC contexts
     475             MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
     476         }
     477 
     478         if (!wglDeleteContext(hRC)) {                     // Are we able to delete the RC
     479             MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
     480             hRC = NULL;                                  // Set RC to NULL
     481         }
     482 
     483         if (hDC && !ReleaseDC(hWnd, hDC)) {              // Are we able to release the DC
     484             MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
     485             hDC = NULL;                                  // Set DC to NULL
     486         }
     487         if (hWnd && !DestroyWindow(hWnd)) {              // Are we able to destroy the window
     488             MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
     489             hWnd = NULL;                                 // Set hWnd to NULL
     490         }
     491 
     492         if (!UnregisterClass("OpenGL", hInstance)) {     // Are we able to unregister class
     493             MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
     494             hInstance = NULL;                            // Set hInstance to NULL
     495         }
     496     }
     497 /******************************************************************************************************************************************/
     498 /******************************************************************************************************************************************/
     499     KillFont();
     500 /******************************************************************************************************************************************/
     501 /******************************************************************************************************************************************/
     502 }
     503 
     504 /*
     505  * The next section of code creates our OpenGL Window.
     506  */
     507 
     508 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
     509 {
     510     /*
     511      * Find  a pixel format that matches the one we want
     512      */
     513     GLuint PixelFormat;                                  // Holds the result after serching for a match
     514     
     515     /*
     516      * Before you create a window, you MUST register a Class for the window
     517      */
     518     WNDCLASS wc;                                         // Windows class structure
     519 
     520     /*
     521      *  dwExStyle and dwStyle will store the Extended and normal Window Style Information.
     522     */
     523     DWORD dwExStyle;                                     // Window extend style
     524     DWORD dwStyle;                                       // Window style
     525 
     526     RECT WindowRect;                                     // Grabs rectangle upper left/lower right values
     527     WindowRect.left = (long)0;                           // Set left value to 0
     528     WindowRect.right = (long)width;                      // Set right value to requested width
     529     WindowRect.top = (long)0;                            // Set top value to 0
     530     WindowRect.bottom = (long)height;                    // Set bottom value to requested height
     531 
     532     fullscreen = fullscreenflag;                         // Set the global fullscreen flag
     533 
     534     /*
     535      *  The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. 
     536      *  CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. 
     537      *  WndProc is the procedure that watches for messages in our program. 
     538      *  No extra Window data is used so we zero the two fields. Then we set the instance. 
     539      *  Next we set hIcon to NULL meaning we don't want an ICON in the Window, 
     540      *  and for a mouse pointer we use the standard arrow. The background color doesn't matter 
     541      *  (we set that in GL). We don't want a menu in this Window so we set it to NULL, 
     542      *  and the class name can be any name you want. I'll use "OpenGL" for simplicity.
     543      */
     544     hInstance = GetModuleHandle(NULL);                   // Grab an instance for our window
     545     wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;       // Redraw on move, and own DC for window
     546     wc.lpfnWndProc = (WNDPROC)WndProc;                   // WndProc handles message
     547     wc.cbClsExtra = 0;                                   // No extra window date
     548     wc.cbWndExtra = 0;                                   // No extra window date
     549     wc.hInstance = hInstance;                            // set the instance
     550     wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);              // Load the default icon
     551     wc.hCursor = LoadCursor(NULL, IDC_ARROW);            // Load the arrow pointer
     552     wc.hbrBackground = NULL;                             // No background requried for GL
     553     wc.lpszMenuName = NULL;                              // We don't want a menu
     554     wc.lpszClassName = "OpenGL";                         // set the class name
     555 
     556     if (!RegisterClass(&wc)) {                           // Attempt to register the window class
     557         MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
     558         return FALSE;                                    // Exit and return false
     559     }
     560 
     561     if (fullscreen) {                                    // attempt fullsreen model
     562         
     563         /*
     564         T*  here are a few very important things you should keep in mind when switching to full screen mode.
     565          *  Make sure the width and height that you use in fullscreen mode is the same as 
     566          *  the width and height you plan to use for your window, and most importantly,
     567          *  set fullscreen mode BEFORE you create your window.
     568          */
     569         DEVMODE dmScreenSettings;                        // Device mode
     570         memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory's cleared
     571         dmScreenSettings.dmSize = sizeof(dmScreenSettings);     // Size of devmode structure
     572         dmScreenSettings.dmPelsWidth = width;            // Select window width
     573         dmScreenSettings.dmPelsHeight = height;          // Select window height
     574         dmScreenSettings.dmBitsPerPel = bits;            // Select bits per pixel
     575         dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
     576         
     577         /*
     578          *  In the line below ChangeDisplaySettings tries to switch to a mode that matches 
     579          *  what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes, 
     580          *  because it's supposed to remove the start bar at the bottom of the screen, 
     581          *  plus it doesn't move or resize the windows on your desktop when you switch to 
     582          *  fullscreen mode and back.
     583          */
     584         //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar
     585         if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
     586             //If the mode fails, offer two options. Quit or run in a window
     587             if (MessageBox(NULL, "The requested fullscreen mode is not supported by
     your video card. Use"
     588                 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
     589             {
     590                 fullscreen = FALSE;                       // Select windowed mode (fullscreen=FLASE)
     591             }
     592             else {
     593                 // Pop up a message box letting user know the programe is closing.
     594                 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP);
     595                 return FALSE;                             // Exit and return FALSE
     596             }
     597         }
     598     }
     599 
     600     if (fullscreen) {                                     // Are we still in fullscreen mode
     601         
     602         /*
     603          *  If we are still in fullscreen mode we'll set the extended style to WS_EX_APPWINDOW, 
     604          *  which force a top level window down to the taskbar once our window is visible. 
     605          *  For the window style we'll create a WS_POPUP window. 
     606          *  This type of window has no border around it, making it perfect for fullscreen mode.
     607 
     608          *  Finally, we disable the mouse pointer. If your program is not interactive, 
     609          *  it's usually nice to disable the mouse pointer when in fullscreen mode. It's up to you though.
     610          */
     611         dwExStyle = WS_EX_APPWINDOW;                      // Window extended style
     612         dwStyle = WS_POPUP;                               // Window style
     613         ShowCursor(FALSE);                                // Hide mosue pointer 
     614     }
     615     else {
     616 
     617         /*
     618          *  If we're using a window instead of fullscreen mode, 
     619          *  we'll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look. 
     620          *  For style we'll use WS_OVERLAPPEDWINDOW instead of WS_POPUP. 
     621          *  WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border, 
     622          *  window menu, and minimize / maximize buttons.
     623          */
     624         dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   // Window extended style
     625         dwStyle = WS_OVERLAPPEDWINDOW;                    // Window style
     626     }
     627 
     628     /*
     629      *  By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders, 
     630      *  instead, the window will be made larger to account for the pixels needed to draw the window border. 
     631      *  In fullscreen mode, this command has no effect.
     632      */
     633     AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);  // Adjust window to true resqusted
     634     
     635     /*
     636      *  WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly. 
     637      *  These styles prevent other windows from drawing over or into our OpenGL Window.
     638      */
     639     if (!(hWnd = CreateWindowEx(dwExStyle,                // Extended style for the window
     640         "OpenGL",                                         // Class name
     641         title,                                            // Window title
     642         WS_CLIPSIBLINGS |                                 // Requried window style
     643         WS_CLIPCHILDREN |                                 // Requried window style
     644         dwStyle,                                          // Select window style
     645         0, 0,                                             // Window position
     646         WindowRect.right - WindowRect.left,               // Calculate adjusted window width
     647         WindowRect.bottom - WindowRect.top,               // Calculate adjusted window height
     648         NULL,                                             // No parent window
     649         NULL,                                             // No menu
     650         hInstance,                                        // Instance
     651         NULL)))                                           // Don't pass anything to WM_CREATE
     652     {
     653         KillGLWindow();                                   //Reset the display
     654         MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
     655         return FALSE;                                     // Retrurn FALSE;
     656     }
     657 
     658     /*
     659      *  aside from the stencil buffer and the (slow) accumulation buffer
     660      */
     661     static PIXELFORMATDESCRIPTOR pfd =                    // pfd tells windows how we want things to be 
     662     {
     663         sizeof(PIXELFORMATDESCRIPTOR),                    // Size of this pixel format descriptor
     664         1,                                                // Version number
     665         PFD_DRAW_TO_WINDOW |                              // Format must support window
     666         PFD_SUPPORT_OPENGL |                              // Format must support OpenGL
     667         PFD_DOUBLEBUFFER,                                 // Must support double buffer
     668         PFD_TYPE_RGBA,                                    // Request an RGBA format
     669         bits,                                             // Select our color depth
     670         0, 0, 0, 0, 0, 0,                                 // Color bits ignored
     671         0,                                                // No alpha buffer
     672         0,                                                // shift bit ignored
     673         0,                                                // No accumulation buffer
     674         0, 0, 0, 0,                                       // Accumulation bits ignored
     675         16,                                               // 16Bits Z_Buffer (depth buffer)
     676         0,                                                // No stencil buffer
     677         0,                                                // No auxiliary buffer
     678         PFD_MAIN_PLANE,                                   // Main drawing layer
     679         0,                                                // Reserved
     680         0, 0, 0                                           // Layer makes ignored
     681     };
     682 
     683     if (!(hDC = GetDC(hWnd))) {                           // Did we get a device context
     684         KillGLWindow();                                   // Reset the display
     685         MessageBox(NULL, "Can't create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
     686         return FALSE;                                     // Return FALSE
     687     }
     688 
     689     if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) {  // Did window find a matching pixel format
     690         KillGLWindow();                                   // Reset the display
     691         MessageBox(NULL, "Can't find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
     692         return FALSE;                                     // Return FALSE;
     693     }
     694 
     695     if (!SetPixelFormat(hDC, PixelFormat, &pfd)) {        // Are we able to set the pixel format
     696         KillGLWindow();                                   // Reset the display
     697         MessageBox(NULL, "Can't set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
     698         return FALSE;                                     // Return FALSE;
     699     }
     700 
     701     if (!(hRC = wglCreateContext(hDC))) {                 // Are we able to rendering context
     702         KillGLWindow();                                   // Reset the display
     703         MessageBox(NULL, "Can't create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
     704         return FALSE;                                     // Return FASLE;
     705     }
     706 
     707     if (!wglMakeCurrent(hDC, hRC)) {                      // Try to activate the rendering context
     708         KillGLWindow();                                   // Reset the display
     709         MessageBox(NULL, "Can't activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
     710         return FALSE;                                     // Return FALSE    
     711     }
     712 
     713     /*
     714      *  ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen.
     715      */
     716     ShowWindow(hWnd, SW_SHOW);                            // Show the window
     717     SetForegroundWindow(hWnd);                            // slightly higher priority
     718     SetFocus(hWnd);                                       // Sets keyboard focus to the window
     719     ReSizeGLScene(width, height);                         // Set up our perspective GL screen
     720 
     721 /*
     722  *  we can set up lighting, textures, and anything else that needs to be setup in InitGL().
     723  */
     724 if (!InitGL()) {                                      // Initialize our newly created GL window
     725     KillGLWindow();                                   // Reset the display
     726     MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
     727     return FALSE;                                     // Return FALSE
     728 }
     729 return TRUE;
     730 }
     731 
     732 LRESULT CALLBACK WndProc(HWND hWnd,                       // Handle for this window
     733     UINT uMsg,                                            // Message for this window
     734     WPARAM wParam,                                        // Additional message information
     735     LPARAM lParam)                                        // Additional message information
     736 {
     737     switch (uMsg) {                                       // Check for window message
     738     case WM_ACTIVATE: {                               // Check minimization state
     739         if (!HIWORD(wParam)) {
     740             active = TRUE;                            // Program is active
     741         }
     742         else {
     743             active = FALSE;                           // Program is no longer active
     744         }
     745         return 0;                                     // Return to the message loop
     746     }
     747     case WM_SYSCOMMAND: {                             // Intercept system commands
     748         switch (wParam) {                             // Check system calls
     749         case SC_SCREENSAVE:                       // Screensaver trying to start
     750         case SC_MONITORPOWER:                     // Monitor trying to enter powersave
     751             return 0;                                 // Prevent form happening
     752         }
     753         break;                                        // Exit
     754     }
     755     case WM_CLOSE: {                                  // Did we receive a close message
     756         PostQuitMessage(0);                           // Send a quit message
     757         return 0;
     758     }
     759     case WM_KEYDOWN: {                                // Is a key being held down
     760         keys[wParam] = TRUE;                          // if so, mark it as TRUE
     761         return 0;                                     // Jump back
     762     }
     763     case WM_KEYUP: {                                  // Has a key been released
     764         keys[wParam] = FALSE;                         // if so, mark it as FALSE
     765         return 0;                                     // Jump back
     766     }
     767     case WM_SIZE: {                                   // Resize the OpenGL window
     768         ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));   // LoWord = width HiWord = height
     769         return 0;                                     // Jump back
     770     }
     771     }
     772     return DefWindowProc(hWnd, uMsg, wParam, lParam);     // Pass all unhandled message to DefWindwProc
     773 }
     774 
     775 int WINAPI WinMain(HINSTANCE hInstance,                   // Instance
     776     HINSTANCE hPrevInstance,                              // Previous instance
     777     LPSTR lpCmdLine,                                      // Command line parameters
     778     int nCmdShow)                                         // Window show state
     779 {
     780     MSG msg;                                              // Window message structure
     781     BOOL done = FALSE;                                    // Bool variable to exit loop
     782                                                           // Ask the user which screen mode they prefer
     783     if (MessageBox(NULL, "Would you like to run in fullscreen mode?",
     784         "Start fullscreen?", MB_YESNO | MB_ICONQUESTION) == IDNO)
     785     {
     786         fullscreen = FALSE;                               // Window mode
     787     }
     788     // Create our OpenGL window
     789     if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) {  // (Modified)
     790         return 0;                                         // Quit if window was not create
     791     }
     792     /******************************************************************************************************************************************/
     793     /******************************************************************************************************************************************/
     794     ResetObjects();                                       // Set player / enemy starting position
     795     TimerInit();                                          // Initialize the timer
     796 
     797     while (!done) {                                       // Loop that runs until donw = TRUE
     798         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {   // Is there a message wating
     799             if (msg.message == WM_QUIT) {                 // Havw we received a quit message
     800                 done = TRUE;                              // if so done  = TRUE
     801             }
     802             else {                                        // If not, deal with window message
     803                 TranslateMessage(&msg);                   // Translate message
     804                 DispatchMessage(&msg);                    // Dispatch message
     805             }
     806         }
     807         else {
     808 
     809             float start = TimerGetTime();                 // Grab timer value before we draw
     810 
     811             // Draw the scene. Watch for ESC key and quit message from DrawGLScene()
     812             if (active) {                                 // Program active
     813                 if (keys[VK_ESCAPE]) {                    // Was ESC pressed
     814                     done = TRUE;                          // ESC signalled a quit
     815                 }
     816                 else {                                    // Not time to quit, update screen
     817                     DrawGLScene();                        // Draw scene
     818                     SwapBuffers(hDC);                     // Swap buffers (double buffering)
     819                 }
     820             }
     821             // Waste Cycles On Fast Systems
     822             while (TimerGetTime() < start + float(steps[adjust] * 2.0f)) {}
     823 
     824             if (keys['A'] && !ap) {
     825                 ap = TRUE;
     826                 anti = !anti;
     827             }
     828             if (!keys['A']) {
     829                 ap = FALSE;
     830             }
     831             if (!gameover && active) {                    // If game isn't over and active move objects
     832                 for (loop1 = 0; loop1 < (stage * level); ++loop1) {
     833                     if ((enemy[loop1].x < player.x) && (enemy[loop1].fy == enemy[loop1].y * 40)) {
     834                         enemy[loop1].x++;                 // Move the enemy right
     835                     }
     836                     if ((enemy[loop1].x > player.x) && (enemy[loop1].fy == enemy[loop1].y * 40)) {
     837                         enemy[loop1].x--;                 // Move the enemy left
     838                     }
     839                     if ((enemy[loop1].y < player.y) && (enemy[loop1].fx == enemy[loop1].x * 60)) {
     840                         enemy[loop1].y++;                 // Move the enemy down
     841                     }
     842                     if ((enemy[loop1].y > player.y) && (enemy[loop1].fx == enemy[loop1].x * 60)) {
     843                         enemy[loop1].y--;                 // Move the enemy up
     844                     }
     845 
     846                     if (delay > (3 - level) && (hourglass.fx != 2)) {
     847                         delay = 0;
     848                         for (loop2 = 0; loop2 < (stage * level); ++loop2) {
     849                             if (enemy[loop2].fx < enemy[loop2].x * 60) {
     850                                 enemy[loop2].fx += steps[adjust];
     851                                 enemy[loop2].spin += steps[adjust];
     852                             }
     853                             if (enemy[loop2].fx > enemy[loop2].x * 60) {
     854                                 enemy[loop2].fx -= steps[adjust];
     855                                 enemy[loop2].spin -= steps[adjust];
     856                             }
     857                             if (enemy[loop2].fy < enemy[loop2].y * 40) {
     858                                 enemy[loop2].fy += steps[adjust];
     859                                 enemy[loop2].spin += steps[adjust];
     860                             }
     861                             if (enemy[loop2].fy > enemy[loop2].y * 40) {
     862                                 enemy[loop2].fy -= steps[adjust];
     863                                 enemy[loop2].spin -= steps[adjust];
     864                             }
     865                         }
     866                     }
     867 
     868                     if ((enemy[loop1].fx == player.fx) && (enemy[loop1].fy == player.fy)) {
     869                         lives--;
     870                         if (lives == 0) {
     871                             gameover = TRUE;
     872                         }
     873                         ResetObjects();
     874                         PlaySound("Die.wav", NULL, SND_SYNC);
     875                     }
     876                 }
     877 
     878                 if (keys[VK_RIGHT] && (player.x < 10) && (player.fx == player.x * 60) &&
     879                     (player.fy == player.y * 40))
     880                 {
     881                     // Make current horizontal border as filled
     882                     hline[player.x][player.y] = TRUE;
     883                     player.x++;                                 // Move the player right
     884                 }
     885                 if (keys[VK_LEFT] && (player.x > 0) && (player.fx == player.x * 60) &&
     886                     (player.fy == player.y * 40))
     887                 {
     888                     player.x--;
     889                     hline[player.x][player.y] = TRUE;
     890                 }
     891                 if (keys[VK_DOWN] && (player.y < 10) && (player.fx == player.x * 60) &&
     892                     (player.fy == player.y * 40))
     893                 {
     894                     vline[player.x][player.y] = TRUE;
     895                     player.y++;
     896                 }
     897                 if (keys[VK_UP] && (player.y > 0) && (player.fx == player.x * 60) &&
     898                     (player.fy == player.y * 40))
     899                 {
     900                     player.y--;
     901                     vline[player.x][player.y] = TRUE;
     902                 }
     903 
     904                 if (player.fx < player.x * 60) {
     905                     player.fx += steps[adjust];
     906                 }
     907                 if (player.fx > player.x * 60) {
     908                     player.fx -= steps[adjust];
     909                 }
     910                 if (player.fy < player.y * 40) {
     911                     player.fy += steps[adjust];
     912                 }
     913                 if (player.fy > player.y * 40) {
     914                     player.fy -= steps[adjust];
     915                 }
     916             }
     917             else {
     918                 if (keys[' ']) {
     919                     gameover = FALSE;
     920                     filled = TRUE;
     921                     level = 1;
     922                     level2 = 1;
     923                     stage = 0;
     924                     lives = 5;
     925                 }
     926             }
     927 
     928             if (filled) {
     929                 PlaySound("Complete.wav", NULL, SND_SYNC);
     930                 stage++;
     931                 if (stage > 3) {
     932                     stage = 1;
     933                     level++;
     934                     level2++;
     935                     if (level > 3) {
     936                         level = 3;
     937                         lives++;
     938                         if (lives > 5) {
     939                             lives = 5;
     940                         }
     941                     }
     942                 }
     943                 ResetObjects();
     944                 for (loop1 = 0; loop1 < 11; ++loop1) {
     945                     for (loop2 = 0; loop2 < 11; ++loop2) {
     946                         if (loop1 < 10) {
     947                             hline[loop1][loop2] = FALSE;
     948                         }
     949                         if (loop2 < 10) {
     950                             vline[loop1][loop2] = FALSE;
     951                         }
     952                     }
     953                 }
     954             }
     955 
     956             if ((player.fx == hourglass.x * 60) && (player.fy == hourglass.y * 40) &&
     957                 (hourglass.fx == 1))
     958             {
     959                 PlaySound("freeze.wav", NULL, SND_ASYNC | SND_LOOP);
     960                 hourglass.fx = 2;
     961                 hourglass.fy = 0;
     962             }
     963 
     964             player.spin += 0.5f * steps[adjust];
     965             if (player.spin > 360.0f) {
     966                 player.spin -= 360.0f;
     967             }
     968             hourglass.spin -= 0.25f * steps[adjust];
     969             if (hourglass.spin < 0.0f) {
     970                 hourglass.spin += 360.0f;
     971             }
     972             hourglass.fy += steps[adjust];
     973             if ((hourglass.fx == 0) && (hourglass.fy > 6000 / level)) {
     974                 PlaySound("hourglass.wav", NULL, SND_ASYNC);
     975                 hourglass.x = rand() % 10 + 1;
     976                 hourglass.y = rand() % 11;
     977                 hourglass.fx = 1;
     978                 hourglass.fy = 0;
     979             }
     980             if ((hourglass.fx == 1) && (hourglass.fy > 6000 / level)) {
     981                 hourglass.fx = 0;
     982                 hourglass.fy = 0;
     983             }
     984             if ((hourglass.fx == 2) && (hourglass.fy > 500 + (500 * level))) {
     985                 PlaySound(NULL, NULL, 0);
     986                 hourglass.fx = 0;
     987                 hourglass.fy = 0;
     988             }
     989             delay++;
     990             /*
     991             *  It allows us to press the F1 key to switch from fullscreen mode to
     992             *  windowed mode or windowed mode to fullscreen mode.
     993             */
     994             if (keys[VK_F1]) {                            // Is F1 being pressed
     995                 keys[VK_F1] = FALSE;                      // If so make key FASLE
     996                 KillGLWindow();                           // Kill our current window
     997                 fullscreen = !fullscreen;                 // Toggle fullscreen / window mode
     998                 //Recreate our OpenGL window(modified)
     999                 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) {
    1000                     return 0;                             // Quit if window was not create
    1001                 }
    1002             }
    1003         }
    1004     }
    1005     // Shutdown
    1006     KillGLWindow();                                       // Kill the window
    1007     return (msg.wParam);                                  // Exit the program
    1008 }
    1009 /******************************************************************************************************************************************/
    1010 /******************************************************************************************************************************************/

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

  • 相关阅读:
    linux---集群架构初探(14)静态、动态、流量术语
    linux---集群架构初探(13)http与www服务基础介绍
    linux---集群架构初探(12)ansible剧本模式(playbook)
    linux---集群架构初探(11) 实践:一键部署nfs
    linux---集群架构初探(10)Ansible常用模块
    试题一 讲解
    aws 试题
    linux 常用命令。
    nohub命令简单介绍。
    Linux 系统conda环境,pip文件的导出和安装。
  • 原文地址:https://www.cnblogs.com/clairvoyant/p/5690011.html
Copyright © 2011-2022 走看看