FireWorks based on NeHe Particle System
2015-12-29 20:20
471 查看
<img src="http://img.blog.csdn.net/20151229202249365?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
/* # Firework based on Nehe # Author : caicai # Date : 2015-12-12 # HomePage : http://blog.csdn.net/caicai_zju # Email : wdong1993@hotmail.com */ #include <stdlib.h> #include <windows.h> // Header File For Windows #include <stdio.h> // Header File For Standard Input/Output #define GLUT_DISABLE_ATEXIT_HACK #include <gl\gl.h> // Header File For The OpenGL32 Library #include <gl/glext.h> #include <gl\glu.h> // Header File For The GLu32 Library #include <gl\glaux.h> // Header File For The Glaux Library #define MAX_PARTICLES 500 // Number Of Particles To Create #define MAX_FIREWORKS 5 HDC hDC=NULL; // Private GDI Device Context HGLRC hRC=NULL; // Permanent Rendering Context HWND hWnd=NULL; // Holds Our Window Handle HINSTANCE hInstance; // Holds The Instance Of The Application bool keys[256]; // Array Used For The Keyboard Routine bool active=TRUE; // Window Active Flag Set To TRUE By Default bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default bool rainbow=true; // Rainbow Mode? bool sp; // Spacebar Pressed? bool rp; // Enter Key Pressed? float slowdown=2.0f; // Slow Down Particles float xspeed; // Base X Speed (To Allow Keyboard Direction Of Tail) float yspeed=0.0f; // Base Y Speed (To Allow Keyboard Direction Of Tail) float zoom=-40.0f; // Used To Zoom Out GLuint loop; // Misc Loop Variable GLuint loop2; // Misc Loop Variable GLuint col; // Current Color Selection GLuint delay; // Rainbow Effect Delay GLuint texture[2]; // Storage For Our Particle Texture typedef struct // Create A Structure For Particle { bool active; // Active (Yes/No) float life; // Particle Life float fade; // Fade Speed float r; // Red Value float g; // Green Value float b; // Blue Value float x; // X Position float y; // Y Position float z; // Z Position float xi; // X Direction float yi; // Y Direction float zi; // Z Direction float xg; // X Gravity float yg; // Y Gravity float zg; // Z Gravity } particles; // Particles Structure typedef struct { int burst; float life; // Particle Life float fade; // Fade Speed float x; // X Position float y; // Y Position float z; // Z Position float xi; // X Direction float yi; // Y Direction float zi; // Z Direction float xg; // X Gravity float yg; // Y Gravity float zg; // Z Gravity particles particle[MAX_PARTICLES]; // Particle Array (Room For Particle Info) } emitter; emitter e[MAX_FIREWORKS]; static GLfloat colors[12][3]= // Rainbow Of Colors { {1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f}, {0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f}, {0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f} }; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc int LoadGLTextures(LPTSTR szFileName, GLuint &texid) // Creates Texture From A Bitmap File { HBITMAP hBMP; // Handle Of The Bitmap BITMAP BMP; // Bitmap Structure glGenTextures(1, &texid); // Create The Texture hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE ); if (!hBMP) // Does The Bitmap Exist? return false; // If Not Return False GetObject(hBMP, sizeof(BMP), &BMP); // Get The Object // hBMP: Handle To Graphics Object // sizeof(BMP): Size Of Buffer For Object Information // &BMP: Buffer For Object Information glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Pixel Storage Mode (Word Alignment / 4 Bytes) // Typical Texture Generation Using Data From The Bitmap glBindTexture(GL_TEXTURE_2D, texid); // Bind To The Texture ID glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Min Filter glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Mag Filter glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP.bmWidth, BMP.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits); DeleteObject(hBMP); // Delete The Object return 1; // Loading Was Successful } int LoadGLTextures() // Load Bitmap And Convert To A Texture { LoadGLTextures("Data/Particle.bmp",texture[0]); LoadGLTextures("Data/background.bmp",texture[1]); return 1; } GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window { if (height==0) // Prevent A Divide By Zero By { height=1; // Making Height Equal One } glViewport(0,0,width,height); // Reset The Current Viewport glMatrixMode(GL_PROJECTION); // Select The Projection Matrix glLoadIdentity(); // Reset The Projection Matrix // Calculate The Aspect Ratio Of The Window gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,20000.0f); glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix glLoadIdentity(); // Reset The Modelview Matrix } void init_emitter(int i) { e[i].life=10.0+float(rand()%30); e[i].burst=0; e[i].fade=float(rand()%100)/1000.0f+0.003f; e[i].x=float(rand()%100-50)/5.0f;; e[i].y=-15.0+float(rand()%10-5); e[i].z=float(rand()%100-50)/20.0f; e[i].xi=float((rand()%60)-32.0f)/2000; e[i].yi=0.07+float((rand()%2)-1)/1000; e[i].zi=float((rand()%60)-32.0f)/2000; e[i].xg=0.0f; e[i].yg=-0.0001f; e[i].zg=0.0f; for (loop=0;loop<MAX_PARTICLES;loop++) // Loop Through All The Particles { e[i].particle[loop].active=true; // Make All The Particles Active e[i].particle[loop].life=1.0f; // Give It New Life e[i].particle[loop].fade=float(rand()%100)/1000.0f+0.003f; // Random Fade Value e[i].particle[loop].x=e[i].x; // Center On X Axis e[i].particle[loop].y=e[i].y; // Center On Y Axis e[i].particle[loop].z=e[i].z; // Center On Z Axis e[i].particle[loop].xi=xspeed/10+float((rand()%60)-32.0f)/100; // X Axis Speed And Direction e[i].particle[loop].yi=yspeed+float((rand()%100)-200.0f); // Y Axis Speed And Direction e[i].particle[loop].zi=float((rand()%60)-30.0f)/100; // Z Axis Speed And Direction e[i].particle[loop].r=colors[col][0]; // Select Red From Color Table e[i].particle[loop].g=colors[col][1]; // Select Green From Color Table e[i].particle[loop].b=colors[col][2]; // Select Blue From Color Table e[i].particle[loop].xg=0.0f; // Set Horizontal Pull To Zero e[i].particle[loop].yg=-0.8f; // Set Vertical Pull Downward e[i].particle[loop].zg=0.0f; // Set Pull On Z Axis To Zero } } void burst_emitter(int i) { glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); e[i].burst=1; for (loop=0;loop<MAX_PARTICLES;loop++) { e[i].particle[loop].life=5.0f; // Give It New Life e[i].particle[loop].fade=float(rand()%100)/1000.0f+0.003f; // Random Fade Value e[i].particle[loop].x=e[i].x; // Center On X Axis e[i].particle[loop].y=e[i].y; // Center On Y Axis e[i].particle[loop].z=e[i].z; // Center On Z Axis e[i].particle[loop].xi=float((rand()%50)-26.0f)*10.0f; // Random Speed On X Axis e[i].particle[loop].yi=float((rand()%50)-25.0f)*10.0f; // Random Speed On Y Axis e[i].particle[loop].zi=float((rand()%50)-25.0f)*10.0f; // Random Speed On Z Axis } } void update_emitter(int i) { for (loop=0;loop<MAX_PARTICLES;loop++) { if(e[i].particle[loop].life>0.0f) { e[i].particle[loop].x+=e[i].particle[loop].xi/(slowdown*1000);// Move On The X Axis By X Speed e[i].particle[loop].y+=e[i].particle[loop].yi/(slowdown*1000);// Move On The Y Axis By Y Speed e[i].particle[loop].z+=e[i].particle[loop].zi/(slowdown*1000);// Move On The Z Axis By Z Speed e[i].particle[loop].xi+=e[i].particle[loop].xg; // Take Pull On X Axis Into Account e[i].particle[loop].yi+=e[i].particle[loop].yg; // Take Pull On Y Axis Into Account e[i].particle[loop].zi+=e[i].particle[loop].zg; // Take Pull On Z Axis Into Account e[i].particle[loop].life-=e[i].particle[loop].fade; // Reduce Particles Life By 'Fade' } if (e[i].yi>0&&e[i].particle[loop].life<0.0f) // If Particle Is Burned Out { e[i].particle[loop].life=0.5f; // Give It New Life e[i].particle[loop].fade=float(rand()%100)/1000.0f+0.003f; // Random Fade Value e[i].particle[loop].x=e[i].x; // Center On X Axis e[i].particle[loop].y=e[i].y; // Center On Y Axis e[i].particle[loop].z=e[i].z; // Center On Z Axis e[i].particle[loop].xi=xspeed+float((rand()%60)-32.0f); // X Axis Speed And Direction e[i].particle[loop].yi=yspeed+float((rand()%100)-200.0f); // Y Axis Speed And Direction e[i].particle[loop].zi=float((rand()%60)-30.0f); // Z Axis Speed And Direction e[i].particle[loop].r=colors[col][0]; // Select Red From Color Table e[i].particle[loop].g=colors[col][1]; // Select Green From Color Table e[i].particle[loop].b=colors[col][2]; // Select Blue From Color Table } } if(e[i].yi>0) { e[i].x+=e[i].xi; e[i].y+=e[i].yi; e[i].z+=e[i].zi; e[i].xi+=e[i].xg; e[i].yi+=e[i].yg; e[i].zi+=e[i].zg; } if(e[i].yi<0&&e[i].burst==0) burst_emitter(i); if(e[i].burst==1&&e[i].life>0.0f) { e[i].life-=e[i].fade; if(e[i].life<0.0f) init_emitter(i); } } int InitGL(GLvoid) // All Setup For OpenGL Goes Here { if (!LoadGLTextures()) // Jump To Texture Loading Routine { return FALSE; // If Texture Didn't Load Return FALSE } glShadeModel(GL_SMOOTH); // Enable Smooth Shading glClearColor(0.0f,0.0f,0.0f,0.0f); // Black Background glClearDepth(1.0f); // Depth Buffer Setup glDisable(GL_DEPTH_TEST); // Disable Depth Testing glEnable(GL_BLEND); // Enable Blending glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Type Of Blending To Perform glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // Really Nice Perspective Calculations glHint(GL_POINT_SMOOTH_HINT,GL_NICEST); // Really Nice Point Smoothing glEnable(GL_TEXTURE_2D); // Enable Texture Mapping for(loop2=0;loop2<MAX_FIREWORKS;loop2++) init_emitter(loop2); PlaySound ("data/Explode.wav",NULL,SND_FILENAME | SND_ASYNC | SND_LOOP); return TRUE; // Initialization Went OK } int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing { float w = 0.05522847498307933984022516322796f; float h = 0.04142135623730950488016887242097f; float r,g,b; r=0.1f;g=0.1f;b=0.1f; for(loop2=0;loop2<=MAX_FIREWORKS;loop2++) if(e[loop2].burst==1&&e[loop2].life>0) {r+=0.9/(float)MAX_FIREWORKS;g+=0.9/(float)MAX_FIREWORKS;b+=0.9/(float)MAX_FIREWORKS;} glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer glLoadIdentity(); // Reset The ModelView Matrix glColor4f(r,g,b,1.0); glBindTexture(GL_TEXTURE_2D, texture[1]); glBegin(GL_TRIANGLE_STRIP); // Build Quad From A Triangle Strip // h = tan(45.f/2) * 0.1f; w = 640.f/480.f*h; glTexCoord2d(1,1); glVertex3f(w, h, -0.1f); // Top Right glTexCoord2d(0,1); glVertex3f(-w, h, -0.1f); // Top Left glTexCoord2d(1,0); glVertex3f(w, -h, -0.1f); // Bottom Right glTexCoord2d(0,0); glVertex3f(-w, -h, -0.1f); // Bottom Left glEnd(); // Done Building Triangle Strip glBindTexture(GL_TEXTURE_2D,texture[0]); // Select Our Texture for(loop2=0;loop2<MAX_FIREWORKS;loop2++) for (loop=0;loop<MAX_PARTICLES;loop++) // Loop Through All The Particles { if (e[loop2].particle[loop].active) // If The Particle Is Active { float x=e[loop2].particle[loop].x; // Grab Our Particle X Position float y=e[loop2].particle[loop].y; // Grab Our Particle Y Position float z=e[loop2].particle[loop].z+zoom; // Particle Z Pos + Zoom // Draw The Particle Using Our RGB Values, Fade The Particle Based On It's Life glColor4f(e[loop2].particle[loop].r,e[loop2].particle[loop].g,e[loop2].particle[loop].b,e[loop2].particle[loop].life); glBegin(GL_TRIANGLE_STRIP); // Build Quad From A Triangle Strip glTexCoord2d(1,1); glVertex3f(x+0.5f,y+0.5f,z); // Top Right glTexCoord2d(0,1); glVertex3f(x-0.5f,y+0.5f,z); // Top Left glTexCoord2d(1,0); glVertex3f(x+0.5f,y-0.5f,z); // Bottom Right glTexCoord2d(0,0); glVertex3f(x-0.5f,y-0.5f,z); // Bottom Left glEnd(); // Done Building Triangle Strip // If Number Pad 8 And Y Gravity Is Less Than 1.5 Increase Pull Upwards if (keys[VK_NUMPAD8] && (e[loop2].particle[loop].yg<1.5f)) e[loop2].particle[loop].yg+=0.01f; // If Number Pad 2 And Y Gravity Is Greater Than -1.5 Increase Pull Downwards if (keys[VK_NUMPAD2] && (e[loop2].particle[loop].yg>-1.5f)) e[loop2].particle[loop].yg-=0.01f; // If Number Pad 6 And X Gravity Is Less Than 1.5 Increase Pull Right if (keys[VK_NUMPAD6] && (e[loop2].particle[loop].xg<1.5f)) e[loop2].particle[loop].xg+=0.01f; // If Number Pad 4 And X Gravity Is Greater Than -1.5 Increase Pull Left if (keys[VK_NUMPAD4] && (e[loop2].particle[loop].xg>-1.5f)) e[loop2].particle[loop].xg-=0.01f; } } for(loop2=0;loop2<MAX_FIREWORKS;loop2++) update_emitter(loop2); return TRUE; // Everything Went OK } GLvoid KillGLWindow(GLvoid) // Properly Kill The Window { if (fullscreen) // Are We In Fullscreen Mode? { ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop ShowCursor(TRUE); // Show Mouse Pointer } if (hRC) // Do We Have A Rendering Context? { if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts? { MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); } if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? { MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); } hRC=NULL; // Set RC To NULL } if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC { MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); hDC=NULL; // Set DC To NULL } if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window? { MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); hWnd=NULL; // Set hWnd To NULL } if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class { MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION); hInstance=NULL; // Set hInstance To NULL } } /* This Code Creates Our OpenGL Window. Parameters Are: * * title - Title To Appear At The Top Of The Window * * width - Width Of The GL Window Or Fullscreen Mode * * height - Height Of The GL Window Or Fullscreen Mode * * bits - Number Of Bits To Use For Color (8/16/24/32) * * fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */ BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) { GLuint PixelFormat; // Holds The Results After Searching For A Match WNDCLASS wc; // Windows Class Structure DWORD dwExStyle; // Window Extended Style DWORD dwStyle; // Window Style RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values WindowRect.left=(long)0; // Set Left Value To 0 WindowRect.right=(long)width; // Set Right Value To Requested Width WindowRect.top=(long)0; // Set Top Value To 0 WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height fullscreen=fullscreenflag; // Set The Global Fullscreen Flag hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window. wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages wc.cbClsExtra = 0; // No Extra Window Data wc.cbWndExtra = 0; // No Extra Window Data wc.hInstance = hInstance; // Set The Instance wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer wc.hbrBackground = NULL; // No Background Required For GL wc.lpszMenuName = NULL; // We Don't Want A Menu wc.lpszClassName = "OpenGL"; // Set The Class Name if (!RegisterClass(&wc)) // Attempt To Register The Window Class { MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if (fullscreen) // Attempt Fullscreen Mode? { DEVMODE dmScreenSettings; // Device Mode memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure dmScreenSettings.dmPelsWidth = width; // Selected Screen Width dmScreenSettings.dmPelsHeight = height; // Selected Screen Height dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) { // If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode. if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) { fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE } else { // Pop Up A Message Box Letting User Know The Program Is Closing. MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP); return FALSE; // Return FALSE } } } if (fullscreen) // Are We Still In Fullscreen Mode? { dwExStyle=WS_EX_APPWINDOW; // Window Extended Style dwStyle=WS_POPUP; // Windows Style ShowCursor(FALSE); // Hide Mouse Pointer } else { dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style } AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size // Create The Window if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window "OpenGL", // Class Name title, // Window Title dwStyle | // Defined Window Style WS_CLIPSIBLINGS | // Required Window Style WS_CLIPCHILDREN, // Required Window Style 0, 0, // Window Position WindowRect.right-WindowRect.left, // Calculate Window Width WindowRect.bottom-WindowRect.top, // Calculate Window Height NULL, // No Parent Window NULL, // No Menu hInstance, // Instance NULL))) // Dont Pass Anything To WM_CREATE { KillGLWindow(); // Reset The Display MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be { 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 bits, // Select Our 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, // 16Bit 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 }; if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context? { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context { KillGLWindow(); // Reset The Display MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } ShowWindow(hWnd,SW_SHOW); // Show The Window SetForegroundWindow(hWnd); // Slightly Higher Priority SetFocus(hWnd); // Sets Keyboard Focus To The Window ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen if (!InitGL()) // Initialize Our Newly Created GL Window { KillGLWindow(); // Reset The Display MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION); return FALSE; // Return FALSE } return TRUE; // Success } LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window UINT uMsg, // Message For This Window WPARAM wParam, // Additional Message Information LPARAM lParam) // Additional Message Information { switch (uMsg) // Check For Windows Messages { case WM_ACTIVATE: // Watch For Window Activate Message { if (!HIWORD(wParam)) // Check Minimization State { active=TRUE; // Program Is Active } else // Otherwise { active=FALSE; // Program Is No Longer Active } return 0; // Return To The Message Loop } case WM_SYSCOMMAND: // Intercept System Commands { switch (wParam) // Check System Calls { case SC_SCREENSAVE: // Screensaver Trying To Start? case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? return 0; // Prevent From Happening } break; // Exit } case WM_CLOSE: // Did We Receive A Close Message? { PostQuitMessage(0); // Send A Quit Message return 0; // Jump Back } case WM_KEYDOWN: // Is A Key Being Held Down? { keys[wParam] = TRUE; // If So, Mark It As TRUE return 0; // Jump Back } case WM_KEYUP: // Has A Key Been Released? { keys[wParam] = FALSE; // If So, Mark It As FALSE return 0; // Jump Back } case WM_SIZE: // Resize The OpenGL Window { ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height return 0; // Jump Back } } // Pass All Unhandled Messages To DefWindowProc return DefWindowProc(hWnd,uMsg,wParam,lParam); } int WINAPI WinMain( HINSTANCE hInstance, // Instance HINSTANCE hPrevInstance, // Previous Instance LPSTR lpCmdLine, // Command Line Parameters int nCmdShow) // Window Show State { MSG msg; // Windows Message Structure BOOL done=FALSE; // Bool Variable To Exit Loop // Ask The User Which Screen Mode They Prefer if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO) { fullscreen=FALSE; // Windowed Mode } // Create Our OpenGL Window if (!CreateGLWindow("FireWorks based on NeHe Particle System",640,480,16,fullscreen)) { return 0; // Quit If Window Was Not Created } if (fullscreen) // Are We In Fullscreen Mode { slowdown=1.0f; // If So, Speed Up The Particles (3dfx Issue) } while(!done) // Loop That Runs While done=FALSE { if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting? { if (msg.message==WM_QUIT) // Have We Received A Quit Message? { done=TRUE; // If So done=TRUE } else // If Not, Deal With Window Messages { TranslateMessage(&msg); // Translate The Message DispatchMessage(&msg); // Dispatch The Message } } else // If There Are No Messages { // Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene() if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received? { done=TRUE; // ESC or DrawGLScene Signalled A Quit } else // Not Time To Quit, Update Screen { SwapBuffers(hDC); // Swap Buffers (Double Buffering) if (keys[VK_ADD] && (slowdown>1.0f)) slowdown-=0.01f; // Speed Up Particles if (keys[VK_SUBTRACT] && (slowdown<4.0f)) slowdown+=0.01f; // Slow Down Particles if (keys[VK_PRIOR]) zoom+=0.1f; // Zoom In if (keys[VK_NEXT]) zoom-=0.1f; // Zoom Out if (keys[VK_RETURN] && !rp) // Return Key Pressed { rp=true; // Set Flag Telling Us It's Pressed rainbow=!rainbow; // Toggle Rainbow Mode On / Off } if (!keys[VK_RETURN]) rp=false; // If Return Is Released Clear Flag if (keys[VK_F2]) PlaySound(NULL, NULL, 0); if (keys[VK_F3]) PlaySound ("data/Explode.wav",NULL,SND_FILENAME | SND_ASYNC | SND_LOOP); if ((keys[' '] && !sp) || (rainbow && (delay>25))) // Space Or Rainbow Mode { if (keys[' ']) rainbow=false; // If Spacebar Is Pressed Disable Rainbow Mode sp=true; // Set Flag Telling Us Space Is Pressed delay=0; // Reset The Rainbow Color Cycling Delay col++; // Change The Particle Color if (col>11) col=0; // If Color Is To High Reset It } if (!keys[' ']) sp=false; // If Spacebar Is Released Clear Flag // If Up Arrow And Y Speed Is Less Than 200 Increase Upward Speed if (keys[VK_UP] && (yspeed<200)) yspeed+=1.0f; // If Down Arrow And Y Speed Is Greater Than -200 Increase Downward Speed if (keys[VK_DOWN] && (yspeed>-200)) yspeed-=1.0f; // If Right Arrow And X Speed Is Less Than 200 Increase Speed To The Right if (keys[VK_RIGHT] && (xspeed<200)) xspeed+=1.0f; // If Left Arrow And X Speed Is Greater Than -200 Increase Speed To The Left if (keys[VK_LEFT] && (xspeed>-200)) xspeed-=1.0f; delay++; // Increase Rainbow Mode Color Cycling Delay Counter if (keys[VK_F1]) // Is F1 Being Pressed? { keys[VK_F1]=FALSE; // If So Make Key FALSE KillGLWindow(); // Kill Our Current Window fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode // Recreate Our OpenGL Window if (!CreateGLWindow("FireWorks based on NeHe Particle System",640,480,16,fullscreen)) { return 0; // Quit If Window Was Not Created } } } } } // Shutdown KillGLWindow(); // Kill The Window return (msg.wParam); // Exit The Program }
相关文章推荐
- 周日随便看看
- 【转】模板类的声明与实现必须同时放在头文件中
- spring配置文件头文件的说明
- pdf-2-eps
- windows下用sendmail配置php的mail函数
- Unity3D 开发优秀技术资源汇总
- bzoj3144: [Hnoi2013]切糕
- (转) sqlserver,mysql,db2,oracle中判断字段的值不为空
- [Android]Context泄露之谜:Handle & 内部类
- 图的创建
- 屏幕适配全攻略
- 屏幕适配全攻略
- java中的String,StringBuffer,StringBuilder
- 屏幕适配全攻略
- 关于有时候插件加载不出来的情况
- WIN7 (64 位)安装AutoCAD2012失败解决方法
- tomcat发布web项目中文乱码
- 《Monkey Android》第2课之环境搭建
- Combination Sum I/II - Leetcode
- 使用异步Get在新浪微博上获取最新的微博