Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: SFML 2 Pong game update proposal  (Read 6596 times)

0 Members and 1 Guest are viewing this topic.

easy

  • Full Member
  • ***
  • Posts: 146
    • MSN Messenger - easy82.contact@gmail.com
    • View Profile
    • Email
SFML 2 Pong game update proposal
« on: August 16, 2011, 09:12:07 am »
Hello!

This might not be the ideal forum section so please move my topic if it's misplaced here. Also I don't know if you're open to such modifications or not.

I've modified a little bit the SFML 2 Pong example to slightly enhance the gameplay, that is:
    - there is a 1 second delay before a round starts (shows how to use an sf::Clock),
    - the game restarts when a player scores a point (encourages to play),
    - the scores are printed on the screen instead of the end text (show how to print variables with sf::Text),
    - fixes AITime to sf::Uint32,
    - added comments.


Just an idea: a new sound (a whistle) could be played on every new round.

I think along with these enhancement the example is still encouraging the new users to modify it but also to play with it.
What do you think?

The code:

Code: [Select]
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
//#include <cmath>
//#include <ctime>
//#include <cstdlib>
#include <sstream>


////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Application exit code
///
////////////////////////////////////////////////////////////
int main()
{
    std::srand(static_cast<unsigned int>(std::time(NULL)));

    // Defines PI
    const float PI = 3.14159f;

    // Create the window of the application
    sf::RenderWindow window(sf::VideoMode(800, 600, 32), "SFML Pong");

    // Load the sounds used in the game
    sf::SoundBuffer ballSoundBuffer;
    if (!ballSoundBuffer.LoadFromFile("resources/ball.wav"))
    {
        return EXIT_FAILURE;
    }
    sf::Sound ballSound(ballSoundBuffer);

    // Load the textures used in the game
    sf::Texture backgroundTexture, leftPaddleTexture, rightPaddleTexture, ballTexture;
    if (!backgroundTexture.LoadFromFile("resources/background.jpg")    ||
        !leftPaddleTexture.LoadFromFile("resources/paddle_left.png")   ||
        !rightPaddleTexture.LoadFromFile("resources/paddle_right.png") ||
        !ballTexture.LoadFromFile("resources/ball.png"))
    {
        return EXIT_FAILURE;
    }

    // Load the text font
    sf::Font font;
    if (!font.LoadFromFile("resources/sansation.ttf"))
        return EXIT_FAILURE;

    // Initialize the score text
    sf::Text scoreText;
    scoreText.SetFont(font);
    scoreText.SetCharacterSize(60);
    scoreText.SetColor(sf::Color(50, 50, 250));

    // Create the sprites of the background, the paddles and the ball
    sf::Sprite background(backgroundTexture);
    sf::Sprite leftPaddle(leftPaddleTexture);
    sf::Sprite rightPaddle(rightPaddleTexture);
    sf::Sprite ball(ballTexture);

    leftPaddle.Move(10, (window.GetView().GetSize().y - leftPaddle.GetSize().y) / 2);
    rightPaddle.Move(window.GetView().GetSize().x - rightPaddle.GetSize().x - 10, (window.GetView().GetSize().y - rightPaddle.GetSize().y) / 2);

    // Define the paddles properties
    sf::Clock AITimer;
    sf::Uint32 AITime      = 200;
    float leftPaddleSpeed  = 400.f;
    float rightPaddleSpeed = 400.f;

    // Define the ball properties
    float ballSpeed = 400.f;
    float ballAngle;

    // Main loop
    int leftScore = 0, rightScore = 0;
    sf::Clock start;
    bool restart = true;
    while (window.IsOpened())
    {
        // 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;
            }
        }

        // Restart the game
        if (restart)
        {
            // Make sure the ball initial angle is not too much vertical
            do
            {
                ballAngle = std::rand() * 2 * PI / RAND_MAX;
            }
            while (std::abs(std::cos(ballAngle)) < 0.7f);

            ball.SetPosition((window.GetView().GetSize().x - ball.GetSize().x) / 2, (window.GetView().GetSize().y - ball.GetSize().y) / 2);

            // Update score
            std::ostringstream oss;
            oss << leftScore << " : " << rightScore;
            scoreText.SetString(oss.str());
            scoreText.SetPosition((window.GetView().GetSize().x / 2) - (scoreText.GetRect().Width / 2), 20.f);

            // Reset
            start.Reset();
            restart = false;
        }

        if (!restart)
        {
            // Move the player's paddle
            if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Up) && (leftPaddle.GetPosition().y > 5.f))
                leftPaddle.Move(0.f, -leftPaddleSpeed * window.GetFrameTime() / 1000.f);
            if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Down) && (leftPaddle.GetPosition().y < window.GetView().GetSize().y - leftPaddle.GetSize().y - 5.f))
                leftPaddle.Move(0.f, leftPaddleSpeed * window.GetFrameTime() / 1000.f);

            // Move the computer's paddle
            if (((rightPaddleSpeed < 0.f) && (rightPaddle.GetPosition().y > 5.f)) ||
                ((rightPaddleSpeed > 0.f) && (rightPaddle.GetPosition().y < window.GetView().GetSize().y - rightPaddle.GetSize().y - 5.f)))
            {
                rightPaddle.Move(0.f, rightPaddleSpeed * window.GetFrameTime() / 1000.f);
            }

            // Update the computer's paddle direction according to the ball position
            if (AITimer.GetElapsedTime() > AITime)
            {
                AITimer.Reset();
                if ((rightPaddleSpeed < 0) && (ball.GetPosition().y + ball.GetSize().y > rightPaddle.GetPosition().y + rightPaddle.GetSize().y))
                    rightPaddleSpeed = -rightPaddleSpeed;
                if ((rightPaddleSpeed > 0) && (ball.GetPosition().y < rightPaddle.GetPosition().y))
                    rightPaddleSpeed = -rightPaddleSpeed;
            }

            // Wait a second before the ball starts moving
            if (start.GetElapsedTime() > 1000)
            {
                // Move the ball
                float factor = ballSpeed * window.GetFrameTime() / 1000.f;
                ball.Move(std::cos(ballAngle) * factor, std::sin(ballAngle) * factor);
            }

            // Check collisions between the ball and the screen
            if (ball.GetPosition().x < 0.f)
            {
                restart = true;
                ++rightScore;
            }
            if (ball.GetPosition().x + ball.GetSize().x > window.GetView().GetSize().x)
            {
                restart = true;
                ++leftScore;
            }
            if (ball.GetPosition().y < 0.f)
            {
                ballSound.Play();
                ballAngle = -ballAngle;
                ball.SetY(0.1f);
            }
            if (ball.GetPosition().y + ball.GetSize().y > window.GetView().GetSize().y)
            {
                ballSound.Play();
                ballAngle = -ballAngle;
                ball.SetY(window.GetView().GetSize().y - ball.GetSize().y - 0.1f);
            }

            // Check the collisions between the ball and the paddles
            // Left Paddle
            if (ball.GetPosition().x < leftPaddle.GetPosition().x + leftPaddle.GetSize().x &&
                ball.GetPosition().x > leftPaddle.GetPosition().x + (leftPaddle.GetSize().x / 2.0f) &&
                ball.GetPosition().y + ball.GetSize().y >= leftPaddle.GetPosition().y &&
                ball.GetPosition().y <= leftPaddle.GetPosition().y + leftPaddle.GetSize().y)
            {
                ballSound.Play();
                ballAngle = PI - ballAngle;
                ball.SetX(leftPaddle.GetPosition().x + leftPaddle.GetSize().x + 0.1f);
            }

            // Right Paddle
            if (ball.GetPosition().x + ball.GetSize().x > rightPaddle.GetPosition().x &&
                ball.GetPosition().x + ball.GetSize().x < rightPaddle.GetPosition().x + (rightPaddle.GetSize().x / 2.0f) &&
                ball.GetPosition().y + ball.GetSize().y >= rightPaddle.GetPosition().y &&
                ball.GetPosition().y <= rightPaddle.GetPosition().y + rightPaddle.GetSize().y)
            {
                ballSound.Play();
                ballAngle = PI - ballAngle;
                ball.SetX(rightPaddle.GetPosition().x - ball.GetSize().x - 0.1f);
            }
        }

        // Clear the window
        window.Clear();

        // Draw the background, paddles and ball sprites
        window.Draw(background);
        window.Draw(leftPaddle);
        window.Draw(rightPaddle);
        window.Draw(ball);
        window.Draw(scoreText);

        // Display things on screen
        window.Display();
    }

    return EXIT_SUCCESS;
}


Cheers,
easy

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
SFML 2 Pong game update proposal
« Reply #1 on: August 16, 2011, 09:27:01 am »
Sounds good, thanks :)
Laurent Gomila - SFML developer

easy

  • Full Member
  • ***
  • Posts: 146
    • MSN Messenger - easy82.contact@gmail.com
    • View Profile
    • Email
SFML 2 Pong game update proposal
« Reply #2 on: August 16, 2011, 09:43:57 am »
You're welcome! :)

easy

  • Full Member
  • ***
  • Posts: 146
    • MSN Messenger - easy82.contact@gmail.com
    • View Profile
    • Email
SFML 2 Pong game update proposal
« Reply #3 on: August 16, 2011, 10:02:51 am »
By the way, I've found an ideal sound for the whistle idea: http://www.freesound.org/samplesViewSingle.php?id=90743

It's under Creative Commons Sampling Plus 1.0 license:
http://creativecommons.org/licenses/sampling+/1.0/