//----------------------------------------------------------------------------- // name: AudioClimber.cpp // desc: step sequencer // // author: Matthew Pick (mpick@stanford.edu) // date: fall 2014 // uses: RtAudio by Gary Scavone //----------------------------------------------------------------------------- //#include "RtAudio.h" #include #include #include #include "chuck_fft.h" #include "RtAudio.h" #include "Squirrel.h" #include #include #include #include #include #include #include #include "Enemy.h" #include "ShootMeter.h" #include "Acorn.h" using namespace std; #ifdef __MACOSX_CORE__ #include #include #include #else #include #include #include #endif #define STARTING_TEMPO 1000 const float MIN_AMP_FOR_PLATFORM = 0.00001; const double INCREASE_CAMERA_POINTS = 1; const double WIN_GAME_POINTS = 500; const float CAMERA_THRESHOLD = 0; const float HIGHEST_POSITION = 11; GLuint squirrelTex; Squirrel *squirrel; GLuint backgroundTex; GLuint deadSquirrelTex; GLuint restInPeaceTex; GLuint vineTex; GLuint enemyTex; GLuint deadEnemyTex; GLuint youWinTex; GLuint acornTex; GLuint acornExplodedTex; GLuint bambooTex; GLuint frameTex; typedef struct { float topLeftX; float topLeftY; float width; float height; float alpha; } platform; typedef struct { float windowLow; float windowHigh; } FreqWindow; vector platforms; queue freqWindowQueue; vector enemies; vector acorns; float lastAmplitude = 0; ShootMeter *shootMeter; int g_score = 0; int g_high_score = 10; //----------------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------------- void initGfx(); void idleFunc(); void displayFunc(); void reshapeFunc( GLsizei width, GLsizei height ); void keyboardFunc( unsigned char, int, int ); void mouseFunc( int button, int state, int x, int y ); // our datetype #define SAMPLE float // corresponding format for RtAudio #define MY_FORMAT RTAUDIO_FLOAT32 // sample rate #define MY_SRATE 44100 // number of channels #define MY_CHANNELS 2 // for convenience #define MY_PIE 3.14159265358979 // width and height long g_width = 2880; long g_height = 1800; SAMPLE * g_buffer = NULL; long g_bufferSize; SAMPLE * g_windowBuf = NULL; #define MAX_VALID_FREQ_WINDOW_COUNTER 5 int g_validFreqWindowCount = -1; bool startGame = true; float g_CameraPosition = 0; //float g_CameraPosition = 11; //----------------------------------------------------------------------------- // name: callme() // desc: audio callback //----------------------------------------------------------------------------- int callme( void * outputBuffer, void * inputBuffer, unsigned int numFrames, double streamTime, RtAudioStreamStatus status, void * data ) { // cast! SAMPLE * input = (SAMPLE *)inputBuffer; SAMPLE * output = (SAMPLE *)outputBuffer; // fill for( int i = 0; i < numFrames; i++ ) { // assume mono g_buffer[i] = input[i]; // if (g_playSoundCounter != -1) { // output[i] = g_playSound[g_playSoundCounter]; // g_playSoundCounter += 1; // // if (g_playSoundCounter >= g_bufferSize){ // g_playSoundCounter = -1; // output[i] = 0; // } // } // else { // zero output output[i] = 0; // } } return 0; } void writeInstructions(){ cout << endl<< "Welcome to DropBeat!" << endl << endl << "------------------------------------------------------" << endl << endl << "Control Keys:" << endl << endl << "Number Keys 1-9: change the instrument by selecting from the color boxes" << endl << endl << "+: increases the tempo of the falling notes" << endl << "-: decreases the tempo fo the falling notes" << endl << "0: Resets the tempo" << endl << endl << "tab: switches between Play and Shoot Modes" << endl << "left and right arrow keys: moves the laser that explodes notes" << endl << "space bar: explodes notes when in Shoot Mode" << endl << endl << "t: switches tracks" << endl << "n: create a new tab" << endl << "Shift + Number Keys 1-9: toggles between silencing and activating an existing track" << endl; } const int INCREASE_SOUND = 1; const int DECREASE_SOUND = 2; void fillQueue(){ FreqWindow prev; int soundDirection = -1; for (int i=0; i<100; i++){ // 25% chance we start new sequence if ( i == 0 || rand() % 4 == 1 || prev.windowLow < 10*pow(10, -3) ){ soundDirection = -1; cout << "new val" << endl; // high can be between 1*10^-4 and 1*10^-2 int num = rand() % 100; int num2 = rand() % 100; while (num <= num2 || num-num2 < 20 || num-num2 == num || num-num2 > 30 || num2 < 20){ num = rand() % 100; num2 = rand() % 100; } float scaleFactor = 1.5; FreqWindow w; w.windowHigh = num*pow(10, -3)*scaleFactor; w.windowLow = num2*pow(10, -3)*scaleFactor; freqWindowQueue.push(w); prev = w; //cout << "High: " << w.windowHigh << ", num: " << num << ", num2: " << num2 << ", Low: " << w.windowLow << endl; } else { if (soundDirection == -1){ cout << "changing direction" << endl; soundDirection = rand() % 2; } int nextValDif = rand() % 100; float delta = (nextValDif/10.0)*pow(10, -3); FreqWindow w; if (soundDirection == INCREASE_SOUND){ w.windowHigh = prev.windowHigh+delta; w.windowLow = prev.windowLow+delta; } else { w.windowHigh = prev.windowHigh-delta; w.windowLow = prev.windowLow-delta; } cout << "D: " << delta << ", H: " << w.windowHigh << ", L: " << w.windowLow << endl; freqWindowQueue.push(w); prev = w; } } cout << endl << endl << endl; } void loadHighScore(){ ifstream file ("high_score.txt"); if (file.is_open()){ string line; getline(file, line); file.close(); g_high_score = atoi(line.c_str()); } else { g_high_score = 0; } } void saveHighScore(){ ofstream file ("high_score.txt"); if (file.is_open()){ file << to_string(g_high_score) << "\n"; file.close(); } else { cerr << "Unable to open file"; } } //----------------------------------------------------------------------------- // name: main() // desc: entry point //----------------------------------------------------------------------------- int main( int argc, char ** argv ) { loadHighScore(); fillQueue(); writeInstructions(); // instantiate RtAudio object RtAudio audio; // variables unsigned int bufferBytes = 0; // frame size unsigned int bufferFrames = 1024; // check for audio devices if( audio.getDeviceCount() < 1 ) { // nopes cout << "no audio devices found!" << endl; exit( 1 ); } // initialize GLUT glutInit( &argc, argv ); // init gfx initGfx(); // let RtAudio print messages to stderr. audio.showWarnings( true ); // set input and output parameters RtAudio::StreamParameters iParams, oParams; iParams.deviceId = audio.getDefaultInputDevice(); iParams.nChannels = MY_CHANNELS; iParams.firstChannel = 0; oParams.deviceId = audio.getDefaultOutputDevice(); oParams.nChannels = MY_CHANNELS; oParams.firstChannel = 0; // create stream options RtAudio::StreamOptions options; // go for it try { // open a stream audio.openStream( &oParams, &iParams, MY_FORMAT, MY_SRATE, &bufferFrames, &callme, (void *)&bufferBytes, &options ); } catch( RtError& e ) { // error! cout << e.getMessage() << endl; exit( 1 ); } // compute bufferBytes = bufferFrames * MY_CHANNELS * sizeof(SAMPLE); // allocate global buffer g_bufferSize = bufferFrames; g_buffer = new SAMPLE[g_bufferSize]; memset( g_buffer, 0, sizeof(SAMPLE)*g_bufferSize ); g_windowBuf = new SAMPLE[g_bufferSize]; hanning(g_windowBuf, g_bufferSize); // go for it try { // start stream audio.startStream(); // let GLUT handle the current thread from here glutMainLoop(); // stop the stream. audio.stopStream(); } catch( RtError& e ) { // print error message cout << e.getMessage() << endl; goto cleanup; } cleanup: // close if open if( audio.isStreamOpen() ) audio.closeStream(); delete squirrel; delete g_buffer; delete g_windowBuf; glDeleteTextures( 1, &squirrelTex ); glDeleteTextures( 1, &deadSquirrelTex ); glDeleteTextures( 1, &backgroundTex ); glDeleteTextures( 1, &restInPeaceTex ); for (int enemy = 0; enemy < enemies.size(); enemy++){ delete enemies[enemy]; } for (int acorn = 0; acorn < acorns.size(); acorn++){ delete acorns[acorn]; } delete shootMeter; // done return 0; } void SpecialKeyCallback(int key, int x, int y) { switch(key) { case GLUT_KEY_UP: //do something here break; case GLUT_KEY_DOWN: //do something here break; case GLUT_KEY_LEFT: break; case GLUT_KEY_RIGHT: break; } } GLuint LoadBitmap(const char* FilePath) { int width = 0; int height = 0; short BitsPerPixel = 0; std::vector Pixels; std::fstream hFile(FilePath, std::ios::in | std::ios::binary); if (!hFile.is_open()) throw std::invalid_argument("Error: File Not Found."); hFile.seekg(0, std::ios::end); int Length = hFile.tellg(); hFile.seekg(0, std::ios::beg); std::vector FileInfo(Length); hFile.read(reinterpret_cast(FileInfo.data()), 54); if (FileInfo[0] != 'B' && FileInfo[1] != 'M') { hFile.close(); throw std::invalid_argument("Error: Invalid File Format. Bitmap Required."); } if (FileInfo[28] != 24 && FileInfo[28] != 32) { hFile.close(); throw std::invalid_argument("Error: Invalid File Format. 24 or 32 bit Image Required."); } BitsPerPixel = FileInfo[28]; width = FileInfo[18] + (FileInfo[19] << 8); height = FileInfo[22] + (FileInfo[23] << 8); std::uint32_t PixelsOffset = FileInfo[10] + (FileInfo[11] << 8); std::uint32_t size = ((width * BitsPerPixel + 31) / 32) * 4 * height; Pixels.resize(size); hFile.seekg(PixelsOffset, std::ios::beg); hFile.read(reinterpret_cast(Pixels.data()), size); hFile.close(); GLuint image; glGenTextures(1, &image); glBindTexture(GL_TEXTURE_2D, image); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, Pixels.data()); return image; } //----------------------------------------------------------------------------- // Name: reshapeFunc( ) // Desc: called when window size changes //----------------------------------------------------------------------------- void initGfx() { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // initialize the window size glutInitWindowSize( g_width, g_height ); // // set the window postion // glutInitWindowPosition( 100, 100 ); // create the window glutCreateWindow( "AudioClimber by Matthew Pick" ); // set the idle function - called when idle glutIdleFunc( idleFunc ); // set the display function - called when redrawing glutDisplayFunc( displayFunc ); // set the reshape function - called when client area changes glutKeyboardFunc( keyboardFunc ); // set the mouse function - called on mouse stuff glutMouseFunc( mouseFunc ); glutSpecialFunc( SpecialKeyCallback ); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable( GL_BLEND ); // set clear color glClearColor( 1, 1, 1, 1 ); squirrelTex = LoadBitmap("textures/squirrel.bmp"); deadSquirrelTex = LoadBitmap("textures/deadSquirrel.bmp"); backgroundTex = LoadBitmap("textures/background.bmp"); restInPeaceTex = LoadBitmap("textures/restInPeaceText.bmp"); vineTex = LoadBitmap("textures/vine.bmp"); enemyTex = LoadBitmap("textures/flyingTurtle.bmp"); deadEnemyTex = LoadBitmap("textures/deadTurtle.bmp"); youWinTex = LoadBitmap("textures/youWin.bmp"); acornTex = LoadBitmap("textures/acorn.bmp"); acornExplodedTex = LoadBitmap("textures/acornExploded.bmp"); bambooTex = LoadBitmap("textures/bamboo.bmp"); frameTex = LoadBitmap("textures/frame.bmp"); } void generateEnemies(){ float spacing = 1.5; for (int i=0; i<7; i++){ int direction = rand() % 2; if (i == 0) enemies.push_back( new Enemy(0, spacing/2, enemyTex, deadEnemyTex, direction+1) ); else enemies.push_back( new Enemy(0, spacing*i+spacing/2, enemyTex, deadEnemyTex, direction+1) ); } } //----------------------------------------------------------------------------- // Name: reshapeFunc( ) // Desc: called when window size changes //----------------------------------------------------------------------------- void reshapeFunc( GLsizei w, GLsizei h ) { // save the new window size g_width = w; g_height = h; // map the view port to the client area glViewport( 0, 0, w, h ); // set the matrix mode to project glMatrixMode( GL_PROJECTION ); // load the identity matrix glLoadIdentity( ); // create the viewing frustum gluPerspective( 45.0, (GLfloat) w / (GLfloat) h, 1.0, 300.0 ); // set the matrix mode to modelview glMatrixMode( GL_MODELVIEW ); // load the identity matrix glLoadIdentity( ); // position the view point gluLookAt( 0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f ); } //----------------------------------------------------------------------------- // Name: keyboardFunc( ) // Desc: key event //----------------------------------------------------------------------------- void keyboardFunc( unsigned char key, int x, int y ) { switch( key ) { case 'Q': case 'q': exit(1); break; case '0': break; case 's': startGame = true; break; case 13: // reset game if ( (squirrel && squirrel->isDead()) || (squirrel && squirrel->centerY-squirrel->Y_RADIUS >= HIGHEST_POSITION) ) { delete squirrel; squirrel = NULL; fillQueue(); enemies.clear(); generateEnemies(); g_CameraPosition = 0; g_score = 0; glClearColor( 1, 1, 1, 1 ); } break; } glutPostRedisplay( ); } //----------------------------------------------------------------------------- // Name: mouseFunc( ) // Desc: handles mouse stuff //----------------------------------------------------------------------------- void mouseFunc( int button, int state, int x, int y ) { if( button == GLUT_LEFT_BUTTON ) { } else if ( button == GLUT_RIGHT_BUTTON ) { // when right mouse button down if( state == GLUT_DOWN ) { } else { } } else { } glutPostRedisplay( ); } void drawSquare(float topLeftX, float topLeftY, float height, float width){ // glDisable(GL_TEXTURE_2D); // glEnable(GL_ALPHA_TEST); // glColor4f(1, 0, 0, alpha); glPushMatrix(); glBegin(GL_QUADS); glTexCoord2d(0,1); glVertex2f(topLeftX, topLeftY); glTexCoord2d(1,1); glVertex2f(topLeftX+width, topLeftY); glTexCoord2d(1,0); glVertex2f(topLeftX+width, topLeftY-height); glTexCoord2d(0,0); glVertex2f(topLeftX, topLeftY-height); glEnd(); glPopMatrix(); } //----------------------------------------------------------------------------- // Name: idleFunc( ) // Desc: callback from GLUT //----------------------------------------------------------------------------- void idleFunc( ) { // render the scene glutPostRedisplay( ); } void drawWord(string word, float x, float y, float z){ glPushMatrix(); glRasterPos3f(x, y, z); for (int i=0; i highestFreq) highestFreq = freq; } return highestFreq; } bool inFreqWindow(){ if (!freqWindowQueue.empty()){ float highestFreq = getHighestFreq(); // float highestFreq = -1; // // for(int i = 0; i < g_bufferSize; i+=2){ // float freq = g_buffer[i]; // if (freq > highestFreq) highestFreq = freq; // } // cout << "queue high: " << freqWindowQueue.front().windowHigh << ", highest freq: " << highestFreq << ", queue lowest: " << freqWindowQueue.front().windowLow << endl; if ( highestFreq > freqWindowQueue.front().windowLow && highestFreq < freqWindowQueue.front().windowHigh ){ g_validFreqWindowCount = 0; return true; } return false; } return false; } void determineIfShouldDrawPlatform(){ // rfft(g_buffer, g_bufferSize/2, FFT_FORWARD); // float avgAmp = getAvgAmplitude(); if ( inFreqWindow() ){ // if (avgAmp > MIN_AMP_FOR_PLATFORM){ bool drawPlatform = squirrel->bounce(); if ( drawPlatform && !squirrel->isDead() ){ squirrel->start(); platform p; p.topLeftX = squirrel->centerX-.1; p.topLeftY = squirrel->centerY-.1; p.width = .2; p.height = .05; p.alpha = 1; platforms.push_back(p); freqWindowQueue.pop(); if (freqWindowQueue.empty()){ fillQueue(); } } } } void drawWave(){ // glColor4f(1, 1, 1, .5); // drawSquare(-.95, .8, .8, .5); apply_window(g_buffer, g_windowBuf, g_bufferSize); GLfloat xStart = -.95; GLfloat x = -.95; int waveScaleFactor = 3; glLineWidth(2); glBegin( GL_LINE_STRIP ); if (g_validFreqWindowCount != -1 && g_validFreqWindowCount < MAX_VALID_FREQ_WINDOW_COUNTER){ glColor4f(0, 1, 0, 1); g_validFreqWindowCount++; } else { glColor4f(1, 0, 0, 1); g_validFreqWindowCount = -1; } // loop over buffer for( int i = 0; i < g_bufferSize; i+=2 ) { // plot float yVal = g_buffer[i]*waveScaleFactor; if (g_buffer[i]*waveScaleFactor < 0) yVal = 0; glVertex2f( x, yVal); // increment x x += .0013; } // end primitive glEnd(); glLineWidth(3); // draw high and low bars glColor4f(0, 0, 1, 1); glBegin(GL_LINE_STRIP); glVertex2f(xStart, freqWindowQueue.front().windowHigh*waveScaleFactor); glVertex2f(x, freqWindowQueue.front().windowHigh*waveScaleFactor); glEnd(); glColor4f(0, 0, 1, 1); glBegin(GL_LINE_STRIP); glVertex2f(xStart, freqWindowQueue.front().windowLow*waveScaleFactor); glVertex2f(x, freqWindowQueue.front().windowLow*waveScaleFactor); glEnd(); //draws wave and shoot meter if (!shootMeter) shootMeter = new ShootMeter(-.95, 0); if ( shootMeter->draw( getHighestFreq(), x ) ){ //fire acorn!!!! cout << "shoot" << endl; acorns.push_back(new Acorn(squirrel->centerX, squirrel->centerY, acornTex, acornExplodedTex)); } } void drawBackground(){ glColor4f(1,1,1,1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, backgroundTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); drawSquare(-.55, 12, 13, .53+.55); glDisable(GL_TEXTURE_2D); } void drawLeftBackground(){ glColor4f(1,1,1,1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, bambooTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); drawSquare(-1, 1, 2, 1); glDisable(GL_TEXTURE_2D); } void drawSides(){ // glDisable(GL_TEXTURE_2D); // glEnable(GL_ALPHA_TEST); // glColor4f(1, 0, 0, 1); // // drawSquare(-.4-.075, 1, 2, .075); // drawSquare(.4, 1, 2, .075); glColor4f(1,1,1,1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, vineTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); drawSquare(-.55-.075, 1, 2, .075); drawSquare(.53, 1, 2, .075); glDisable(GL_TEXTURE_2D); } void checkToMoveCamera(){ // squirrel is too high so move to middle if (squirrel->centerY+squirrel->Y_RADIUS-g_CameraPosition >= 1){ g_score += (int)(((squirrel->centerY+squirrel->Y_RADIUS-g_CameraPosition - 1)/.01)*INCREASE_CAMERA_POINTS); g_CameraPosition += squirrel->centerY+squirrel->Y_RADIUS-g_CameraPosition - 1+.01; } else if (squirrel->goingUp() && squirrel->centerY-g_CameraPosition > CAMERA_THRESHOLD){ g_CameraPosition += .01; g_score += INCREASE_CAMERA_POINTS; } if (g_CameraPosition > HIGHEST_POSITION){ g_CameraPosition = HIGHEST_POSITION; } } void drawRestInPeaceText(){ glColor4f(1,1,1,1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, restInPeaceTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); drawSquare(-.925, .3, .6, .65); glDisable(GL_TEXTURE_2D); glClearColor( 20/255.0, 20/255.0, 20/255.0, 1 ); saveHighScore(); } void drawYouWinText(){ glColor4f(1,1,1,1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, youWinTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); drawSquare(-.95, .8, 1.5, .65); glDisable(GL_TEXTURE_2D); saveHighScore(); } void drawEnemiesAndCheckForCollisions(){ for (int enemyCounter = 0; enemyCounter < enemies.size(); enemyCounter++){ Enemy *enemy = enemies[enemyCounter]; enemy->draw(g_CameraPosition); enemy->checkForSquirrelCollision(squirrel, g_CameraPosition, &g_score); for (int acornCounter = 0; acornCounter < acorns.size(); acornCounter++){ Acorn *acorn = acorns[acornCounter]; enemy->checkForAcornCollision(acorn, g_CameraPosition, &g_score); } } } void filterBuf(){ for (int i=0; i::iterator it = acorns.begin(); cout << acorns.size() << endl; // draws good acorns and cleans out bad ones while (it != acorns.end()) { Acorn *acorn = (*it); if ( acorn->isDead() ) { delete acorn; it = acorns.erase(it); } else { acorn->draw(); if (acorn->centerY-acorn->Y_RADIUS-g_CameraPosition >= 1 ) acorn->dead = true; ++it; } } // for (int i=0; i < acorns.size(); i++){ // Acorn *acorn = acorns[i]; // acorn->draw(); // } } void drawScore(string word, float x, float y){ // glColor4f(1,1,1,1); // // glEnable(GL_TEXTURE_2D); // glBindTexture(GL_TEXTURE_2D, frameTex); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // // drawSquare(-1, 1, .7, .8); // glDisable(GL_TEXTURE_2D); if (g_high_score < g_score) g_high_score = g_score; glPushMatrix(); glColor4f(1, 1, 1, 1); glRasterPos2f(x, y); for (int i=0; iisDead()) drawRestInPeaceText(); else if (squirrel && squirrel->centerY-squirrel->Y_RADIUS >= HIGHEST_POSITION) drawYouWinText(); else{ filterBuf(); drawLeftBackground(); drawWave(); //drawShootMeter(); } glPushMatrix(); glTranslatef(.4, 0, 0); drawSides(); glPushMatrix(); glTranslatef(0, -g_CameraPosition, 0); drawBackground(); // glTranslatef(0, translateDownVal, 0); drawPlatforms(); if (startGame){ if (!squirrel) squirrel = new Squirrel(0, -.5, squirrelTex, deadSquirrelTex); // if (!squirrel) squirrel = new Squirrel(0, 11, squirrelTex, deadSquirrelTex); if (enemies.empty()) generateEnemies(); determineIfShouldDrawPlatform(); squirrel->draw(); drawAcorns(); drawEnemiesAndCheckForCollisions(); } glPopMatrix(); glPopMatrix(); if ( !squirrel->isDead() ) checkToMoveCamera(); if ( squirrel->centerY+squirrel->Y_RADIUS-g_CameraPosition < -.9 ){ squirrel->squirrelDied(); } drawScore("Score: "+to_string(g_score), -.67, .8); // flush! glFlush( ); // swap the double buffer glutSwapBuffers( ); }