243 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
 | 
						|
////////////////////////////////////////////////////////////
 | 
						|
// Headers
 | 
						|
////////////////////////////////////////////////////////////
 | 
						|
#include <SFML/Graphics.hpp>
 | 
						|
#include <SFML/Audio.hpp>
 | 
						|
#include <cmath>
 | 
						|
#include <ctime>
 | 
						|
#include <cstdlib>
 | 
						|
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////
 | 
						|
/// Entry point of application
 | 
						|
///
 | 
						|
/// \return Application exit code
 | 
						|
///
 | 
						|
////////////////////////////////////////////////////////////
 | 
						|
int main()
 | 
						|
{
 | 
						|
    std::srand(static_cast<unsigned int>(std::time(NULL)));
 | 
						|
 | 
						|
    // Define some constants
 | 
						|
    const float pi = 3.14159f;
 | 
						|
    const int gameWidth = 800;
 | 
						|
    const int gameHeight = 600;
 | 
						|
    sf::Vector2f paddleSize(25, 100);
 | 
						|
    float ballRadius = 10.f;
 | 
						|
 | 
						|
    // 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("resources/ball.wav"))
 | 
						|
        return EXIT_FAILURE;
 | 
						|
    sf::Sound ballSound(ballSoundBuffer);
 | 
						|
 | 
						|
    // Create the left paddle
 | 
						|
    sf::RectangleShape leftPaddle;
 | 
						|
    leftPaddle.setSize(paddleSize - sf::Vector2f(3, 3));
 | 
						|
    leftPaddle.setOutlineThickness(3);
 | 
						|
    leftPaddle.setOutlineColor(sf::Color::Black);
 | 
						|
    leftPaddle.setFillColor(sf::Color(100, 100, 200));
 | 
						|
    leftPaddle.setOrigin(paddleSize / 2.f);
 | 
						|
 | 
						|
    // Create the right paddle
 | 
						|
    sf::RectangleShape rightPaddle;
 | 
						|
    rightPaddle.setSize(paddleSize - sf::Vector2f(3, 3));
 | 
						|
    rightPaddle.setOutlineThickness(3);
 | 
						|
    rightPaddle.setOutlineColor(sf::Color::Black);
 | 
						|
    rightPaddle.setFillColor(sf::Color(200, 100, 100));
 | 
						|
    rightPaddle.setOrigin(paddleSize / 2.f);
 | 
						|
 | 
						|
    // Create the ball
 | 
						|
    sf::CircleShape ball;
 | 
						|
    ball.setRadius(ballRadius - 3);
 | 
						|
    ball.setOutlineThickness(3);
 | 
						|
    ball.setOutlineColor(sf::Color::Black);
 | 
						|
    ball.setFillColor(sf::Color::White);
 | 
						|
    ball.setOrigin(ballRadius / 2, ballRadius / 2);
 | 
						|
 | 
						|
    // Load the text font
 | 
						|
    sf::Font font;
 | 
						|
    if (!font.loadFromFile("resources/sansation.ttf"))
 | 
						|
        return EXIT_FAILURE;
 | 
						|
 | 
						|
    // Initialize the pause message
 | 
						|
    sf::Text pauseMessage;
 | 
						|
    pauseMessage.setFont(font);
 | 
						|
    pauseMessage.setCharacterSize(40);
 | 
						|
    pauseMessage.setPosition(170.f, 150.f);
 | 
						|
    pauseMessage.setFillColor(sf::Color::White);
 | 
						|
    pauseMessage.setString("Welcome to SFML pong!\nPress space to start the game");
 | 
						|
 | 
						|
    // Define the paddles properties
 | 
						|
    sf::Clock AITimer;
 | 
						|
    const sf::Time AITime   = sf::seconds(0.1f);
 | 
						|
    const float paddleSpeed = 400.f;
 | 
						|
    float rightPaddleSpeed  = 0.f;
 | 
						|
    const float ballSpeed   = 400.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))
 | 
						|
            {
 | 
						|
                if (!isPlaying)
 | 
						|
                {
 | 
						|
                    // (re)start the game
 | 
						|
                    isPlaying = true;
 | 
						|
                    clock.restart();
 | 
						|
 | 
						|
                    // Reset the position of the paddles and ball
 | 
						|
                    leftPaddle.setPosition(10 + paddleSize.x / 2, gameHeight / 2);
 | 
						|
                    rightPaddle.setPosition(gameWidth - 10 - paddleSize.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 = (std::rand() % 360) * 2 * pi / 360;
 | 
						|
                    }
 | 
						|
                    while (std::abs(std::cos(ballAngle)) < 0.7f);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        if (isPlaying)
 | 
						|
        {
 | 
						|
            float deltaTime = clock.restart().asSeconds();
 | 
						|
 | 
						|
            // Move the player's paddle
 | 
						|
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) &&
 | 
						|
               (leftPaddle.getPosition().y - paddleSize.y / 2 > 5.f))
 | 
						|
            {
 | 
						|
                leftPaddle.move(0.f, -paddleSpeed * deltaTime);
 | 
						|
            }
 | 
						|
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) &&
 | 
						|
               (leftPaddle.getPosition().y + paddleSize.y / 2 < gameHeight - 5.f))
 | 
						|
            {
 | 
						|
                leftPaddle.move(0.f, paddleSpeed * deltaTime);
 | 
						|
            }
 | 
						|
 | 
						|
            // Move the computer's paddle
 | 
						|
            if (((rightPaddleSpeed < 0.f) && (rightPaddle.getPosition().y - paddleSize.y / 2 > 5.f)) ||
 | 
						|
                ((rightPaddleSpeed > 0.f) && (rightPaddle.getPosition().y + paddleSize.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.getPosition().y + ballRadius > rightPaddle.getPosition().y + paddleSize.y / 2)
 | 
						|
                    rightPaddleSpeed = paddleSpeed;
 | 
						|
                else if (ball.getPosition().y - ballRadius < rightPaddle.getPosition().y - paddleSize.y / 2)
 | 
						|
                    rightPaddleSpeed = -paddleSpeed;
 | 
						|
                else
 | 
						|
                    rightPaddleSpeed = 0.f;
 | 
						|
            }
 | 
						|
 | 
						|
            // Move the ball
 | 
						|
            float factor = ballSpeed * deltaTime;
 | 
						|
            ball.move(std::cos(ballAngle) * factor, std::sin(ballAngle) * factor);
 | 
						|
 | 
						|
            // Check collisions between the ball and the screen
 | 
						|
            if (ball.getPosition().x - ballRadius < 0.f)
 | 
						|
            {
 | 
						|
                isPlaying = false;
 | 
						|
                pauseMessage.setString("You lost!\nPress space to restart or\nescape to exit");
 | 
						|
            }
 | 
						|
            if (ball.getPosition().x + ballRadius > gameWidth)
 | 
						|
            {
 | 
						|
                isPlaying = false;
 | 
						|
                pauseMessage.setString("You won!\nPress space to restart or\nescape to exit");
 | 
						|
            }
 | 
						|
            if (ball.getPosition().y - ballRadius < 0.f)
 | 
						|
            {
 | 
						|
                ballSound.play();
 | 
						|
                ballAngle = -ballAngle;
 | 
						|
                ball.setPosition(ball.getPosition().x, ballRadius + 0.1f);
 | 
						|
            }
 | 
						|
            if (ball.getPosition().y + ballRadius > gameHeight)
 | 
						|
            {
 | 
						|
                ballSound.play();
 | 
						|
                ballAngle = -ballAngle;
 | 
						|
                ball.setPosition(ball.getPosition().x, gameHeight - ballRadius - 0.1f);
 | 
						|
            }
 | 
						|
 | 
						|
            // Check the collisions between the ball and the paddles
 | 
						|
            // Left Paddle
 | 
						|
            if (ball.getPosition().x - ballRadius < leftPaddle.getPosition().x + paddleSize.x / 2 &&
 | 
						|
                ball.getPosition().x - ballRadius > leftPaddle.getPosition().x &&
 | 
						|
                ball.getPosition().y + ballRadius >= leftPaddle.getPosition().y - paddleSize.y / 2 &&
 | 
						|
                ball.getPosition().y - ballRadius <= leftPaddle.getPosition().y + paddleSize.y / 2)
 | 
						|
            {
 | 
						|
                if (ball.getPosition().y > leftPaddle.getPosition().y)
 | 
						|
                    ballAngle = pi - ballAngle + (std::rand() % 20) * pi / 180;
 | 
						|
                else
 | 
						|
                    ballAngle = pi - ballAngle - (std::rand() % 20) * pi / 180;
 | 
						|
 | 
						|
                ballSound.play();
 | 
						|
                ball.setPosition(leftPaddle.getPosition().x + ballRadius + paddleSize.x / 2 + 0.1f, ball.getPosition().y);
 | 
						|
            }
 | 
						|
 | 
						|
            // Right Paddle
 | 
						|
            if (ball.getPosition().x + ballRadius > rightPaddle.getPosition().x - paddleSize.x / 2 &&
 | 
						|
                ball.getPosition().x + ballRadius < rightPaddle.getPosition().x &&
 | 
						|
                ball.getPosition().y + ballRadius >= rightPaddle.getPosition().y - paddleSize.y / 2 &&
 | 
						|
                ball.getPosition().y - ballRadius <= rightPaddle.getPosition().y + paddleSize.y / 2)
 | 
						|
            {
 | 
						|
                if (ball.getPosition().y > rightPaddle.getPosition().y)
 | 
						|
                    ballAngle = pi - ballAngle + (std::rand() % 20) * pi / 180;
 | 
						|
                else
 | 
						|
                    ballAngle = pi - ballAngle - (std::rand() % 20) * pi / 180;
 | 
						|
 | 
						|
                ballSound.play();
 | 
						|
                ball.setPosition(rightPaddle.getPosition().x - ballRadius - paddleSize.x / 2 - 0.1f, ball.getPosition().y);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // 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;
 | 
						|
}
 |