Skip to content

Instantly share code, notes, and snippets.

@dlivingstone
Created July 6, 2012 22:18

Revisions

  1. dlivingstone created this gist Jul 6, 2012.
    196 changes: 196 additions & 0 deletions main.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,196 @@
    // 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
    }