Skip to content

Instantly share code, notes, and snippets.

@dlivingstone
Created July 6, 2012 22:18
Show Gist options
  • Save dlivingstone/3063071 to your computer and use it in GitHub Desktop.
Save dlivingstone/3063071 to your computer and use it in GitHub Desktop.
OpenGL demo project: A project that needs lots of fixing and restructuring
// main.cpp
// A very basic OpenGL/GLUT application using the deprecated OpenGL 1.x
// (c) Daniel Livingstone, 2012
// The structure of this program is typical of many simple OpenGL demonstration
// programs, but is unsuitable for larger projects: The very basic structure
// is useful when learning OpenGL, but very poor for building large, complex
// systems such as modern games
// In this 'game' the player has to move (using w,s,a,d keys) and resize (using
// arrow keys) a white cursor to surround a red target as tightly as possible.
// When the player succeeds, the red target will be randomly resized and positioned
// Many to-do's in this project:
// - Seperate update from keyboard and render functions
// - - Fix keyboard to recognise multiple key presses
// - Use timers to provide better control over frame-rate
// - - Try GLUT timers first
// - - Then frame limiter
// - - Then independent physics/render loop
// - Introduce game-state, with main menu and 'game' and pause screens
#define FREEGLUT_STATIC
#include <GL/freeglut.h>
// C stdlib and C time libraries for rand and time functions
#include <cstdlib>
#include <ctime>
// iostream for cin and cout
#include <iostream>
// stringstream and string
#include <sstream>
#include <string>
float xpos = 0.0f;
float ypos = 0.0f;
float xsize = 0.25f;
float ysize = 0.25f;
float targetXPos = 0.0f;
float targetYPos = 0.0f;
float targetXSize = 0.0f;
float targetYSize = 0.0f;
int score = 0;
clock_t lastTime; // clock_t is an integer type
clock_t currentTime; // use this to trace time between frames
void displayString(float x, float y, void* font, const char *str)
{
glRasterPos2f(x, y);
while (*str != NULL)
glutBitmapCharacter(font, *str++);
}
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0); // set background colour
std::srand( std::time(NULL) );
targetXPos = (float)rand()/RAND_MAX - 0.75f;
targetYPos = (float)rand()/RAND_MAX - 0.75f;
targetXSize = 0.19f;
targetYSize= 0.19f;
lastTime = clock();
}
void render(void) {
glClear(GL_COLOR_BUFFER_BIT); // Clear all pixels
// drawing code goes in here!
// draw player
glColor3f(1.0,1.0,1.0);
glBegin(GL_POLYGON);
glVertex3f (xpos, ypos, 0.0); // first corner
glVertex3f (xpos+xsize, ypos, 0.0); // second corner
glVertex3f (xpos+xsize, ypos+ysize, 0.0); // third corner
glVertex3f (xpos, ypos+ysize, 0.0); // fourth corner
glEnd();
displayString(xpos+(xsize/2.0f), ypos+ysize, GLUT_BITMAP_TIMES_ROMAN_10, "Player");
// draw target
glColor3f(1.0,0.0,0.0);
glBegin(GL_POLYGON);
glVertex3f (targetXPos, targetYPos, 0.0); // first corner
glVertex3f (targetXPos+targetXSize, targetYPos, 0.0); // second corner
glVertex3f (targetXPos+targetXSize, targetYPos+targetYSize, 0.0); // third corner
glVertex3f (targetXPos, targetYPos+targetYSize, 0.0); // fourth corner
glEnd();
displayString(targetXPos+(targetXSize/2.0f), targetYPos+targetYSize, GLUT_BITMAP_TIMES_ROMAN_10, "Target");
if ( (targetXPos >= xpos) && (targetXPos+targetXSize <= xpos+xsize) // cursor surrounds target in x
&& (targetYPos >= ypos) && (targetYPos+targetYSize <= ypos+ysize) // cursor surrounds target in y
&& ( xsize <= targetXSize+0.1f) && ( ysize <= targetYSize+0.1f) ) // cursor only slightly larger than target
{
// congrats, player has scored!
score += 100;
std::cout << "Score: " << score << std::endl;
// randomize target
targetXPos = (float)rand()/RAND_MAX - 0.75f;
targetYPos = (float)rand()/RAND_MAX - 0.75f;
targetXSize = (float)rand()/RAND_MAX * 0.8f;
targetYSize= (float)rand()/RAND_MAX * 0.8f;
}
// Calculate ms/frame
// Some OpenGL drivers will limit the frames to 60fps (16.66 ms/frame)
// If so, expect to see the time to rapidly switch between 16 and 17...
glColor3f(1.0,1.0,1.0);
currentTime = clock();
// On some systems, CLOCKS_PER_SECOND is 1000, which makes the arithmetic below redundant
// - but this is not necessarily the case on all systems
float milliSecondsPerFrame = ((currentTime - lastTime)/(float)CLOCKS_PER_SEC*1000);
// Print out the score and frame time information
std::stringstream strStream;
strStream << "Score:" << score;
strStream << " ms/frame: " << milliSecondsPerFrame;
displayString(-0.9,0.9, GLUT_BITMAP_9_BY_15, strStream.str().c_str());
lastTime = clock();
glutSwapBuffers(); // Redraw (double buffered)
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'w':
case 'W':
ypos += 0.05;
break;
case 's':
case 'S':
ypos -= 0.05;
break;
case 'a':
case 'A':
xpos -= 0.05;
break;
case 'd':
case 'D':
xpos += 0.05;
break;
}
glutPostRedisplay();
}
void specialKeys(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_UP:
ysize += 0.05;
break;
case GLUT_KEY_DOWN:
ysize -= 0.05;
break;
case GLUT_KEY_LEFT:
xsize -= 0.05;
break;
case GLUT_KEY_RIGHT:
xsize += 0.05;
break;
}
glutPostRedisplay();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400 );
glutInitDisplayMode(GLUT_DOUBLE);
glutCreateWindow("Demo Project");
init();
glutDisplayFunc(render); // Register the render callack
glutKeyboardFunc(keyboard); // Setup keyboard callback
glutSpecialFunc(specialKeys); // Setup special keys callback
glutIdleFunc(render); // Set idle callback to the render function
glutMainLoop(); // loop while waiting for messages
// by default, window will respond
// to resize, move and close events
return 0; // return 0 indicates program exited OK
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment