📄 billiards.cpp
字号:
ballList[0].speed.x = powX*(-0.1); ballList[0].speed.z = powZ*(-0.1); doAnimation = true; } } if ((button == GLUT_MIDDLE_BUTTON) && (state == GLUT_DOWN)) { middleMouseButton = true; pressedZoom = zoom; } if ((button == GLUT_MIDDLE_BUTTON) && (state == GLUT_UP)) { middleMouseButton = false; } glutPostRedisplay();}// Determines what happens when the mouse is moved.void lookMouse(int x, int y) { if (leftMouseButton == true) { theta = pressedTheta + (x - prevMouseX)*0.005; elevationAngle = pressedElevation + (y - prevMouseY)*0.005; } if (rightMouseButton == true) { theta = pressedTheta + (x - prevMouseX)*0.005; power = 3.0 + (y - prevMouseY)*0.5; if (power >= 35.0) power = 35.0; if (power <= 3.0) power = 3.0; } if (middleMouseButton == true) { zoom = pressedZoom + (y - prevMouseY)*1.0; if (zoom < 10) zoom = 10; if (zoom > 100) zoom = 100; } updateCamera(); glutPostRedisplay();}// Handles the collision of two balls on the table.void deflectBalls(int ballOne, int ballTwo) { vector3 midPointConnectV = vector3(0.0, 0.0, 0.0); vector3 relative = vector3(0.0, 0.0, 0.0); float impulse = 0.0, e = 0.8; midPointConnectV = ballList[ballOne].position - ballList[ballTwo].position; relative = ballList[ballOne].speed - ballList[ballTwo].speed; impulse = ((-1.0)*(1.0 + e)*(relative % midPointConnectV)) / (midPointConnectV % (midPointConnectV * (2.0 / ballList[ballOne].mass))); ballList[ballOne].collided = true; ballList[ballOne].speed = ballList[ballOne].speed + ((midPointConnectV)*(impulse / ballList[ballOne].mass)); ballList[ballOne].updateSpeedSize(); if (ballList[ballOne].speedSize == 0) ballList[ballOne].speedSize = 0.000001; ballList[ballOne].accell = (ballList[ballOne].speed * -1.0) * (ballList[ballOne].accellSize) * (1 / ballList[ballOne].speedSize); ballList[ballTwo].collided = true; ballList[ballTwo].speed = ballList[ballTwo].speed - ((midPointConnectV)*(impulse / ballList[ballTwo].mass)); ballList[ballTwo].updateSpeedSize(); if (ballList[ballTwo].speedSize == 0) ballList[ballTwo].speedSize = 0.000001; ballList[ballTwo].accell = (ballList[ballTwo].speed * -1.0) * (ballList[ballTwo].accellSize) * (1 / ballList[ballTwo].speedSize); alSourcePlay(soundClip[COLLIDE]); if ((error = alGetError()) != AL_NO_ERROR) DisplayALError("alSourcePlay COLLIDE : ", error);}// Determines what happens when a ball is hit into a pocket.void ballInPocket(int ballNr, int pocketNr) { ballList[ballNr].setPos(-1000.0, 2000, -1000); if ((ballNr != 0) && (ballList[ballNr].inPlay == true)) { // No team if (players[currentPlayer].side == -1) { if (ballNr > 8) { players[currentPlayer].side = 1; players[(currentPlayer+1)%playerCount].side = 0; } else if (ballNr < 8) { players[currentPlayer].side = 0; players[(currentPlayer+1)%playerCount].side = 1; } if (ballNr != 8) { players[currentPlayer].noOfShots += 1; players[currentPlayer].balls[ballNr] = true; } // Has team } else { // Check that the correct team ball was hit if (players[currentPlayer].side == 0) { if (ballNr < 8) { players[currentPlayer].noOfShots += 1; players[currentPlayer].balls[ballNr] = true; } else if (ballNr > 8) { players[currentPlayer].noOfShots = 0; players[(currentPlayer+1)%playerCount].noOfShots += 1; players[(currentPlayer+1)%playerCount].balls[ballNr] = true; } } else if (players[currentPlayer].side == 1) { if (ballNr > 8) { players[currentPlayer].noOfShots += 1; players[currentPlayer].balls[ballNr] = true; } else if (ballNr < 8) { players[currentPlayer].noOfShots = 0; players[(currentPlayer+1)%playerCount].noOfShots += 1; players[(currentPlayer+1)%playerCount].balls[ballNr] = true; } } } // Eight-ball has been sunk (end of game), determine winner (if any). if (ballNr == 8) { if (players[currentPlayer].side != -1) { int completeList = 0; for (int k=1; k < 8; k++) { if (players[currentPlayer].balls[players[currentPlayer].side*8 + k] == true) completeList++; } if (completeList == 7) { strcat(endGame, "Player "); strcat(endGame, players[currentPlayer].name); strcat(endGame, " wins! "); } } gameover = true; glutPostRedisplay(); } } else { returnWhiteBall = true; players[(currentPlayer+1)%playerCount].noOfShots += 1; players[currentPlayer].noOfShots = 0; } ballList[ballNr].inPlay = false; alSourcePlay(soundClip[SINK]); if ((error = alGetError()) != AL_NO_ERROR) DisplayALError("alSourcePlay 0 : ", error);}// Instantiates the physics objects and reset them to predefined states.void initPhysics() { // Setup balls' positions on table ballList[0] = mySphere(0.0, 24.9 , minZ - minZ/3); // Closely packed triangle (may cause some problems for collision detection/response) ballList[15] = mySphere(7.0, 24.9 , 27.0); ballList[1] = mySphere(3.5, 24.9 , 27.0); ballList[14] = mySphere(0.0, 24.9 , 27.0); ballList[13] = mySphere(-3.5, 24.9 , 27.0); ballList[2] = mySphere(-7.0, 24.9 , 27.0); ballList[3] = mySphere(5.25, 24.9 , 23.5); ballList[12] = mySphere(1.75, 24.9 , 23.5); ballList[4] = mySphere(-1.75, 24.9 , 23.5); ballList[11] = mySphere(-5.25, 24.9 , 23.5); ballList[10] = mySphere(3.5, 24.9 , 20.0); ballList[8] = mySphere(0.0, 24.9 , 20.0); ballList[5] = mySphere(-3.5, 24.9 , 20.0); ballList[6] = mySphere(1.75, 24.9 , 16.5); ballList[7] = mySphere(-1.75, 24.9 , 16.5); ballList[9] = mySphere(0.0, 24.9 , 13.0); // Initialize physics properties for balls for (int r=0; r < ballCount; r++) { ballList[r].setDefaults(); }}// Resets the game parameters and cameravoid resetGame() { initPhysics(); setupPlayers(); gameover = false; theta = M_PI + M_PI/2.0; updateTarget(); updateCamera(); endGame[0] = '\0';}// Sets up the list of playersvoid setupPlayers() { for (int p=0; p < playerCount; p++) { for (int i = 0; i < ballCount; i++) players[p].balls[i] = false; players[p].name = nameList[p]; players[p].noOfShots = 0; players[p].side = -1; players[p].id = p; } // First player in list starts the game players[0].noOfShots = 1; currentPlayer = 0;}// Rendered window's reshape function (manages changes to size of the window).void changeParentWindow(GLsizei width, GLsizei height) { if (height == 0) height = 1; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (GLfloat)width/height, 0.1, 5000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity();}// Initializes the OpenGL display listsvoid setupLists() { GLint listCount = 5; displayList[0] = glGenLists(listCount-1); for (GLint k=1; k < listCount; k++) { displayList[k] = displayList[0] + k; } renderTableLegs(); renderTable(); renderRoom(); renderBalcony();}// Displays OpenAL error messagesALvoid DisplayALError(ALbyte *szText, ALint errorcode) { printf("%s%s", szText, alGetString(errorcode));}// Loads .WAV sound files using OpenAL (opensource multi-platform audio libraries)void loadSound() { ALfloat listenerPos[]={0.0,0.0,0.0}; ALfloat listenerVel[]={0.0,0.0,0.0}; ALfloat listenerOri[]={0.0,0.0,-1.0, 0.0,1.0,0.0}; // "at", then "up" ALsizei size,freq; ALenum format; ALvoid *data; ALboolean loop; const ALuint NUM_BUFFERS = 4; char* audioFiles[NUM_BUFFERS] = {"audio/shoot.wav", "audio/hit.wav", "audio/side.wav", "audio/sunk.wav"}; ALuint g_Buffers[NUM_BUFFERS]; // Initialize OpenAL alutInit(0, NULL); alGetError(); // Generate Buffers alGenBuffers(NUM_BUFFERS, g_Buffers); for (ALuint k=0; k < NUM_BUFFERS; k++) { alutLoadWAVFile(audioFiles[k],&format,&data,&size,&freq,&loop); alBufferData(g_Buffers[k],format,data,size,freq); alutUnloadWAV(format,data,size,freq); } // Generate Sources alGenSources(NUM_BUFFERS,soundClip); for (ALuint r=0; r < NUM_BUFFERS; r++) { alSourcei(soundClip[r], AL_BUFFER, g_Buffers[r]); } // Set Listener Position ... alListenerfv(AL_POSITION,listenerPos); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alListenerfv POSITION : ", error); exit(-1); } // Set Listener Velocity ... alListenerfv(AL_VELOCITY,listenerVel); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alListenerfv VELOCITY : ", error); exit(-1); } // Set Listener Orientation ... alListenerfv(AL_ORIENTATION,listenerOri); if ((error = alGetError()) != AL_NO_ERROR) { DisplayALError("alListenerfv ORIENTATION : ", error); exit(-1); }}// Initializes basic lighting parameters for use in the final rendered scene.void initlights(void) { // Global parameters / settings GLfloat lmodel_ambient[] = { 0.5, 0.5, 0.5, 1.0 }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); GLfloat ambient[] = { 0.8, 0.8, 0.8, 1.0 }; GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f}; // Table spotlight (0) glLightfv(GL_LIGHT0,GL_SPECULAR,specular); glLightfv(GL_LIGHT0,GL_POSITION,light0Pos); glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,45.0f); glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,100.0f); // Global Ambient light (1) glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, ambient); glLightfv(GL_LIGHT1, GL_POSITION, light1Pos); // Material settings GLfloat mat_diffuse[] = { 0.5, 0.5, 0.5, 1.0 }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 80.0 }; glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR,mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); // Enable lighting glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_LIGHT1);}// Load Bitmaps And Convert To Texturesvoid LoadGLTextures() { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); for (int k=0; k < textureCount; k++) { if (!ImageLoad(textureFilenames[k], &myTextureData[k])) exit(1); // Various texture specific parameters, including wrapping/tiling and filtering. glGenTextures(1, &theTexture[k]); glBindTexture(GL_TEXTURE_2D, theTexture[k]); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); 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, myTextureData[k].sizeX, myTextureData[k].sizeY, GL_RGB, GL_UNSIGNED_BYTE, myTextureData[k].data); }}// Sets up some global OpenGL parameters..void initScene(int argc, char **argv) { LoadGLTextures(); loadSound(); glShadeModel(GL_SMOOTH); glClearStencil(0); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glEnable(GL_TEXTURE_2D); // Instantiates the quadric object used to render the pillars and table sides (etc.). pillarCylinder=gluNewQuadric(); gluQuadricNormals(pillarCylinder, GLU_FLAT); gluQuadricOrientation(pillarCylinder, GLU_OUTSIDE); gluQuadricTexture(pillarCylinder, GL_TRUE); // Instantiates the quadric object used to render the billiard balls. ballQuadric=gluNewQuadric(); gluQuadricNormals(ballQuadric, GLU_SMOOTH); gluQuadricOrientation(ballQuadric, GLU_OUTSIDE); gluQuadricTexture(ballQuadric, GL_TRUE);}// The main function, sets up the window and links up the OpenGL GLUT functions.int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA | GLUT_STENCIL); glutInitWindowPosition(100,100); glutInitWindowSize(parentWindowWidth,parentWindowHeight); mainWindow = glutCreateWindow("The Blue Room"); glutReshapeFunc(changeParentWindow); glutDisplayFunc(renderParentWindow); glutKeyboardFunc(keys); glutSpecialFunc(specialKeyPressed); glutMouseFunc(useMouse); glutMotionFunc(lookMouse); glutSetCursor(GLUT_CURSOR_CROSSHAIR); glutIdleFunc(idle); glutFullScreen(); initScene(argc,argv); initlights(); setupLists(); resetGame(); glutMainLoop(); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -