| //======================================================================== |
| // This is a small test application for GLFW. |
| // This is an OpenGL port of the famous "PONG" game (the first computer |
| // game ever?). It is very simple, and could be improved alot. It was |
| // created in order to show off the gaming capabilities of GLFW. |
| //======================================================================== |
| |
| #include <GL/glfw.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <math.h> |
| |
| |
| //======================================================================== |
| // Constants |
| //======================================================================== |
| |
| // Screen resolution |
| #define WIDTH 640 |
| #define HEIGHT 480 |
| |
| // Player size (units) |
| #define PLAYER_XSIZE 0.05f |
| #define PLAYER_YSIZE 0.15f |
| |
| // Ball size (units) |
| #define BALL_SIZE 0.02f |
| |
| // Maximum player movement speed (units / second) |
| #define MAX_SPEED 1.5f |
| |
| // Player movement acceleration (units / seconds^2) |
| #define ACCELERATION 4.0f |
| |
| // Player movement deceleration (units / seconds^2) |
| #define DECELERATION 2.0f |
| |
| // Ball movement speed (units / second) |
| #define BALL_SPEED 0.4f |
| |
| // Menu options |
| #define MENU_NONE 0 |
| #define MENU_PLAY 1 |
| #define MENU_QUIT 2 |
| |
| // Game events |
| #define NOBODY_WINS 0 |
| #define PLAYER1_WINS 1 |
| #define PLAYER2_WINS 2 |
| |
| // Winner ID |
| #define NOBODY 0 |
| #define PLAYER1 1 |
| #define PLAYER2 2 |
| |
| // Camera positions |
| #define CAMERA_CLASSIC 0 |
| #define CAMERA_ABOVE 1 |
| #define CAMERA_SPECTATOR 2 |
| #define CAMERA_DEFAULT CAMERA_CLASSIC |
| |
| |
| //======================================================================== |
| // Textures |
| //======================================================================== |
| |
| #define TEX_TITLE 0 |
| #define TEX_MENU 1 |
| #define TEX_INSTR 2 |
| #define TEX_WINNER1 3 |
| #define TEX_WINNER2 4 |
| #define TEX_FIELD 5 |
| #define NUM_TEXTURES 6 |
| |
| // Texture names |
| char * tex_name[ NUM_TEXTURES ] = { |
| "pong3d_title.tga", |
| "pong3d_menu.tga", |
| "pong3d_instr.tga", |
| "pong3d_winner1.tga", |
| "pong3d_winner2.tga", |
| "pong3d_field.tga" |
| }; |
| |
| // OpenGL texture object IDs |
| GLuint tex_id[ NUM_TEXTURES ]; |
| |
| |
| //======================================================================== |
| // Global variables |
| //======================================================================== |
| |
| // Display information |
| int width, height; |
| |
| // Frame information |
| double thistime, oldtime, dt, starttime; |
| |
| // Camera information |
| int camerapos; |
| |
| // Player information |
| struct { |
| double ypos; // -1.0 to +1.0 |
| double yspeed; // -MAX_SPEED to +MAX_SPEED |
| } player1, player2; |
| |
| // Ball information |
| struct { |
| double xpos, ypos; |
| double xspeed, yspeed; |
| } ball; |
| |
| // And the winner is... |
| int winner; |
| |
| // Lighting configuration |
| const GLfloat env_ambient[4] = {1.0f,1.0f,1.0f,1.0f}; |
| const GLfloat light1_position[4] = {-3.0f,3.0f,2.0f,1.0f}; |
| const GLfloat light1_diffuse[4] = {1.0f,1.0f,1.0f,0.0f}; |
| const GLfloat light1_ambient[4] = {0.0f,0.0f,0.0f,0.0f}; |
| |
| // Object material properties |
| const GLfloat player1_diffuse[4] = {1.0f,0.3f,0.3f,1.0f}; |
| const GLfloat player1_ambient[4] = {0.3f,0.1f,0.0f,1.0f}; |
| const GLfloat player2_diffuse[4] = {0.3f,1.0f,0.3f,1.0f}; |
| const GLfloat player2_ambient[4] = {0.1f,0.3f,0.1f,1.0f}; |
| const GLfloat ball_diffuse[4] = {1.0f,1.0f,0.5f,1.0f}; |
| const GLfloat ball_ambient[4] = {0.3f,0.3f,0.1f,1.0f}; |
| const GLfloat border_diffuse[4] = {0.3f,0.3f,1.0f,1.0f}; |
| const GLfloat border_ambient[4] = {0.1f,0.1f,0.3f,1.0f}; |
| const GLfloat floor_diffuse[4] = {1.0f,1.0f,1.0f,1.0f}; |
| const GLfloat floor_ambient[4] = {0.3f,0.3f,0.3f,1.0f}; |
| |
| |
| //======================================================================== |
| // LoadTextures() - Load textures from disk and upload to OpenGL card |
| //======================================================================== |
| |
| GLboolean LoadTextures( void ) |
| { |
| int i; |
| |
| // Generate texture objects |
| glGenTextures( NUM_TEXTURES, tex_id ); |
| |
| // Load textures |
| for( i = 0; i < NUM_TEXTURES; i ++ ) |
| { |
| // Select texture object |
| glBindTexture( GL_TEXTURE_2D, tex_id[ i ] ); |
| |
| // Set texture parameters |
| glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); |
| glTexParameteri( 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 ); |
| |
| // Upload texture from file to texture memory |
| if( !glfwLoadTexture2D( tex_name[ i ], 0 ) ) |
| { |
| fprintf( stderr, "Failed to load texture %s\n", tex_name[ i ] ); |
| return GL_FALSE; |
| } |
| } |
| |
| return GL_TRUE; |
| } |
| |
| |
| //======================================================================== |
| // DrawImage() - Draw a 2D image as a texture |
| //======================================================================== |
| |
| void DrawImage( int texnum, float x1, float x2, float y1, float y2 ) |
| { |
| glEnable( GL_TEXTURE_2D ); |
| glBindTexture( GL_TEXTURE_2D, tex_id[ texnum ] ); |
| glBegin( GL_QUADS ); |
| glTexCoord2f( 0.0f, 1.0f ); |
| glVertex2f( x1, y1 ); |
| glTexCoord2f( 1.0f, 1.0f ); |
| glVertex2f( x2, y1 ); |
| glTexCoord2f( 1.0f, 0.0f ); |
| glVertex2f( x2, y2 ); |
| glTexCoord2f( 0.0f, 0.0f ); |
| glVertex2f( x1, y2 ); |
| glEnd(); |
| glDisable( GL_TEXTURE_2D ); |
| } |
| |
| |
| //======================================================================== |
| // GameMenu() - Game menu (returns menu option) |
| //======================================================================== |
| |
| int GameMenu( void ) |
| { |
| int option; |
| |
| // Enable sticky keys |
| glfwEnable( GLFW_STICKY_KEYS ); |
| |
| // Wait for a game menu key to be pressed |
| do |
| { |
| // Get window size |
| glfwGetWindowSize( &width, &height ); |
| |
| // Set viewport |
| glViewport( 0, 0, width, height ); |
| |
| // Clear display |
| glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); |
| glClear( GL_COLOR_BUFFER_BIT ); |
| |
| // Setup projection matrix |
| glMatrixMode( GL_PROJECTION ); |
| glLoadIdentity(); |
| glOrtho( 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f ); |
| |
| // Setup modelview matrix |
| glMatrixMode( GL_MODELVIEW ); |
| glLoadIdentity(); |
| |
| // Display title |
| glColor3f( 1.0f, 1.0f, 1.0f ); |
| DrawImage( TEX_TITLE, 0.1f, 0.9f, 0.0f, 0.3f ); |
| |
| // Display menu |
| glColor3f( 1.0f, 1.0f, 0.0f ); |
| DrawImage( TEX_MENU, 0.38f, 0.62f, 0.35f, 0.5f ); |
| |
| // Display instructions |
| glColor3f( 0.0f, 1.0f, 1.0f ); |
| DrawImage( TEX_INSTR, 0.32f, 0.68f, 0.65f, 0.85f ); |
| |
| // Swap buffers |
| glfwSwapBuffers(); |
| |
| // Check for keys |
| if( glfwGetKey( 'Q' ) || !glfwGetWindowParam( GLFW_OPENED ) ) |
| { |
| option = MENU_QUIT; |
| } |
| else if( glfwGetKey( GLFW_KEY_F1 ) ) |
| { |
| option = MENU_PLAY; |
| } |
| else |
| { |
| option = MENU_NONE; |
| } |
| |
| // To avoid horrible busy waiting, sleep for at least 20 ms |
| glfwSleep( 0.02 ); |
| } |
| while( option == MENU_NONE ); |
| |
| // Disable sticky keys |
| glfwDisable( GLFW_STICKY_KEYS ); |
| |
| return option; |
| } |
| |
| |
| //======================================================================== |
| // NewGame() - Initialize a new game |
| //======================================================================== |
| |
| void NewGame( void ) |
| { |
| // Frame information |
| starttime = thistime = glfwGetTime(); |
| |
| // Camera information |
| camerapos = CAMERA_DEFAULT; |
| |
| // Player 1 information |
| player1.ypos = 0.0; |
| player1.yspeed = 0.0; |
| |
| // Player 2 information |
| player2.ypos = 0.0; |
| player2.yspeed = 0.0; |
| |
| // Ball information |
| ball.xpos = -1.0 + PLAYER_XSIZE; |
| ball.ypos = player1.ypos; |
| ball.xspeed = 1.0; |
| ball.yspeed = 1.0; |
| } |
| |
| |
| //======================================================================== |
| // PlayerControl() - Player control |
| //======================================================================== |
| |
| void PlayerControl( void ) |
| { |
| float joy1pos[ 2 ], joy2pos[ 2 ]; |
| |
| // Get joystick X & Y axis positions |
| glfwGetJoystickPos( GLFW_JOYSTICK_1, joy1pos, 2 ); |
| glfwGetJoystickPos( GLFW_JOYSTICK_2, joy2pos, 2 ); |
| |
| // Player 1 control |
| if( glfwGetKey( 'A' ) || joy1pos[ 1 ] > 0.2f ) |
| { |
| player1.yspeed += dt * ACCELERATION; |
| if( player1.yspeed > MAX_SPEED ) |
| { |
| player1.yspeed = MAX_SPEED; |
| } |
| } |
| else if( glfwGetKey( 'Z' ) || joy1pos[ 1 ] < -0.2f ) |
| { |
| player1.yspeed -= dt * ACCELERATION; |
| if( player1.yspeed < -MAX_SPEED ) |
| { |
| player1.yspeed = -MAX_SPEED; |
| } |
| } |
| else |
| { |
| player1.yspeed /= exp( DECELERATION * dt ); |
| } |
| |
| // Player 2 control |
| if( glfwGetKey( 'K' ) || joy2pos[ 1 ] > 0.2f ) |
| { |
| player2.yspeed += dt * ACCELERATION; |
| if( player2.yspeed > MAX_SPEED ) |
| { |
| player2.yspeed = MAX_SPEED; |
| } |
| } |
| else if( glfwGetKey( 'M' ) || joy2pos[ 1 ] < -0.2f ) |
| { |
| player2.yspeed -= dt * ACCELERATION; |
| if( player2.yspeed < -MAX_SPEED ) |
| { |
| player2.yspeed = -MAX_SPEED; |
| } |
| } |
| else |
| { |
| player2.yspeed /= exp( DECELERATION * dt ); |
| } |
| |
| // Update player 1 position |
| player1.ypos += dt * player1.yspeed; |
| if( player1.ypos > 1.0 - PLAYER_YSIZE ) |
| { |
| player1.ypos = 1.0 - PLAYER_YSIZE; |
| player1.yspeed = 0.0; |
| } |
| else if( player1.ypos < -1.0 + PLAYER_YSIZE ) |
| { |
| player1.ypos = -1.0 + PLAYER_YSIZE; |
| player1.yspeed = 0.0; |
| } |
| |
| // Update player 2 position |
| player2.ypos += dt * player2.yspeed; |
| if( player2.ypos > 1.0 - PLAYER_YSIZE ) |
| { |
| player2.ypos = 1.0 - PLAYER_YSIZE; |
| player2.yspeed = 0.0; |
| } |
| else if( player2.ypos < -1.0 + PLAYER_YSIZE ) |
| { |
| player2.ypos = -1.0 + PLAYER_YSIZE; |
| player2.yspeed = 0.0; |
| } |
| } |
| |
| |
| //======================================================================== |
| // BallControl() - Ball control |
| //======================================================================== |
| |
| int BallControl( void ) |
| { |
| int event; |
| double ballspeed; |
| |
| // Calculate new ball speed |
| ballspeed = BALL_SPEED * (1.0 + 0.02*(thistime-starttime)); |
| ball.xspeed = ball.xspeed > 0 ? ballspeed : -ballspeed; |
| ball.yspeed = ball.yspeed > 0 ? ballspeed : -ballspeed; |
| ball.yspeed *= 0.74321; |
| |
| // Update ball position |
| ball.xpos += dt * ball.xspeed; |
| ball.ypos += dt * ball.yspeed; |
| |
| // Did the ball hit a top/bottom wall? |
| if( ball.ypos >= 1.0 ) |
| { |
| ball.ypos = 2.0 - ball.ypos; |
| ball.yspeed = -ball.yspeed; |
| } |
| else if( ball.ypos <= -1.0 ) |
| { |
| ball.ypos = -2.0 - ball.ypos; |
| ball.yspeed = -ball.yspeed; |
| } |
| |
| // Did the ball hit/miss a player? |
| event = NOBODY_WINS; |
| |
| // Is the ball entering the player 1 goal? |
| if( ball.xpos < -1.0 + PLAYER_XSIZE ) |
| { |
| // Did player 1 catch the ball? |
| if( ball.ypos > (player1.ypos-PLAYER_YSIZE) && |
| ball.ypos < (player1.ypos+PLAYER_YSIZE) ) |
| { |
| ball.xpos = -2.0 + 2.0*PLAYER_XSIZE - ball.xpos; |
| ball.xspeed = -ball.xspeed; |
| } |
| else |
| { |
| event = PLAYER2_WINS; |
| } |
| } |
| |
| // Is the ball entering the player 2 goal? |
| if( ball.xpos > 1.0 - PLAYER_XSIZE ) |
| { |
| // Did player 2 catch the ball? |
| if( ball.ypos > (player2.ypos-PLAYER_YSIZE) && |
| ball.ypos < (player2.ypos+PLAYER_YSIZE) ) |
| { |
| ball.xpos = 2.0 - 2.0*PLAYER_XSIZE - ball.xpos; |
| ball.xspeed = -ball.xspeed; |
| } |
| else |
| { |
| event = PLAYER1_WINS; |
| } |
| } |
| |
| return event; |
| } |
| |
| |
| //======================================================================== |
| // DrawBox() - Draw a 3D box |
| //======================================================================== |
| |
| #define TEX_SCALE 4.0f |
| |
| |
| void DrawBox( float x1, float y1, float z1, float x2, float y2, float z2 ) |
| { |
| // Draw six sides of a cube |
| glBegin( GL_QUADS ); |
| // Side 1 (down) |
| glNormal3f( 0.0f, 0.0f, -1.0f ); |
| glTexCoord2f( 0.0f, 0.0f ); |
| glVertex3f( x1,y2,z1 ); |
| glTexCoord2f( TEX_SCALE, 0.0f ); |
| glVertex3f( x2,y2,z1 ); |
| glTexCoord2f( TEX_SCALE, TEX_SCALE ); |
| glVertex3f( x2,y1,z1 ); |
| glTexCoord2f( 0.0f, TEX_SCALE ); |
| glVertex3f( x1,y1,z1 ); |
| // Side 2 (up) |
| glNormal3f( 0.0f, 0.0f, 1.0f ); |
| glTexCoord2f( 0.0f, 0.0f ); |
| glVertex3f( x1,y1,z2 ); |
| glTexCoord2f( TEX_SCALE, 0.0f ); |
| glVertex3f( x2,y1,z2 ); |
| glTexCoord2f( TEX_SCALE, TEX_SCALE ); |
| glVertex3f( x2,y2,z2 ); |
| glTexCoord2f( 0.0f, TEX_SCALE ); |
| glVertex3f( x1,y2,z2 ); |
| // Side 3 (backward) |
| glNormal3f( 0.0f, -1.0f, 0.0f ); |
| glTexCoord2f( 0.0f, 0.0f ); |
| glVertex3f( x1,y1,z1 ); |
| glTexCoord2f( TEX_SCALE, 0.0f ); |
| glVertex3f( x2,y1,z1 ); |
| glTexCoord2f( TEX_SCALE, TEX_SCALE ); |
| glVertex3f( x2,y1,z2 ); |
| glTexCoord2f( 0.0f, TEX_SCALE ); |
| glVertex3f( x1,y1,z2 ); |
| // Side 4 (forward) |
| glNormal3f( 0.0f, 1.0f, 0.0f ); |
| glTexCoord2f( 0.0f, 0.0f ); |
| glVertex3f( x1,y2,z2 ); |
| glTexCoord2f( TEX_SCALE, 0.0f ); |
| glVertex3f( x2,y2,z2 ); |
| glTexCoord2f( TEX_SCALE, TEX_SCALE ); |
| glVertex3f( x2,y2,z1 ); |
| glTexCoord2f( 0.0f, TEX_SCALE ); |
| glVertex3f( x1,y2,z1 ); |
| // Side 5 (left) |
| glNormal3f( -1.0f, 0.0f, 0.0f ); |
| glTexCoord2f( 0.0f, 0.0f ); |
| glVertex3f( x1,y1,z2 ); |
| glTexCoord2f( TEX_SCALE, 0.0f ); |
| glVertex3f( x1,y2,z2 ); |
| glTexCoord2f( TEX_SCALE, TEX_SCALE ); |
| glVertex3f( x1,y2,z1 ); |
| glTexCoord2f( 0.0f, TEX_SCALE ); |
| glVertex3f( x1,y1,z1 ); |
| // Side 6 (right) |
| glNormal3f( 1.0f, 0.0f, 0.0f ); |
| glTexCoord2f( 0.0f, 0.0f ); |
| glVertex3f( x2,y1,z1 ); |
| glTexCoord2f( TEX_SCALE, 0.0f ); |
| glVertex3f( x2,y2,z1 ); |
| glTexCoord2f( TEX_SCALE, TEX_SCALE ); |
| glVertex3f( x2,y2,z2 ); |
| glTexCoord2f( 0.0f, TEX_SCALE ); |
| glVertex3f( x2,y1,z2 ); |
| glEnd(); |
| } |
| |
| |
| //======================================================================== |
| // UpdateDisplay() - Draw graphics (all game related OpenGL stuff goes |
| // here) |
| //======================================================================== |
| |
| void UpdateDisplay( void ) |
| { |
| // Get window size |
| glfwGetWindowSize( &width, &height ); |
| |
| // Set viewport |
| glViewport( 0, 0, width, height ); |
| |
| // Clear display |
| glClearColor( 0.02f, 0.02f, 0.02f, 0.0f ); |
| glClearDepth( 1.0f ); |
| glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); |
| |
| // Setup projection matrix |
| glMatrixMode( GL_PROJECTION ); |
| glLoadIdentity(); |
| gluPerspective( |
| 55.0f, // Angle of view |
| (GLfloat)width/(GLfloat)height, // Aspect |
| 1.0f, // Near Z |
| 100.0f // Far Z |
| ); |
| |
| // Setup modelview matrix |
| glMatrixMode( GL_MODELVIEW ); |
| glLoadIdentity(); |
| switch( camerapos ) |
| { |
| default: |
| case CAMERA_CLASSIC: |
| gluLookAt( |
| 0.0f, 0.0f, 2.5f, |
| 0.0f, 0.0f, 0.0f, |
| 0.0f, 1.0f, 0.0f |
| ); |
| break; |
| case CAMERA_ABOVE: |
| gluLookAt( |
| 0.0f, 0.0f, 2.5f, |
| (float)ball.xpos, (float)ball.ypos, 0.0f, |
| 0.0f, 1.0f, 0.0f |
| ); |
| break; |
| case CAMERA_SPECTATOR: |
| gluLookAt( |
| 0.0f, -2.0, 1.2f, |
| (float)ball.xpos, (float)ball.ypos, 0.0f, |
| 0.0f, 0.0f, 1.0f |
| ); |
| break; |
| } |
| |
| // Enable depth testing |
| glEnable( GL_DEPTH_TEST ); |
| glDepthFunc( GL_LEQUAL ); |
| |
| // Enable lighting |
| glEnable( GL_LIGHTING ); |
| glLightModelfv( GL_LIGHT_MODEL_AMBIENT, env_ambient ); |
| glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE ); |
| glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE ); |
| glLightfv( GL_LIGHT1, GL_POSITION, light1_position ); |
| glLightfv( GL_LIGHT1, GL_DIFFUSE, light1_diffuse ); |
| glLightfv( GL_LIGHT1, GL_AMBIENT, light1_ambient ); |
| glEnable( GL_LIGHT1 ); |
| |
| // Front face is counter-clock-wise |
| glFrontFace( GL_CCW ); |
| |
| // Enable face culling (not necessary, but speeds up rendering) |
| glCullFace( GL_BACK ); |
| glEnable( GL_CULL_FACE ); |
| |
| // Draw Player 1 |
| glMaterialfv( GL_FRONT, GL_DIFFUSE, player1_diffuse ); |
| glMaterialfv( GL_FRONT, GL_AMBIENT, player1_ambient ); |
| DrawBox( -1.f, (GLfloat)player1.ypos-PLAYER_YSIZE, 0.f, |
| -1.f+PLAYER_XSIZE, (GLfloat)player1.ypos+PLAYER_YSIZE, 0.1f ); |
| |
| // Draw Player 2 |
| glMaterialfv( GL_FRONT, GL_DIFFUSE, player2_diffuse ); |
| glMaterialfv( GL_FRONT, GL_AMBIENT, player2_ambient ); |
| DrawBox( 1.f-PLAYER_XSIZE, (GLfloat)player2.ypos-PLAYER_YSIZE, 0.f, |
| 1.f, (GLfloat)player2.ypos+PLAYER_YSIZE, 0.1f ); |
| |
| // Draw Ball |
| glMaterialfv( GL_FRONT, GL_DIFFUSE, ball_diffuse ); |
| glMaterialfv( GL_FRONT, GL_AMBIENT, ball_ambient ); |
| DrawBox( (GLfloat)ball.xpos-BALL_SIZE, (GLfloat)ball.ypos-BALL_SIZE, 0.f, |
| (GLfloat)ball.xpos+BALL_SIZE, (GLfloat)ball.ypos+BALL_SIZE, BALL_SIZE*2 ); |
| |
| // Top game field border |
| glMaterialfv( GL_FRONT, GL_DIFFUSE, border_diffuse ); |
| glMaterialfv( GL_FRONT, GL_AMBIENT, border_ambient ); |
| DrawBox( -1.1f, 1.0f, 0.0f, 1.1f, 1.1f, 0.1f ); |
| // Bottom game field border |
| glColor3f( 0.0f, 0.0f, 0.7f ); |
| DrawBox( -1.1f, -1.1f, 0.0f, 1.1f, -1.0f, 0.1f ); |
| // Left game field border |
| DrawBox( -1.1f, -1.0f, 0.0f, -1.0f, 1.0f, 0.1f ); |
| // Left game field border |
| DrawBox( 1.0f, -1.0f, 0.0f, 1.1f, 1.0f, 0.1f ); |
| |
| // Enable texturing |
| glEnable( GL_TEXTURE_2D ); |
| glBindTexture( GL_TEXTURE_2D, tex_id[ TEX_FIELD ] ); |
| |
| // Game field floor |
| glMaterialfv( GL_FRONT, GL_DIFFUSE, floor_diffuse ); |
| glMaterialfv( GL_FRONT, GL_AMBIENT, floor_ambient ); |
| DrawBox( -1.01f, -1.01f, -0.01f, 1.01f, 1.01f, 0.0f ); |
| |
| // Disable texturing |
| glDisable( GL_TEXTURE_2D ); |
| |
| // Disable face culling |
| glDisable( GL_CULL_FACE ); |
| |
| // Disable lighting |
| glDisable( GL_LIGHTING ); |
| |
| // Disable depth testing |
| glDisable( GL_DEPTH_TEST ); |
| } |
| |
| |
| //======================================================================== |
| // GameOver() |
| //======================================================================== |
| |
| void GameOver( void ) |
| { |
| // Enable sticky keys |
| glfwEnable( GLFW_STICKY_KEYS ); |
| |
| // Until the user presses ESC or SPACE |
| while( !glfwGetKey( GLFW_KEY_ESC ) && !glfwGetKey( ' ' ) && |
| glfwGetWindowParam( GLFW_OPENED ) ) |
| { |
| // Draw display |
| UpdateDisplay(); |
| |
| // Setup projection matrix |
| glMatrixMode( GL_PROJECTION ); |
| glLoadIdentity(); |
| glOrtho( 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f ); |
| |
| // Setup modelview matrix |
| glMatrixMode( GL_MODELVIEW ); |
| glLoadIdentity(); |
| |
| // Enable blending |
| glEnable( GL_BLEND ); |
| |
| // Dim background |
| glBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA ); |
| glColor4f( 0.3f, 0.3f, 0.3f, 0.3f ); |
| glBegin( GL_QUADS ); |
| glVertex2f( 0.0f, 0.0f ); |
| glVertex2f( 1.0f, 0.0f ); |
| glVertex2f( 1.0f, 1.0f ); |
| glVertex2f( 0.0f, 1.0f ); |
| glEnd(); |
| |
| // Display winner text |
| glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_COLOR ); |
| if( winner == PLAYER1 ) |
| { |
| glColor4f( 1.0f, 0.5f, 0.5f, 1.0f ); |
| DrawImage( TEX_WINNER1, 0.35f, 0.65f, 0.46f, 0.54f ); |
| } |
| else if( winner == PLAYER2 ) |
| { |
| glColor4f( 0.5f, 1.0f, 0.5f, 1.0f ); |
| DrawImage( TEX_WINNER2, 0.35f, 0.65f, 0.46f, 0.54f ); |
| } |
| |
| // Disable blending |
| glDisable( GL_BLEND ); |
| |
| // Swap buffers |
| glfwSwapBuffers(); |
| } |
| |
| // Disable sticky keys |
| glfwDisable( GLFW_STICKY_KEYS ); |
| } |
| |
| |
| //======================================================================== |
| // GameLoop() - Game loop |
| //======================================================================== |
| |
| void GameLoop( void ) |
| { |
| int playing, event; |
| |
| // Initialize a new game |
| NewGame(); |
| |
| // Enable sticky keys |
| glfwEnable( GLFW_STICKY_KEYS ); |
| |
| // Loop until the game ends |
| playing = GL_TRUE; |
| while( playing && glfwGetWindowParam( GLFW_OPENED ) ) |
| { |
| // Frame timer |
| oldtime = thistime; |
| thistime = glfwGetTime(); |
| dt = thistime - oldtime; |
| |
| // Get user input and update player positions |
| PlayerControl(); |
| |
| // Move the ball, and check if a player hits/misses the ball |
| event = BallControl(); |
| |
| // Did we have a winner? |
| switch( event ) |
| { |
| case PLAYER1_WINS: |
| winner = PLAYER1; |
| playing = GL_FALSE; |
| break; |
| case PLAYER2_WINS: |
| winner = PLAYER2; |
| playing = GL_FALSE; |
| break; |
| default: |
| break; |
| } |
| |
| // Did the user press ESC? |
| if( glfwGetKey( GLFW_KEY_ESC ) ) |
| { |
| playing = GL_FALSE; |
| } |
| |
| // Did the user change camera view? |
| if( glfwGetKey( '1' ) ) |
| { |
| camerapos = CAMERA_CLASSIC; |
| } |
| else if( glfwGetKey( '2' ) ) |
| { |
| camerapos = CAMERA_ABOVE; |
| } |
| else if( glfwGetKey( '3' ) ) |
| { |
| camerapos = CAMERA_SPECTATOR; |
| } |
| |
| // Draw display |
| UpdateDisplay(); |
| |
| // Swap buffers |
| glfwSwapBuffers(); |
| } |
| |
| // Disable sticky keys |
| glfwDisable( GLFW_STICKY_KEYS ); |
| |
| // Show winner |
| GameOver(); |
| } |
| |
| |
| //======================================================================== |
| // main() - Program entry point |
| //======================================================================== |
| |
| int main( void ) |
| { |
| int menuoption; |
| |
| // Initialize GLFW |
| if( !glfwInit() ) |
| { |
| fprintf( stderr, "Failed to initialize GLFW\n" ); |
| exit( EXIT_FAILURE ); |
| } |
| |
| // Open OpenGL window |
| if( !glfwOpenWindow( WIDTH, HEIGHT, 0,0,0,0, 16,0, GLFW_FULLSCREEN ) ) |
| { |
| fprintf( stderr, "Failed to open GLFW window\n" ); |
| glfwTerminate(); |
| exit( EXIT_FAILURE ); |
| } |
| |
| glfwSwapInterval( 1 ); |
| |
| // Load all textures |
| if( !LoadTextures() ) |
| { |
| glfwTerminate(); |
| exit( EXIT_FAILURE ); |
| } |
| |
| // Main loop |
| do |
| { |
| // Get menu option |
| menuoption = GameMenu(); |
| |
| // If the user wants to play, let him... |
| if( menuoption == MENU_PLAY ) |
| { |
| GameLoop(); |
| } |
| } |
| while( menuoption != MENU_QUIT ); |
| |
| // Unload all textures |
| if( glfwGetWindowParam( GLFW_OPENED ) ) |
| { |
| glDeleteTextures( NUM_TEXTURES, tex_id ); |
| } |
| |
| // Terminate GLFW |
| glfwTerminate(); |
| |
| exit( EXIT_SUCCESS ); |
| } |
| |