/**************************************************************************//** * @author Paul Blasi, Caitlin Taggart * * @par Description: * Main execution point of the app. Initializes the window and prepares the * main objects to be drawn on the screen. Also sets up the callback events. * * @returns Execution outcome. * *****************************************************************************/ int main(int argc, char *argv[]) { //set up the window glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT); glutInitWindowPosition(100, 100); glutCreateWindow("Pong"); glClearColor(0.0, 0.0, 0.0, 1.0); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //specify callbacks glutDisplayFunc(Display); glutReshapeFunc(Reshape); glutKeyboardFunc(Keyboard); glutKeyboardUpFunc(KeyboardUp); glutSpecialFunc(SpecialKeys); glutSpecialUpFunc(SpecialKeysUp); glutTimerFunc(30, Animate, 1); //TODO set up players and ball BALL = Ball(Point(100, 50),5, WHITE); LEFT_PLAYER = Paddle(Point(10, 50), 10, 40, WHITE); RIGHT_PLAYER = Paddle(Point(190, 50), 10, 40, WHITE); NET = Net(Point(100, 50), VERTICAL, WHITE, 98); TOP_WALL = Wall(Point(100, 99), HORIZONTAL, WHITE, 198); BOTTOM_WALL = Wall(Point(100, 1), HORIZONTAL, WHITE, 198); LEFT_WALL = Wall(Point(1, 50), VERTICAL, WHITE, 98); RIGHT_WALL = Wall(Point(199, 50), VERTICAL, WHITE, 98); COLLISION_MAN.RegisterCollision(&BALL, &LEFT_PLAYER, BallCollideWithLeftPaddle); COLLISION_MAN.RegisterCollision(&BALL, &RIGHT_PLAYER, BallCollideWithRightPaddle); COLLISION_MAN.RegisterCollision(&BALL, &TOP_WALL, BallCollideWithWall); COLLISION_MAN.RegisterCollision(&BALL, &BOTTOM_WALL, BallCollideWithWall); COLLISION_MAN.RegisterCollision(&BALL, &LEFT_WALL, Score); COLLISION_MAN.RegisterCollision(&BALL, &RIGHT_WALL, Score); COLLISION_MAN.RegisterCollision(&LEFT_PLAYER, &TOP_WALL, LeftCollideWithWall); COLLISION_MAN.RegisterCollision(&LEFT_PLAYER, &BOTTOM_WALL, LeftCollideWithWall); COLLISION_MAN.RegisterCollision(&LEFT_PLAYER, &LEFT_WALL, LeftCollideWithWall); COLLISION_MAN.RegisterCollision(&LEFT_PLAYER, &NET, LeftCollideWithWall); COLLISION_MAN.RegisterCollision(&RIGHT_PLAYER, &TOP_WALL, RightCollideWithWall); COLLISION_MAN.RegisterCollision(&RIGHT_PLAYER, &BOTTOM_WALL, RightCollideWithWall); COLLISION_MAN.RegisterCollision(&RIGHT_PLAYER, &RIGHT_WALL, RightCollideWithWall); COLLISION_MAN.RegisterCollision(&RIGHT_PLAYER, &NET, RightCollideWithWall); glutMainLoop(); return 0; }
Player::Player(sf::Keyboard::Key keyUp, sf::Keyboard::Key keyDown, sf::Color color, Side side): keyUp(keyUp), keyDown(keyDown), paddle() { float paddleX = 10.0f; float paddleY = (float) HEIGHT / 2.0f; float paddleWidth = 20.0f; float paddleHeight = 150.0f; if (side == Side::RIGHT) { paddleX = (float) WIDTH - paddleX - paddleWidth; } paddleY -= paddleHeight / 2.0f; paddle = Paddle(paddleX, paddleY, paddleWidth, paddleHeight, color); }
/**************************************************************************//** * @author Paul Blasi, Caitlin Taggart * * @par Description: * The display callback. Draws each of the objects and displays score for each * player. If the game is currently paused, it also draws a translucent box * over the play area and the text "Paused". * *****************************************************************************/ void Display(void) { int length; glClear(GL_COLOR_BUFFER_BIT); BALL.Draw(); LEFT_PLAYER.Draw(); RIGHT_PLAYER.Draw(); LEFT_WALL.Draw(); RIGHT_WALL.Draw(); TOP_WALL.Draw(); BOTTOM_WALL.Draw(); NET.Draw(); string right_score = to_string(RIGHT_PLAYER.Score); string left_score = to_string(LEFT_PLAYER.Score); glColor4fv(WHITE); length = glutBitmapLength(GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)left_score.c_str()); glRasterPos2i(50 - (200.0 / SCREEN_WIDTH * length / 2.0), 90); glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)left_score.c_str()); length = glutBitmapLength(GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)right_score.c_str()); glRasterPos2i(150 - (200.0 / SCREEN_WIDTH * length / 2.0), 90); glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)right_score.c_str()); if (PAUSED) { float alphaBlack[4] = { 0.0, 0.0, 0.0, .60 }; Paddle temp; temp = Paddle(Point(100, 50), 200, 100, alphaBlack); temp.Draw(); glColor4fv(WHITE); length = glutBitmapLength(GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)"PAUSED"); glRasterPos2i(100 - (200.0/SCREEN_WIDTH * length / 2.0), 50); glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, (const unsigned char*)"PAUSED"); } //glFlush(); glutSwapBuffers(); }
version 2.1 of the License, or (at your option) any later version. */ #include <stdlib.h> #include <string.h> #include <inttypes.h> #include "Paddle.h" Paddle::Paddle(uint8_t button, uint8_t potentiometer) { } void Paddle::init(uint8_t button, uint8_t potentiometer) { } uint8_t Paddle::buttonPressed(void) { return 0; } int Paddle::getPosition(void) { return 0; } // Preinstantiate default Paddle objects // I need to think about whether this is the right thing to do. Anyone using the // controllers library will have the pins configured automatically. Paddle PaddleA = Paddle(0, 3); Paddle PaddleB = Paddle(1, 2);
GameLogic::GameLogic(int Width, int Height, float LogicFPS) { Debug = false; Display = NULL; EventQueue = NULL; Timer = NULL; Bitmap.Logo = NULL; Bitmap.Title = NULL; Font.Small = NULL; Font.Medium = NULL; Font.Big = NULL; Sound.HitWall = NULL; Sound.HitPaddle = NULL; Sound.BackgroundMusic = NULL; UserDataFile = NULL; DisplayWidth = Width; DisplayHeight = Height; TimerStep = 1.0 / LogicFPS; bool key[2] = { false, false }; float alpha = 0; float colr = 0; float colg = 0; float colb = 0; int tick = 0; int menu = 0; int high_score = 0; bool restart = true; int score = 0, multi = 1, final_score = 1; bool game_over, redraw; char scoretxt[8] = ""; char multitxt[4] = ""; char final_scoretxt[16] = ""; char hightxt[16] = ""; // intro screen while (1) { ALLEGRO_EVENT ev; al_wait_for_event(EventQueue, &ev); if(ev.type == ALLEGRO_EVENT_TIMER) { // trigger redraw tick++; if(tick < 180) { colr = colg = colb = (0.5 * sin( (tick - 90) * ALLEGRO_PI / 180.0) + 0.5); alpha = 0; } else if(tick < 360) { alpha = (0.5 * sin( (tick + 90) * ALLEGRO_PI / 180.0) + 0.5); colr = colg = colb = 1; } else if(tick > 450 && tick < 630) { colr = colg = colb = alpha = (0.5 * cos( (tick - 90) * ALLEGRO_PI / 180.0) + 0.5); } else if(tick > 632) { break; } redraw = true; } else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { return; } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { break; } if(redraw && al_is_event_queue_empty(EventQueue)) { redraw = false; al_clear_to_color(al_map_rgb_f(colr,colg,colb)); al_draw_tinted_bitmap(Bitmap.Logo, al_map_rgba_f(alpha, alpha, alpha, alpha), (DisplayWidth - al_get_bitmap_width(Bitmap.Logo) ) / 2, (DisplayHeight - al_get_bitmap_height(Bitmap.Logo) )/ 2, 0); al_flip_display(); } } al_flip_display(); al_clear_to_color(al_map_rgb(0,0,0)); // load hiscore info UserDataFile = al_fopen("assets/hiscore.txt", "r"); if(UserDataFile) { char *line = (char*) malloc (17); line = al_fgets(UserDataFile, line, 17); high_score = atoi(line); free(line); } else { high_score = 0; } final_score = 0; sprintf(hightxt, "High: %d", high_score); al_fclose(UserDataFile); // main menu loop while (1) { ALLEGRO_EVENT ev; al_wait_for_event(EventQueue, &ev); if(ev.type == ALLEGRO_EVENT_TIMER) { // trigger redraw redraw = true; } else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { // exit if the Display is closed return; } else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) { // track mouse movement if((ev.mouse.y > 350) && (ev.mouse.y < 388) && (ev.mouse.x > 250) && (ev.mouse.x < 388)) { menu = 1; } else { menu = 0; } } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { // track mouse clicks if(menu == 1) { break; } } if(redraw && al_is_event_queue_empty(EventQueue)) { // process entire queue and only render if the Timer has ticked redraw = false; al_clear_to_color(al_map_rgb(0,0,0)); al_draw_bitmap(Bitmap.Title, (DisplayWidth - al_get_bitmap_width(Bitmap.Title) ) / 2, 16, 0); al_draw_text(Font.Small, al_map_rgb(128,128,0), DisplayWidth / 2, 250, ALLEGRO_ALIGN_CENTRE, "Version 0.1"); if(menu == 1) { al_draw_text(Font.Medium, al_map_rgb(128,0,0), DisplayWidth / 2, 350, ALLEGRO_ALIGN_CENTRE, "Play Now!"); } else { al_draw_text(Font.Medium, al_map_rgb(128,128,0), DisplayWidth / 2, 350, ALLEGRO_ALIGN_CENTRE, "Play Now!"); } al_flip_display(); } } // seed rand function srand(al_get_time()); // game wrapper lets us restart the game while(restart) { // hide the cursor //al_hide_mouse_cursor(Display); // assume we don't want to play again restart = false; // Base objects Ball StarterBall = Ball(); Paddle StarterPaddle = Paddle(0); Paddle StarterPaddle2 = Paddle(DisplayHeight - 8); Paddle StarterPaddle3 = Paddle(0, true); Paddle StarterPaddle4 = Paddle(DisplayWidth - 8, true); // TODO: load the right map // set Bitmap.Title // set base speed // create list of block entities // Populate entity lists // Remove static data when we get map loading done for(int i=0; i < 64; i++) { Brick SingleBlockyEntity = Brick((i % 16) * 40, 80 + ( (i / 16) * 10), i % 8); Bricks.push_back(SingleBlockyEntity); } Paddles.push_back(StarterPaddle); Paddles.push_back(StarterPaddle2); Paddles.push_back(StarterPaddle3); Paddles.push_back(StarterPaddle4); Balls.push_back(StarterBall); // save high score if the final score is higher if(final_score > high_score) { high_score = final_score; sprintf (hightxt, "High: %d", high_score); } // reset score if not a continuation // init hud // force initial draw redraw = true; // reset physics game_over = false; // main game loop while(1) { ALLEGRO_EVENT ev; al_wait_for_event(EventQueue, &ev); if(ev.type == ALLEGRO_EVENT_TIMER) { // game logic loop if(!game_over) { // calculate each ball's new position and check for... Path CurrentPath; for(int i = 0; i < Balls.size(); i++) { CurrentPath = Balls[i].GetPath(TimerStep); // distance traveled in axis directions in time delta t float NX = Balls[i].Position.DeltaX * TimerStep; float NY = Balls[i].Position.DeltaY * TimerStep; // new unencombered position float NewPositionX = Balls[i].Position.X + NX; float NewPositionY = Balls[i].Position.Y + NY; ClosestEntity Closest; Closest.Magnitude = 10000; // look for collisions for(int j = 0; j < (int)Bricks.size(); j++) { // only check items that haven't been hit in the most recent update if (!Bricks[j].HasBeenHit()) { Intersection Point = Bricks[j].PathIntersect(CurrentPath); if (Point.Type == Intersecting) { // mark this hit so we don't check for it again... // until the next update frame. Bricks[i].Hit = true; // see how far the collision is float Magnitude = sqrt(pow(Point.X - Balls[i].Position.X, 2) + pow(Point.Y - Balls[i].Position.Y, 2)); if (Magnitude < Closest.Magnitude) { // nab the closest collision so we can handle multiple collisions Closest.Magnitude = Magnitude; Closest.EntityIndex = j; Closest.CollisionPoint = Point; } } } } if (Closest.CollisionPoint.Type == Intersecting) { if(Bricks[Closest.EntityIndex].Harm(Balls[i].CollisionDamage)) { // TODO: play a sound // Update the ball to the point of collision Balls[i].Position.X = Closest.CollisionPoint.X; Balls[i].Position.Y = Closest.CollisionPoint.Y; // Reflect the ball in the appropriate direction switch(Closest.CollisionPoint.From) { default: case Top: case Bottom: Balls[i].ReflectY(); break; case Left: case Right: Balls[i].ReflectX(); break; } /* Find the fraction of DeltaT that had to occur before this collision float UnknownT = TimerStep * (Closest.Magnitude / sqrt(pow(NX,2) + pow(NY, 2))); // simlulate the ball movement after the collision Balls[i].GetPath(TimerStep - UnknownT); break;*/ } if(NewPositionX > 0.0f && NewPositionX < DisplayWidth - Balls[i].Width && NewPositionY > 0.0f && NewPositionY < DisplayHeight - Balls[i].Height) { Balls[i].Live = true; Balls[i].Position.X = NewPositionX; Balls[i].Position.Y = NewPositionY; } else { Balls[i].Live = false; } } // make sure at least one ball is in play if(Balls[0].BallCount < 1) { game_over = true; } } } else { // end game animation logic } // trigger a render every tick redraw = true; } else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { break; } else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY) { if(!game_over) { // update each paddle for(int i = 0; i < Paddles.size(); i++) { // horizontal clip if(Paddles[i].IsHorizontal()) { if(ev.mouse.x < (Paddles[i].Width / 2) ) { Paddles[i].Position.X = 0; } else if(ev.mouse.x > DisplayWidth - (Paddles[i].Width / 2) ) { Paddles[i].Position.X = DisplayWidth - Paddles[i].Width; } else { Paddles[i].Position.X = ev.mouse.x - (Paddles[i].Width / 2); } } else { // vertical clip if(ev.mouse.y < (Paddles[i].Height / 2) ) { Paddles[i].Position.Y = 0; } else if(ev.mouse.y > DisplayHeight - (Paddles[i].Height / 2) ) { Paddles[i].Position.Y = DisplayHeight - Paddles[i].Height; } else { Paddles[i].Position.Y = ev.mouse.y - (Paddles[i].Height / 2); } } } } else { // track mouse movement for retry menu logic } } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { if(game_over) { // track mouse clicks for retry menu logic } else { // Debug // add a ball at the current mouse position } } else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) { // set keys we are interested in if pressed switch(ev.keyboard.keycode) { case ALLEGRO_KEY_ESCAPE: key[KEY_ESC] = true; break; case ALLEGRO_KEY_SPACE: key[KEY_SPACE] = true; break; } } else if(ev.type == ALLEGRO_EVENT_KEY_UP) { // release keys we are interested in if let go switch(ev.keyboard.keycode) { case ALLEGRO_KEY_ESCAPE: key[KEY_ESC] = false; break; case ALLEGRO_KEY_SPACE: key[KEY_SPACE] = false; break; } } if(redraw && al_is_event_queue_empty(EventQueue)) { //The render loop redraw = false; if(!game_over) { // game play // blank al_clear_to_color(al_map_rgb(128,128,128)); // render each brick for(int i = 0; i < Bricks.size(); i++) { Bricks[i].Render(); } // render each ball for(int i = 0; i < Balls.size(); i++) { Balls[i].Render(); } // render each paddle for(int i = 0; i < Paddles.size(); i++) { Paddles[i].Render(); } // render HUD sprintf (scoretxt, "%d", score); sprintf (multitxt, "%d", multi); al_draw_text(Font.Medium, al_map_rgb(0,0,0), 8, 8, ALLEGRO_ALIGN_LEFT, "Score"); al_draw_text(Font.Medium, al_map_rgb(255,255,255), 128, 8, ALLEGRO_ALIGN_LEFT, scoretxt); al_draw_text(Font.Medium, al_map_rgb(0,0,0), 300, 8, ALLEGRO_ALIGN_LEFT, "x"); al_draw_text(Font.Medium, al_map_rgb(255,255,255), 316, 8, ALLEGRO_ALIGN_LEFT, multitxt); al_draw_text(Font.Medium, al_map_rgb(0,0,0), 424, 8, ALLEGRO_ALIGN_LEFT, hightxt); } else { // render retry menu al_clear_to_color(al_map_rgb(128,128,128)); } // always flip Display al_flip_display(); } } } // save high score if the final score is higher if(final_score > high_score) { high_score = final_score; } sprintf (hightxt, "%d", high_score); // write highscore to file UserDataFile = al_fopen("assets/hiscore.txt", "w"); if(UserDataFile) { al_fputs(UserDataFile, hightxt); al_fclose(UserDataFile); } // proper cleanup is important! al_destroy_bitmap(Bitmap.Title); al_destroy_bitmap(Bitmap.Logo); al_destroy_timer(Timer); al_destroy_display(Display); al_destroy_event_queue(EventQueue); }
int main() { //GAME SETUP sf::RenderWindow window(sf::VideoMode(gDisplayx,gDisplayy), "PONG - Obrecht"); window.setFramerateLimit(60); // Initialize the Menu Menu menu( window.getSize().x, window.getSize().y ); bool menuBool = true; //Boolean to clear Menu Options options( window.getSize().x, window.getSize().y ); bool optionsBool = false; bool computerAIBool = false; bool playertwoBool = true; //default behavior // Initialize Score Score score( window.getSize().x, window.getSize().y ); ScoreWindow scorewindow( window.getSize().x, window.getSize().y ); sf::Time elapsed; bool scoreBool = true; // Initialize the TableMap sf::Color PongTableColor = sf::Color(4,27,90); TableMap tablemap( window.getSize().x, window.getSize().y ); // Initialize the Paddles - Two Players Paddle Paddles("Player 1","Player 2"); // AI Paddle - One Player Paddle Paddle("Player 1"); // Initialize the Ball Ball ball; ball.loadsound(); //Initialize Gameover Screen int winningscore = 5; Gameover gameover( window.getSize().x, window.getSize().y ); gameover.loadsound(); sf::Time elapsedGameOver; bool gameoverBool = false; while( window.isOpen() ) { sf::Event event; while( window.pollEvent(event) ) { if( event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape) ) { window.close(); } // Handling Menu Options: if( menuBool ) { if( sf::Keyboard::isKeyPressed( sf::Keyboard::Up ) ) { menu.MoveUp(); } else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Down ) ) { menu.MoveDown(); } else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Return ) ) { switch( menu.getPressedItem() ) { case 0: menuBool = false; break; case 1: menuBool = false; optionsBool = true; break; case 2: window.close(); break; } } } if( optionsBool ) { if( sf::Keyboard::isKeyPressed( sf::Keyboard::Up ) ) { options.MoveUp(); } else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Down ) ) { options.MoveDown(); } else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Return ) ) { switch( options.getPressedItem() ) { case 1: computerAIBool = true; playertwoBool = false; break; case 2: playertwoBool = true; break; case 3: optionsBool = false; menuBool = true; break; } } } if( gameoverBool ) { if( sf::Keyboard::isKeyPressed( sf::Keyboard::Space )) { menuBool = true; optionsBool = false; ball.setRightScore(0); ball.setLeftScore(0); ball.ballupdate(); gameoverBool = false; } } } //DRAWING - Layers of draw commands, i.e. first is layer one // Menu at beginning of game if( menuBool && !optionsBool) { window.clear(); window.draw(menu); } // If Options is pushed if( optionsBool ) { window.clear(); window.draw(options); } if( !menuBool && !optionsBool ) { // Table Lines window.clear(PongTableColor); window.draw(tablemap); // Score window.draw(score); // Paddles if( playertwoBool ) { window.draw(Paddles); Paddles.movePaddle(); } // Computer AI if( computerAIBool ){ } // Ball window.draw(ball); ball.update(&Paddles); // Score Keeper if(ball.didLeftPaddleScore() || ball.didRightPaddleScore() ) { sf::Clock scoreClock; //reset clock each time window.clear(); scorewindow.updateScore( ball.getLeftScore(), ball.getRightScore() ); window.draw(scorewindow); elapsed+=scoreClock.getElapsedTime(); if( elapsed.asSeconds() >= 0.009 ) { ball.setLeftBool(false); ball.setRightBool(false); elapsed-=elapsed; ball.ballupdate(); } scoreClock.restart(); } // Clean up / Updates score.updateScore( ball.getLeftScore(), ball.getRightScore() ); // Gameover if( ball.getRightScore() == winningscore ) { gameoverBool = true; ball.setLeftBool(false); ball.setRightBool(false); //gameover.playsound(); std::string winner = Paddles.getRightName() + " WINS!"; gameover.setWinner( winner ); window.clear(); if(gameoverBool) window.draw(gameover); } if( ball.getLeftScore() == winningscore ) { gameoverBool = true; ball.setLeftBool(false); ball.setRightBool(false); //gameover.playsound(); std::string winner = Paddles.getLeftName() + " WINS!"; gameover.setWinner( winner ); window.clear(); if(gameoverBool) window.draw(gameover); } } window.display(); } return 0; }
int main() { if (!init()) { return 1; } ballImg = loadImage ("ball.png"); Ball ball = Ball (screen, ballImg, SCREEN_WIDTH/2 - 8, SCREEN_HEIGHT/2 - 8, 1, 1); Paddle p1 = Paddle (screen, SCREEN_WIDTH-20, SCREEN_HEIGHT/2-PADDLE_HEIGHT/2, PADDLE_WIDTH, PADDLE_HEIGHT); Paddle p2 = Paddle (screen, 20, SCREEN_HEIGHT/2-PADDLE_HEIGHT/2, PADDLE_WIDTH, PADDLE_HEIGHT); // p1 can use default keys, p2 needs new ones bound. p2.setKeys (SDLK_w, SDLK_s); bool quit = false; bool winner = false; SDL_Event event; Timer fps; int bounceCount = 0; while (!quit) { fps.start(); if (SDL_PollEvent (&event)) { p1.handleEvents (event); p2.handleEvents (event); if (event.type == SDL_QUIT) { quit = true; } } // white out the background SDL_FillRect (screen, &screen->clip_rect, SDL_MapRGB (screen->format, 0xFF, 0xFF, 0xFF)); // update the paddles p1.draw (); p2.draw (); // update the ball ball.update(); if (!winner) { // check to see if the ball is past the paddle if (ball.getXPos() < 20) { // left player win std::cout << "right player win!" << std::endl; winner = true; } else if (ball.getXPos() > SCREEN_WIDTH - 20 - PADDLE_WIDTH) { // right player win std::cout << "left player win!" << std::endl; winner = true; } } // check to see if the ball should bounce off the right paddle if (ball.getXPos() + 6 == SCREEN_WIDTH - 20 - PADDLE_WIDTH && ball.getYPos() < p1.getYPos() + PADDLE_HEIGHT && ball.getYPos() > p1.getYPos()) { std::cout << "right bounce!" << std::endl; ball.bounce(); } SDL_UpdateWindowSurface (window); if (fps.get_ticks() < 1000 / FRAMES_PER_SECOND) { SDL_Delay ((1000 / FRAMES_PER_SECOND) - fps.get_ticks()); } } clean(); return 0; }