//////////////////////////////////////////////////////////// // Headers //////////////////////////////////////////////////////////// #include #include #include #include #include #include "Ball.h" #include "Paddle.h" #ifdef SFML_SYSTEM_IOS #include #endif using namespace std; string resourcesDir() { #ifdef SFML_SYSTEM_IOS return ""; #else return "resources/"; #endif } //////////////////////////////////////////////////////////// /// Entry point of application /// /// \return Application exit code /// //////////////////////////////////////////////////////////// int main() { srand(static_cast(time(NULL))); // Define some constants const float pi = 3.1415; const int gameWidth = 800; const int gameHeight = 600; // Create the window of the application sf::RenderWindow window(sf::VideoMode(gameWidth, gameHeight, 32), "SFML Pong", sf::Style::Titlebar | sf::Style::Close); window.setVerticalSyncEnabled(true); // Load the sounds used in the game sf::SoundBuffer ballSoundBuffer; if (!ballSoundBuffer.loadFromFile(resourcesDir() + "ball.wav")) return EXIT_FAILURE; sf::Sound ballSound(ballSoundBuffer); // Create the left paddle Paddle leftPaddle; // Create the right paddle Paddle rightPaddle; // Create the ball Ball ball; // Load the text font sf::Font font; if (!font.loadFromFile(resourcesDir() + "sansation.ttf")) return EXIT_FAILURE; // Initialize the pause message sf::Text pauseMessage; pauseMessage.setFont(font); pauseMessage.setCharacterSize(40); pauseMessage.setPosition(170, 150); //pauseMessage.setFillColor(sf::Color::White); #ifdef SFML_SYSTEM_IOS pauseMessage.setString("Welcome to SFML pong!\nTouch the screen to start the game"); #else pauseMessage.setString("Welcome to SFML pong!\nPress space to start the game"); #endif // Define the paddles properties sf::Clock AITimer; const sf::Time AITime = sf::seconds(0.1f); const float paddleSpeed = 400.f; float rightPaddleSpeed = 0.f; float ballAngle = 0.f; // to be changed later sf::Clock clock; bool isPlaying = false; while (window.isOpen()) { // Handle events sf::Event event; while (window.pollEvent(event)) { // Window closed or escape key pressed: exit if ((event.type == sf::Event::Closed) || ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))) { window.close(); break; } // Space key pressed: play if (((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space)) || (event.type == sf::Event::TouchBegan)) { if (!isPlaying) { // (re)start the game isPlaying = true; clock.restart(); // Reset the position of the paddles and ball leftPaddle.setPosition(10 + leftPaddle.getSize().x / 2, gameHeight / 2); rightPaddle.setPosition(gameWidth - 10 - leftPaddle.getSize().x / 2, gameHeight / 2); ball.setPosition(gameWidth / 2, gameHeight / 2); // Reset the ball angle do { // Make sure the ball initial angle is not too much vertical ballAngle = (rand() % 360) * 2 * pi / 360; } while (abs(cos(ballAngle)) < 0.7f); } } // Window size changed, adjust view appropriately if (event.type == sf::Event::Resized) { sf::View view; view.setSize(gameWidth, gameHeight); view.setCenter(gameWidth/2.f, gameHeight/2.f); window.setView(view); } } if (isPlaying) { float deltaTime = clock.restart().asSeconds(); // Move the player's paddle if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && (leftPaddle.getY() - leftPaddle.getSize().y / 2 > 5)) { leftPaddle.move(0.f, -paddleSpeed * deltaTime); } if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) && (leftPaddle.getY() + leftPaddle.getSize().y / 2 < gameHeight - 5)) { leftPaddle.move(0.f, paddleSpeed * deltaTime); } if (sf::Touch::isDown(0)) { sf::Vector2i pos = sf::Touch::getPosition(0); sf::Vector2f mappedPos = window.mapPixelToCoords(pos); leftPaddle.setPosition(leftPaddle.getX(), mappedPos.y); } // Move the computer's paddle if (((rightPaddleSpeed < 0.f) && (rightPaddle.getY() - leftPaddle.getSize().y / 2 > 5.f)) || ((rightPaddleSpeed > 0.f) && (rightPaddle.getY() + leftPaddle.getSize().y / 2 < gameHeight - 5.f))) { rightPaddle.move(0.f, rightPaddleSpeed * deltaTime); } // Update the computer's paddle direction according to the ball position if (AITimer.getElapsedTime() > AITime) { AITimer.restart(); if (ball.getY() + ball.getRadius() > rightPaddle.getY() + leftPaddle.getSize().y / 2) rightPaddleSpeed = paddleSpeed; else if (ball.getY() - ball.getRadius() < rightPaddle.getY() - leftPaddle.getSize().y / 2) rightPaddleSpeed = -paddleSpeed; else rightPaddleSpeed = 0.f; } // Move the ball float factor = ball.getSpeed() * deltaTime; ball.move(cos(ballAngle) * factor, sin(ballAngle) * factor); #ifdef SFML_SYSTEM_IOS const string inputString = "Touch the screen to restart"; #else const string inputString = "Press space to restart or\nescape to exit"; #endif // Check collisions between the ball and the screen if (ball.getX() - ball.getRadius() < 0.f) { isPlaying = false; pauseMessage.setString("You Lost!\n" + inputString); } if (ball.getX() + ball.getRadius() > gameWidth) { isPlaying = false; pauseMessage.setString("You Won!\n" + inputString); } if (ball.getY() - ball.getRadius() < 0.f) { ballSound.play(); ballAngle = -ballAngle; ball.setPosition(ball.getX(), ball.getRadius() + 0.1f); } if (ball.getY() + ball.getRadius() > gameHeight) { ballSound.play(); ballAngle = -ballAngle; ball.setPosition(ball.getX(), gameHeight - ball.getRadius() - 0.1f); } // Check the collisions between the ball and the paddles // Left Paddle if (ball.getX() - ball.getRadius() < leftPaddle.getX() + leftPaddle.getSize().x / 2 && ball.getX() - ball.getRadius() > leftPaddle.getX() && ball.getY() + ball.getRadius() >= leftPaddle.getY() - leftPaddle.getSize().y / 2 && ball.getY() - ball.getRadius() <= leftPaddle.getY() + leftPaddle.getSize().y / 2) { if (ball.getY() > leftPaddle.getY()) ballAngle = pi - ballAngle + (rand() % 20) * pi / 180; else ballAngle = pi - ballAngle - (rand() % 20) * pi / 180; ballSound.play(); ball.setPosition(leftPaddle.getX() + ball.getRadius() + leftPaddle.getSize().x / 2 + 0.1f, ball.getY()); } // Right Paddle if (ball.getX() + ball.getRadius() > rightPaddle.getX() - leftPaddle.getSize().x / 2 && ball.getX() + ball.getRadius() < rightPaddle.getX() && ball.getY() + ball.getRadius() >= rightPaddle.getY() - leftPaddle.getSize().y / 2 && ball.getY() - ball.getRadius() <= rightPaddle.getY() + leftPaddle.getSize().y / 2) { if (ball.getY() > rightPaddle.getY()) ballAngle = pi - ballAngle + (rand() % 20) * pi / 180; else ballAngle = pi - ballAngle - (rand() % 20) * pi / 180; ballSound.play(); ball.setPosition(rightPaddle.getX() - ball.getRadius() - leftPaddle.getSize().x / 2 - 0.1f, ball.getY()); } } // Clear the window window.clear(sf::Color(50, 200, 50)); if (isPlaying) { // Draw the paddles and the ball window.draw(leftPaddle); window.draw(rightPaddle); window.draw(ball); } else { // Draw the pause message window.draw(pauseMessage); } // Display things on screen window.display(); } return EXIT_SUCCESS; }