/* * CS 4280 - Final Project * finprj.cpp * source for finprj.exe * v. alpha 0.7.3 * * References: * www.opengl.org/documentation/specs/glut/spec3/spec3.html * pheatt.emporia.edu/courses/2005/cs410f05/OpenGLin4Weeks/L12.c * www.ncrg.aston.ac.uk/~cornfosd/graphics/opengl/openglman.html * www.eng.mu.edu/corlissg/151.04Sp/ch5.html * www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ * nehe.gamedev.net * gpwiki.org/index.php/OpenGL_Tutorial_Framework:Texture_Mapping * www.euclideanspace.com/software/games/threed/openglcpp/texture/index.htm */ #include #include #include #include #include #include // #define GLUT_USE_SGI_OPENGL struct Objects { GLfloat fOx; GLfloat fOy; int iShape; int iTexture; }; struct Performance { long pointsItem; long pointsChain; long pointsGlobal; long objectsCollected; long objectsCollectedChain; long level; }; struct Coords { int xmin; int ymin; int xmax; int ymax; }; enum { HORIZ, VERT }; enum userDir { NORTH, EAST, SOUTH, WEST }; char version[14] = "Alpha 0.6.5\0"; HDC hDC = NULL; // gdi dc HGLRC hRC = NULL; // rendering dc HWND hWnd = NULL; // win handle HINSTANCE hInstance; // hInstance bool keys[256]; // keyboard bool active = TRUE; // flag bool fullscreen = FALSE; // fullscreen off is default bool light; // light on/off bool lp; // L key bool fp; // F key bool sp; // spacebar bool firstTime = TRUE; // turns light ON bool gotSource = FALSE; // mouse valid src/dest points bool gotDest = FALSE; bool bMatchFound = FALSE; Objects myObj[64]; Performance stats; Coords objCoord[64] = { 36, 25, 83, 73, 88, 25, 137, 73, 142, 25, 189, 73, 195, 25, 242, 73, 247, 25, 295, 73, 301, 25, 348, 73, 354, 25, 402, 73, 407, 25, 454, 73, 36, 78, 83, 126, 88, 78, 137, 126, 142, 78, 189, 126, 195, 78, 242, 126, 247, 78, 295, 126, 301, 78, 348, 126, 354, 78, 402, 126, 407, 78, 454, 126, 36, 131, 83, 179, 88, 131, 137, 179, 142, 131, 189, 179, 195, 131, 242, 179, 247, 131, 295, 179, 301, 131, 348, 179, 354, 131, 402, 179, 407, 131, 454, 179, 36, 184, 83, 232, 88, 184, 137, 232, 142, 184, 189, 232, 195, 184, 242, 232, 247, 184, 295, 232, 301, 184, 348, 232, 354, 184, 402, 232, 407, 184, 454, 232, 36, 237, 83, 285, 88, 237, 137, 285, 142, 237, 189, 285, 195, 237, 242, 285, 247, 237, 295, 285, 301, 237, 348, 285, 354, 237, 402, 285, 407, 237, 454, 285, 36, 289, 83, 338, 88, 289, 137, 338, 142, 289, 189, 338, 195, 289, 242, 338, 247, 289, 295, 338, 301, 289, 348, 338, 354, 289, 402, 338, 407, 289, 454, 338, 36, 343, 83, 391, 88, 343, 137, 391, 142, 343, 189, 391, 195, 343, 242, 391, 247, 343, 295, 391, 301, 343, 348, 391, 354, 343, 402, 391, 407, 343, 454, 391, 36, 396, 83, 444, 88, 396, 137, 444, 142, 396, 189, 444, 195, 396, 242, 444, 247, 396, 295, 444, 301, 396, 348, 444, 354, 396, 402, 444, 407, 396, 454, 444 }; GLfloat xMStart = -10.8f; // matrix x ccord begin GLfloat yMStart = 7.9f; // matrix y ccord begin GLfloat xSpin; // X rotation GLfloat ySpin; // Y rotation GLfloat xSpeed; // X rotation Speed GLfloat ySpeed; // Y rotation Speed GLfloat z = -25.0f; // depth into the screen GLfloat xMouseStart; GLfloat yMouseStart; GLfloat xMouseEnd; GLfloat yMouseEnd; GLUquadricObj *quadratic; // the quadratic object GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f }; GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f }; GLuint filter; // which filter GLuint texture[10]; GLuint object = 0; // which object int placeSource, placeDest; int initCounter = 0; // ================================================== LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM); // ================================================== // scrolls 3 positions at the given address // in the given direction in the array. // Before exiting, updates the score void Scroll( int iToken, int index, int iDir) { static int iCounter = 0; static int sessionNumber = 0; int i = index; switch ( iDir) { case 0: // horizontal { if ( index / 8 ) { while ( index > 7 ) { for ( i = index; i < (index +3); i++ ) myObj[i].iTexture = myObj[i-8].iTexture; index -= 8; Sleep( 100); } } for ( i = index; i < (index+3); i++ ) myObj[i].iTexture = rand() % 6; break; } case 1: // vertical { int row = index / 8; i = row; while ( i-- ) { myObj[index+16].iTexture = myObj[index-8].iTexture; index -= 8; Sleep( 100); } myObj[index].iTexture = rand() % 6; } } // end of switch (iDir) if ( sessionNumber != iToken ) { iCounter = 0; stats.pointsChain = stats.level * stats.pointsItem * 3; } else { ++iCounter; stats.pointsChain = stats.level * iCounter * stats.pointsItem * 3; } stats.pointsGlobal += stats.pointsChain; bMatchFound = TRUE; gotSource = gotDest = FALSE; placeSource = placeDest = 0; } // ================================================== // checks if any 3 equal obj.s void CheckMatch( ) { int iToken = rand(); int iOffset = 0; // horizontal check for ( iOffset = 0; iOffset <= 56; iOffset += 8 ) for ( int i = 0; i < 6; i++) { int iAddr = iOffset + i; if ( myObj[iAddr].iTexture == myObj[iAddr+1].iTexture && myObj[iAddr].iTexture == myObj[iAddr+2].iTexture ) { Scroll( iToken, iAddr, HORIZ); return; } } // vertical check for ( iOffset = 0; iOffset < 6; iOffset++ ) for ( int i = 0; i <= 40; i += 8) { int iAddr = iOffset + i; if ( myObj[iAddr].iTexture == myObj[iAddr+8].iTexture && myObj[iAddr].iTexture == myObj[iAddr+16].iTexture ) { Scroll( iToken, iAddr, VERT); return; } } } // ================================================== // swaps two objects void SwapObj() { Objects temp; bMatchFound = FALSE; /* temp.fOx = myObj[placeDest].fOx; temp.fOy = myObj[placeDest].fOy; temp.iShape = myObj[placeDest].iShape; temp.iTexture = myObj[placeDest].iTexture; myObj[placeDest].fOx = myObj[placeSource].fOx; myObj[placeDest].fOy = myObj[placeSource].fOy; myObj[placeDest].iShape = myObj[placeSource].iShape; myObj[placeDest].iTexture = myObj[placeSource].iTexture; myObj[placeSource].fOx = temp.fOx; myObj[placeSource].fOy = temp.fOy; myObj[placeSource].iShape = temp.iShape; myObj[placeSource].iTexture = temp.iTexture; */ temp.iTexture = myObj[placeDest].iTexture; myObj[placeDest].iTexture = myObj[placeSource].iTexture; myObj[placeSource].iTexture = temp.iTexture; CheckMatch(); if( ! bMatchFound ) // revert back the obj.s { /* myObj[placeSource].fOx = myObj[placeDest].fOx; myObj[placeSource].fOy = myObj[placeDest].fOy; myObj[placeSource].iShape = myObj[placeDest].iShape; myObj[placeSource].iTexture = myObj[placeDest].iTexture; myObj[placeDest].fOx = temp.fOx; myObj[placeDest].fOy = temp.fOy; myObj[placeDest].iShape = temp.iShape; myObj[placeDest].iTexture = temp.iTexture; */ myObj[placeSource].iTexture = myObj[placeDest].iTexture; myObj[placeDest].iTexture = temp.iTexture; } } // ======================================== // zeroes the counters, also for a new game void InitScore() { stats.level = 1; stats.objectsCollected = 0; stats.objectsCollectedChain = 0; stats.pointsChain = 0; stats.pointsGlobal = 0; stats.pointsItem = 5; } // ======================================== // init the obj.s' texture // also good when new level void InitText() { srand( (unsigned) time( NULL)); for (int j = 0; j < 64; j++) myObj[j].iTexture = rand() % 6; // oh and don't forget few other things xMouseStart = yMouseStart = xMouseEnd = yMouseEnd = 0; gotSource = gotDest = bMatchFound = FALSE; placeSource = placeDest = 0; } // ================================================ // updates both the array of objects and statistics void UpdateTables() { CheckMatch( ); long lLevelLimit_objectsCollected = 12.5 * stats.level * stats.level + 6 * stats.level; long lLevelLimit_points = 500 * stats.level * stats.level + 500 * stats.level; if ( stats.objectsCollected > lLevelLimit_objectsCollected // OR || stats.pointsGlobal > lLevelLimit_points - 500 ) { // then prize ++stats.level; // good job bud stats.pointsItem += 5; InitText(); } // refresh score display // char str[10] = "Tiles\0"; // glColor3f(0.5f,0.8f,1.0f); // glRasterPos2f( 50.0, 200.0); // glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'T'); } // ======================================= // init the coords of the array of obiects void InitObjs() { int i = 0; float iX = xMStart; float iY = yMStart; for ( ; iY > (yMStart-15.8f); iY -= 2 ) { for ( iX = xMStart; iX < 4.7f; iX += 2 ) { myObj[i].fOx = iX; myObj[i].fOy = iY; iX += 0.2f; ++i; } iY -= 0.2f; } InitScore(); } // ====================================== // check if bitmap exists AUX_RGBImageRec *LoadBMP( char *file_name) { FILE *hFile = NULL; if (! file_name) return NULL; hFile = fopen( file_name,"r"); if ( hFile) { fclose( hFile); // close return auxDIBImageLoad( file_name); // texture } return NULL; // else return error } // =============================================== // bitmap to texture int LoadTextures() { int iStatus = FALSE; // false in the beginning AUX_RGBImageRec *TextureImage[6]; memset( TextureImage, 0, sizeof(void *)*6 ); if ( TextureImage[0] = LoadBMP( "wood0.bmp") ) if ( TextureImage[1] = LoadBMP( "wood1.bmp") ) if ( TextureImage[2] = LoadBMP( "wood2.bmp") ) if ( TextureImage[3] = LoadBMP( "wood3.bmp") ) if ( TextureImage[4] = LoadBMP( "wood4.bmp") ) if ( TextureImage[5] = LoadBMP( "wood5.bmp") ) { iStatus = TRUE; glGenTextures( 1, &texture[0]); // create texture // mipMapped texture glBindTexture( GL_TEXTURE_2D, texture[0]); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); gluBuild2DMipmaps( GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); glGenTextures( 1, &texture[1]); // create texture // mipMapped texture glBindTexture( GL_TEXTURE_2D, texture[1]); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); gluBuild2DMipmaps( GL_TEXTURE_2D, 3, TextureImage[1]->sizeX, TextureImage[1]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[1]->data); glGenTextures( 1, &texture[2]); // create exture // mipMapped texture glBindTexture( GL_TEXTURE_2D, texture[2]); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); gluBuild2DMipmaps( GL_TEXTURE_2D, 3, TextureImage[2]->sizeX, TextureImage[2]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[2]->data); glGenTextures( 1, &texture[3]); // create texture // mipMapped texture glBindTexture( GL_TEXTURE_2D, texture[3]); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); gluBuild2DMipmaps( GL_TEXTURE_2D, 3, TextureImage[3]->sizeX, TextureImage[3]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[3]->data); glGenTextures( 1, &texture[4]); // create texture // mipMapped texture glBindTexture( GL_TEXTURE_2D, texture[4]); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); gluBuild2DMipmaps( GL_TEXTURE_2D, 3, TextureImage[4]->sizeX, TextureImage[4]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[4]->data); glGenTextures( 1, &texture[5]); // create texture // mipMapped texture glBindTexture( GL_TEXTURE_2D, texture[5]); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); gluBuild2DMipmaps( GL_TEXTURE_2D, 3, TextureImage[5]->sizeX, TextureImage[5]->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[5]->data); } if ( TextureImage[0] ) // if texture exists { if ( TextureImage[0]->data ) // if texture image exists free( TextureImage[0]->data); // free texture memory free( TextureImage[0]); // free image structure } if ( TextureImage[1] ) { if ( TextureImage[1]->data ) free( TextureImage[1]->data); free( TextureImage[1]); } if ( TextureImage[2] ) { if ( TextureImage[2]->data ) free( TextureImage[2]->data); free( TextureImage[2]); } if ( TextureImage[3] ) { if ( TextureImage[3]->data ) free( TextureImage[3]->data); free( TextureImage[3]); } if ( TextureImage[4] ) { if ( TextureImage[4]->data ) free( TextureImage[4]->data); free( TextureImage[4]); } if ( TextureImage[5] ) { if ( TextureImage[5]->data ) free( TextureImage[5]->data); free( TextureImage[5]); } return iStatus; } // ================================================= // resize glWindow GLvoid ResizeScene( GLsizei width, GLsizei height) { if ( height == 0 ) // divide by zero ? height=1; glViewport( 0, 0, width, height); // reset viewport glMatrixMode( GL_PROJECTION); // choose projection matrix glLoadIdentity(); // reset it // aspect ratio gluPerspective( 45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f); glMatrixMode( GL_MODELVIEW); // choose modelview glLoadIdentity(); // reset it } // ================================================= // init the machine int InitGL( GLvoid) { if ( ! LoadTextures() ) return FALSE; // if wrong return FALSE glEnable( GL_TEXTURE_2D); // texture mapping glShadeModel( GL_SMOOTH); // smooth shading glClearColor( 0.0f, 0.0f, 0.0f, 0.5f); // black glClearDepth( 1.0f); // depth buffer glEnable( GL_DEPTH_TEST); // depth testing glDepthFunc( GL_LEQUAL); // what type of depth testing glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // optimal perspective // ambient light glLightfv( GL_LIGHT1, GL_AMBIENT, LightAmbient); // diffuse light glLightfv( GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // position glLightfv( GL_LIGHT1, GL_POSITION, LightPosition); glEnable( GL_LIGHT1); quadratic = gluNewQuadric(); // just a pointer gluQuadricNormals( quadratic, GLU_SMOOTH); // smooth normals gluQuadricTexture( quadratic, GL_TRUE); // texture coords return TRUE; } // ================================================= GLvoid DrawObject( int i) { glBegin( GL_QUADS); // front glNormal3f( 0.0f, 0.0f, 1.0f); glTexCoord2f( 0.0f, 0.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy-1.0f, z+1); glTexCoord2f( 1.0f, 0.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy-1.0f, z+1); glTexCoord2f( 1.0f, 1.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy+1.0f, z+1); glTexCoord2f( 0.0f, 1.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy+1.0f, z+1); // back glNormal3f( 0.0f, 0.0f, -1.0f); glTexCoord2f( 1.0f, 0.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy-1.0f, z-1); glTexCoord2f( 1.0f, 1.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy+1.0f, z-1); glTexCoord2f( 0.0f, 1.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy+1.0f, z-1); glTexCoord2f( 0.0f, 0.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy-1.0f, z-1); // top glNormal3f( 0.0f, 1.0f, 0.0f); glTexCoord2f( 0.0f, 1.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy+1.0f, z-1); glTexCoord2f( 0.0f, 0.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy+1.0f, z+1); glTexCoord2f( 1.0f, 0.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy+1.0f, z+1); glTexCoord2f( 1.0f, 1.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy+1.0f, z-1); // bottom glNormal3f( 0.0f,-1.0f, 0.0f); glTexCoord2f( 1.0f, 1.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy-1.0f, z-1); glTexCoord2f( 0.0f, 1.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy-1.0f, z-1); glTexCoord2f( 0.0f, 0.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy-1.0f, z+1); glTexCoord2f( 1.0f, 0.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy-1.0f, z+1); // right glNormal3f( 1.0f, 0.0f, 0.0f); glTexCoord2f( 1.0f, 0.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy-1.0f, z-1); glTexCoord2f( 1.0f, 1.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy+1.0f, z-1); glTexCoord2f( 0.0f, 1.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy+1.0f, z+1); glTexCoord2f( 0.0f, 0.0f); glVertex3f( myObj[i].fOx+1.0f, myObj[i].fOy-1.0f, z+1); // left glNormal3f( -1.0f, 0.0f, 0.0f); glTexCoord2f( 0.0f, 0.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy-1.0f, z-1); glTexCoord2f( 1.0f, 0.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy-1.0f, z+1); glTexCoord2f( 1.0f, 1.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy+1.0f, z+1); glTexCoord2f( 0.0f, 1.0f); glVertex3f( myObj[i].fOx-1.0f, myObj[i].fOy+1.0f, z-1); glEnd(); } // ================================================= // open the dances int DrawScene( GLvoid) { if ( firstTime ) // switch ON the diffuse light { if ( initCounter > 2) { // save status glPushMatrix(); glDisable( GL_LIGHTING ); glDisable(GL_TEXTURE_2D); glMatrixMode( GL_PROJECTION ); // glLoadIdentity( ); // gluOrtho2D( -1.0, 1.0, -1.0, 1.0 ); glOrtho( 0.0, 640.0, 0.0, 480.0, -0.0, 1.0 ); glLoadIdentity( ); // glMatrixMode( GL_MODELVIEW ); // glLoadIdentity( ); glColor3f( 250, 250, 250 ); // this chunk to be executed but it doesn't !! // char str[10] = "Tiles\0"; glRasterPos2f( 3.0, 8.0); glutBitmapCharacter( GLUT_BITMAP_TIMES_ROMAN_24, 'T'); glRasterPos2f( 5.0, 4.0); glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, 'V'); // restore status glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glEnable(GL_TEXTURE_2D); glEnable( GL_LIGHTING ); glLoadIdentity( ); } ++initCounter; if ( initCounter > 2 ) firstTime = FALSE; } // true stuff glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear screen + d buffer glLoadIdentity(); // reset // DrawOctahedron(); glutSolidTorus ( 0.5, 0.99, 15, 24); // glutSolidOctahedron( ); glutSolidTeapot( 1.3); for ( int i = 0; i < 64; i++) { glBindTexture( GL_TEXTURE_2D, texture[myObj[i].iTexture]); DrawObject( i); } UpdateTables(); CheckMatch(); return TRUE; // keep going } // =========================== // kill da window GLvoid KillGLWindow( GLvoid) { gluDeleteQuadric( quadratic); // free system resources if ( fullscreen) // fullscreen ? { ChangeDisplaySettings( NULL,0); // then switch back ShowCursor( TRUE); // show mouse pointer } if ( hRC) // is there a rendering context ? { if ( !wglMakeCurrent( NULL, NULL)) // release DC and RC contexts ? MessageBox( NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); if ( ! wglDeleteContext( hRC) ) // 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) ) // 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) ) // destroy the window ? { MessageBox( NULL,"Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hWnd = NULL; // set hWnd to NULL } // unregister class if ( !UnregisterClass( "OpenGL", hInstance) ) { MessageBox( NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); hInstance = NULL; // set hInstance to NULL } } // ================================================= // create opengl window 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; DWORD dwStyle; RECT WindowRect; WindowRect.left = (long) 0; WindowRect.right = (long) width; WindowRect.top = (long) 0; WindowRect.bottom = (long) height; fullscreen = fullscreenflag; // set fullscreen flag // usual win stuff hInstance = GetModuleHandle( NULL); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( NULL, IDI_WINLOGO); wc.hCursor = LoadCursor( NULL, IDC_ARROW); wc.hbrBackground = NULL; // not required in opengl wc.lpszMenuName = NULL; // no menu needed wc.lpszClassName = "OpenGL"; if ( !RegisterClass( &wc) ) { MessageBox( NULL, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION ); return FALSE; } if ( fullscreen) { DEVMODE dmScreenSettings; // device mode memset( &dmScreenSettings, 0, sizeof(dmScreenSettings)); // clear mem dmScreenSettings.dmSize = sizeof( dmScreenSettings); // size of devmode structure dmScreenSettings.dmPelsWidth = width; // screen width dmScreenSettings.dmPelsHeight = height; // screen height dmScreenSettings.dmBitsPerPel = bits; // bits per pixel dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; // try to set selected mode and get results. if ( ChangeDisplaySettings( &dmScreenSettings, CDS_FULLSCREEN )!= DISP_CHANGE_SUCCESSFUL ) { // if fails offer 2 options: quit or use windowed mode. if (MessageBox( NULL, "The requested fullscreen mode is not supported by\nyour video card. Use windowed mode instead ?", "Final Project", MB_YESNO | MB_ICONEXCLAMATION) == IDYES ) fullscreen = FALSE; // windowed mMode sSelected else { // close MessageBox( NULL, "Program Will Now Close.", "ERROR", MB_OK | MB_ICONSTOP); return FALSE; } } } if ( fullscreen) // still in fullscreen mode ? { dwExStyle = WS_EX_APPWINDOW; // window extended style dwStyle = WS_POPUP; // windows style ShowCursor( FALSE); // hide pointer } else { dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // window extended style dwStyle = WS_OVERLAPPEDWINDOW; // windows style } // adjust window to true requested size AdjustWindowRectEx( &WindowRect, dwStyle, FALSE, dwExStyle); // Create The Window if ( ! (hWnd = CreateWindowEx( dwExStyle, // window extended style "OpenGL", // class name title, dwStyle | // defined window style WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, // window position WindowRect.right - WindowRect.left, // window width WindowRect.bottom - WindowRect.top, // window height NULL, // no parent NULL, // no menu hInstance, NULL))) // Don't pass anything to WM_CREATE { KillGLWindow(); // reset MessageBox( NULL, "Window Creation Error.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; } static PIXELFORMATDESCRIPTOR pfd= { sizeof( PIXELFORMATDESCRIPTOR), // its size 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 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 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 MessageBox( NULL, "Can't Create A GL Device Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; } // did windows find a matching pixel format ? if ( ! ( PixelFormat = ChoosePixelFormat( hDC, &pfd))) { KillGLWindow(); MessageBox( NULL, "Can't Find A Suitable PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; } // can set the pixel format ? if ( ! SetPixelFormat( hDC, PixelFormat, &pfd)) { KillGLWindow(); MessageBox( NULL, "Can't Set The PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; } // get a rendering context ? if ( ! ( hRC = wglCreateContext(hDC))) { KillGLWindow(); MessageBox( NULL, "Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; } if ( ! wglMakeCurrent( hDC, hRC)) // try to activate the rendering context { KillGLWindow(); MessageBox( NULL, "Can't Activate The GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; } ShowWindow( hWnd, SW_SHOW); // show the window SetForegroundWindow( hWnd); // slightly higher priority SetFocus( hWnd); // sets keyboard focus to the window ResizeScene( width, height); // set up the perspective GL screen if ( ! InitGL() ) // init the GL window { KillGLWindow(); MessageBox( NULL, "Initialization Failed.", "fanculo ERROR", MB_OK | MB_ICONEXCLAMATION); return FALSE; } return TRUE; // smooth } // ================================================= LRESULT CALLBACK WndProc( HWND hWnd, // handle UINT uMsg, // message WPARAM wParam, // additional msg info LPARAM lParam) // additional msg info { switch ( uMsg) // check for msgs { case WM_ACTIVATE: // win activate msg { if (! HIWORD( wParam)) // check minimization state active = TRUE; // program is active else active = FALSE; // no longer active return 0; // return to the message loop } case WM_CLOSE: { PostQuitMessage(0); return 0; } case WM_KEYDOWN: // is a key down ? { keys[wParam] = TRUE; // mark it TRUE return 0; } case WM_KEYUP: { keys[wParam] = FALSE; // mark it FALSE return 0; } case WM_SIZE: { ResizeScene( LOWORD( lParam), HIWORD( lParam)); // LoWord=width HiWord=height return 0; } case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: { xMouseStart = yMouseStart = xMouseEnd = yMouseEnd = 0; SetCapture( hWnd); if ( ! gotSource ) { xMouseStart = LOWORD( lParam); yMouseStart = HIWORD( lParam); // check if mouse point is in rect for ( int k = 0; k < 64; k++) if ( xMouseStart >= objCoord[k].xmin && xMouseStart <= objCoord[k].xmax && yMouseStart >= objCoord[k].ymin && yMouseStart <= objCoord[k].ymax ) { gotSource = TRUE; placeSource = k; return 0; } } else { gotDest = FALSE; placeDest = 0; xMouseEnd = LOWORD( lParam); yMouseEnd = HIWORD( lParam); // check if mouse point is in rect for ( int k = 0; k < 64; k++) if ( xMouseEnd >= objCoord[k].xmin && xMouseEnd <= objCoord[k].xmax && yMouseEnd >= objCoord[k].ymin && yMouseEnd <= objCoord[k].ymax ) { placeDest = k; break; } } // check if the two pieces are adjacent if ( placeSource != placeDest ) if ( placeDest == (placeSource + 1) || placeDest == (placeSource - 1) || placeDest == (placeSource + 8) || placeDest == (placeSource - 8) ) gotDest = TRUE; if ( gotSource && gotDest && placeSource != placeDest ) { SwapObj( ); placeSource = placeDest = 0; gotSource = gotDest = FALSE; } else { if ( gotSource ) { placeSource = placeDest = 0; gotSource = gotDest = FALSE; } } return 0; } case WM_LBUTTONUP: case WM_RBUTTONUP: { xMouseEnd = LOWORD( lParam); yMouseEnd = HIWORD( lParam); // check if mouse point is in rect for ( int k = 0; k < 64; k++) { if ( xMouseEnd >= objCoord[k].xmin && xMouseEnd <= objCoord[k].xmax && yMouseEnd >= objCoord[k].ymin && yMouseEnd <= objCoord[k].ymax ) { placeDest = k; break; } } // check if the two pieces are adjacent if ( placeSource != placeDest ) { if ( placeDest == (placeSource + 1) || placeDest == (placeSource - 1) || placeDest == (placeSource + 8) || placeDest == (placeSource - 8) ) { gotDest = TRUE; } } if ( gotSource && gotDest && placeSource != placeDest ) SwapObj( ); return 0; } case WM_MOUSEMOVE: { xMouseEnd = LOWORD( lParam); yMouseEnd = HIWORD( lParam); return 0; } } // the remainder of the msg to DefWindowProc return DefWindowProc( hWnd, uMsg, wParam, lParam); } // ================================================ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { InitObjs(); InitText(); MSG msg; BOOL done = FALSE; // to exit loop // ask the user what screen mode they prefer if ( MessageBox( NULL, "Would you like to run in fullscreen mode?", "Start FullScreen?", MB_YESNO | MB_ICONQUESTION) == IDNO ) fullscreen = FALSE; // create openGL window if ( ! CreateGLWindow("Final Project", 640, 480, 16, fullscreen) ) return 0; // exit if error while ( !done ) // loop runs if done is FALSE { if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE)) { if ( msg.message == WM_QUIT) { done = TRUE; } else // tom & jerry { TranslateMessage(&msg); DispatchMessage(&msg); } } else // if no message { // draw the scene + wait for ESC + quit if ( ( active && !DrawScene() ) || keys[VK_ESCAPE] ) // any quit done = TRUE; // either ESC or DrawScene quitted else // update screen { SwapBuffers( hDC); // swap buffers ( double buffering ) if ( keys['L'] && !lp) { lp = TRUE; light = !light; if ( !light) glDisable( GL_LIGHTING); else glEnable( GL_LIGHTING); } if ( !keys['L']) lp = FALSE; if ( keys[VK_PRIOR]) z -= 0.02f; if ( keys[VK_NEXT]) z += 0.02f; if ( keys[VK_UP]) xSpeed -= 0.01f; if ( keys[VK_DOWN]) xSpeed += 0.01f; if ( keys[VK_RIGHT]) ySpeed += 0.01f; if ( keys[VK_LEFT]) ySpeed -= 0.01f; if ( keys[VK_F1]) // F1 ? { keys[VK_F1] = FALSE; KillGLWindow(); fullscreen = !fullscreen; if ( ! CreateGLWindow("Final Project", 640, 480, 16, fullscreen)) return 0; // if error quit } } } } // bye KillGLWindow(); return ( msg.wParam); }