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

Author Topic: Finished my First Pong Game using SFML (Mac OS X)!  (Read 8674 times)

0 Members and 1 Guest are viewing this topic.

AndreeU17

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Finished my First Pong Game using SFML (Mac OS X)!
« on: June 01, 2014, 07:57:32 pm »
So after a month of pure coding and asking everyone for basic questions, i manage to fully complete the game even though it still needs a ton more improvements which i will still keep implementing until i have a decent game with no bugs!

I'm a beginner in SFML and C++, if you find any other way i can improve my code, please let me know! Anything is worth it even bad comments, anything that can help me improve this!

Please offer any critics and improvements needed, Here is a few things i need to work on:
1) smooth movement for the paddles as well as the ball
2) create a splash screen
3) work on any other fixes to improve the coding
4) Implement a Computer AI
5) Implement Textures and Sprite for better look and feel
6)......Anything that you guys request!



Here is the source code:
/*
    Retro Clone Pong Game by Jonathan A Vazquez
    Version 2.0
 
 */


#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <ResourcePath.hpp> //Helper method resourcepath() for files (Images, Sounds, fonts)
#include <cmath>
#include <string>


//Window Settings
int windowWidth{600};
int windowHeight{400};
std::string windowTitle{"RetroPong"};

//Creating the Left and Right Paddle Position and Size
float leftPaddleSize_X{15};
float leftPaddleSize_Y{75};
float leftPaddlePos_X{5};
float leftPaddlePos_Y{(windowHeight / 2) - (leftPaddleSize_Y / 2)};
float rightPaddleSize_X{leftPaddleSize_X};
float rightPaddleSize_Y{leftPaddleSize_Y};
float rightPaddlePos_X{575};
float rightPaddlePos_Y{(windowHeight / 2) - (rightPaddleSize_Y / 2)};

//Creating the PongBall Properties
float ballPos_X{300};
float ballPos_Y{200};
float ballRadius{10};
float ballSpeed{0.1};
float ballDir_X{1.0};
float ballDir_Y{1.0};

//keeping the scoreboard
int playerScore{0};
int opponentScore{0};

int main()
{
    // Create the main window as well as all the necessary shapes and text
    sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), windowTitle);
    sf::Font font;
    sf::Text playerTextScore, opponentTextScore;
    sf::RectangleShape bgLeftBox, bgRightBox, leftPaddle, rightPaddle;
    sf::CircleShape pongBall;
   
    //Setting the Right and Left Background Boxes
    bgLeftBox.setSize(sf::Vector2f(windowWidth/2, windowHeight));
    bgLeftBox.setPosition(sf::Vector2f(0, 0));
    bgLeftBox.setFillColor(sf::Color::White);
    bgRightBox.setSize(sf::Vector2f(windowWidth/2, windowHeight));
    bgRightBox.setPosition(sf::Vector2f(windowWidth / 2, 0));
    bgRightBox.setFillColor(sf::Color::Black);
   
    //Import the Font and create a Score Text for the user
    std::string resourcePath(void);
    font.loadFromFile(resourcePath() + "boxfont.ttf");
    playerTextScore.setFont(font);
    opponentTextScore.setFont(font);
    playerTextScore.setCharacterSize(72);
    opponentTextScore.setCharacterSize(72);
    playerTextScore.setColor(sf::Color::Black);
    opponentTextScore.setColor(sf::Color::White);
    opponentTextScore.setPosition(sf::Vector2f(450 ,0));
    playerTextScore.setPosition(sf::Vector2f(125, 0));
    playerTextScore.setString("0");
    opponentTextScore.setString("0");

    //Converting integer to strings
    //std::string s = to_string(playerScore);
   
    //Setting the Right and Left Paddle
    leftPaddle.setSize(sf::Vector2f(leftPaddleSize_X, leftPaddleSize_Y));
    leftPaddle.setPosition(sf::Vector2f(leftPaddlePos_X, leftPaddlePos_Y));
    leftPaddle.setFillColor(sf::Color::Black);
    rightPaddle.setSize(sf::Vector2f(rightPaddleSize_X, rightPaddleSize_Y));
    rightPaddle.setPosition(sf::Vector2f(rightPaddlePos_X, rightPaddlePos_Y)); //total window is 600, size 15, position is 5
    rightPaddle.setFillColor(sf::Color::White);
   
    //Creating the ball and its properties
    pongBall.setRadius(ballRadius);
    pongBall.setPosition(ballPos_X, ballPos_Y);
    pongBall.setFillColor(sf::Color::White);

                             
    // Start the game loop
    while (window.isOpen())
    {
        //Updating the movement of the ball and changing its color in the game loop
        //Moving Ball
        ballPos_X += ballSpeed * ballDir_X;
        ballPos_Y += ballSpeed * ballDir_Y;
        pongBall.setPosition(ballPos_X, ballPos_Y);
       
        ///Changing the Ball Color depending on location
        if(pongBall.getPosition().x < (windowWidth / 2))
        {
            pongBall.setFillColor(sf::Color::Black);
        }else
        {
            pongBall.setFillColor(sf::Color::White);
        }
       
        //Wall Rebounce Both Top and Bottom
        if(pongBall.getPosition().y > windowHeight)
        {
            ballDir_Y = -fabs(ballDir_Y);
        }else if(pongBall.getPosition().y < 0)
        {
            ballDir_Y = fabs(ballDir_Y);
        }
       
        //Collision Detection of the left and Right Paddle
        if(pongBall.getPosition().x < leftPaddle.getSize().x + leftPaddle.getPosition().x &&
           pongBall.getPosition().x > leftPaddle.getPosition().x &&
           pongBall.getPosition().y < leftPaddle.getPosition().y + leftPaddle.getSize().y &&
           pongBall.getPosition().y > leftPaddle.getPosition().y ) //Left Paddle
        {
            ballDir_X = fabs(ballDir_X);
           
        }else if(pongBall.getPosition().x < 0)
        {
            ballPos_X = windowWidth / 2;
            ballPos_Y = windowHeight / 2;
            pongBall.setPosition(ballPos_X, ballPos_Y);
            ballDir_X = fabs(ballDir_X);
            ++opponentScore;
            std::string opponentScoreText = std::to_string(opponentScore);
            opponentTextScore.setString(opponentScoreText);
            if(opponentScore == 7)
            {
                //Print out Opponent Win and stop the ball from moving
                opponentTextScore.setColor(sf::Color::Red);
                opponentTextScore.setCharacterSize(20);
                opponentTextScore.setPosition(sf::Vector2f(0, windowHeight / 2));
                opponentTextScore.setString("Opponent Won the Match, Thanks for playing");
                window.clear();
                window.close();
            }
        }
        if(pongBall.getPosition().x <  rightPaddle.getPosition().x + rightPaddle.getSize().x &&
           pongBall.getPosition().x > rightPaddle.getPosition().x &&
           pongBall.getPosition().y < rightPaddle.getSize().y + rightPaddle.getPosition().y &&
           pongBall.getPosition().y > rightPaddle.getPosition().y) //Right Paddle
        {
            ballDir_X = -fabs(ballDir_X);
        }else if(pongBall.getPosition().x > windowWidth)
        {
            ballPos_X  = windowWidth / 2;
            ballPos_Y = windowHeight / 2;
            pongBall.setPosition(ballPos_X, ballPos_Y);
            ballDir_X = -fabs(ballDir_X);
            ++playerScore;
            std::string playerScoreText = std::to_string(playerScore);
            playerTextScore.setString(playerScoreText);
            if(playerScore == 7)
            {
                //Print out Player Win and stop the ball from moving
                playerTextScore.setColor(sf::Color::Red);
                playerTextScore.setCharacterSize(20);
                playerTextScore.setPosition(sf::Vector2f(0, windowHeight / 2));
                playerTextScore.setString("Player Won the Match, Thanks for playing");
                window.clear();
                window.close();
            }
        }
       
       
        // Process events
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Close window : exit
            if (event.type == sf::Event::Closed) {
                // Clear screen
                window.clear(sf::Color::White);
                window.close();
            }
            //To Move the Left Paddle Event
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
            {
                leftPaddle.move(sf::Vector2f(0, -12));
            }else if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
            {
                leftPaddle.move(sf::Vector2f(0, 12));
            }
            //To move the right Paddle Event
            if(sf::Keyboard::isKeyPressed(sf::Keyboard::I))
            {
                rightPaddle.move(sf::Vector2f(0, -12));
            }else if(sf::Keyboard::isKeyPressed(sf::Keyboard::K))
            {
                rightPaddle.move(sf::Vector2f(0, 12));
            }
        }

        // Draw the sprite
        window.draw(bgLeftBox);
        window.draw(bgRightBox);
        window.draw(playerTextScore);
        window.draw(opponentTextScore);
        window.draw(leftPaddle);
        window.draw(rightPaddle);
        window.draw(pongBall);

        // Update the window
        window.display();
    }
}
 

Here is a picture of what it looks like
« Last Edit: June 01, 2014, 07:59:26 pm by AndreeU17 »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Finished my First Pong Game using SFML (Mac OS X)!
« Reply #1 on: June 01, 2014, 10:25:31 pm »
I didn't try your game, but from the screenshots it looks good.  :)

A few things I would suggest you do is first learn to use some form of source control and instead of putting all the code in the initial post upload it using source control to a hosting site a provide a link.

Secondly looking at the code I suggest you learn about object oriented programming and how to encapsulate different functions into classes. At the moment you have duplicated code which could be eliminated if you broke your program into classes. Also making a change like this would force you to think about object ownership and what should be doing what instead of letting everything hang out in the main function. (Global variables are not a great idea and should be avoided  ;))

Oh and one more thing, you need to implement delta time measurement. At the moment your movement code is tied to FPS and any change in FPS will cause your paddle to move at different speeds. For example if I run your code on a 10 year old PC that can't pull 30 FPS the paddles would move very slowly. Or if I ran it on my i7 laptop everything would fly off the screen.  :P
« Last Edit: June 01, 2014, 10:27:47 pm by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

The Illusionist Mirage

  • Full Member
  • ***
  • Posts: 115
  • My Life = Linux, C++ & Computers
    • View Profile
    • fleptic
    • Email
Re: Finished my First Pong Game using SFML (Mac OS X)!
« Reply #2 on: June 02, 2014, 06:13:53 am »
Screenshots look nice indeed. :)

And I agree with zsbzsb and would advise you to redesign the game using separate classes for separate functionalities. e.g., a Paddle class, a Ball class, a Game class and so on. And when you compare the two codes, you'll see the difference ;)

Here's a good link for achieving a fixed FPS : http://gafferongames.com/game-physics/fix-your-timestep/

Cirrus Minor

  • Full Member
  • ***
  • Posts: 121
    • View Profile
Re: Finished my First Pong Game using SFML (Mac OS X)!
« Reply #3 on: June 02, 2014, 07:26:40 am »
Congratulations for your first SFML game !

I like this retro touch ! Well done  :)

AndreeU17

  • Jr. Member
  • **
  • Posts: 53
    • View Profile
Re: Finished my First Pong Game using SFML (Mac OS X)!
« Reply #4 on: June 02, 2014, 06:04:16 pm »
I didn't try your game, but from the screenshots it looks good.  :)

A few things I would suggest you do is first learn to use some form of source control and instead of putting all the code in the initial post upload it using source control to a hosting site a provide a link.

Secondly looking at the code I suggest you learn about object oriented programming and how to encapsulate different functions into classes. At the moment you have duplicated code which could be eliminated if you broke your program into classes. Also making a change like this would force you to think about object ownership and what should be doing what instead of letting everything hang out in the main function. (Global variables are not a great idea and should be avoided  ;))

Oh and one more thing, you need to implement delta time measurement. At the moment your movement code is tied to FPS and any change in FPS will cause your paddle to move at different speeds. For example if I run your code on a 10 year old PC that can't pull 30 FPS the paddles would move very slowly. Or if I ran it on my i7 laptop everything would fly off the screen.  :P

Yeah I was thinking about creating a class an a constructor that specifies a paddles position, size & color as I was directed by a user on sfml! I appreciate the comments, I will redesign it since I want to learn effective coding ! Also I need to look more into frames since I totally forgot, also that explains why it's faster in my PC compared to laptop !! I appreciate and I will repost this game hopefully in a week since I'm on break from school !

Thanks also should I add textures and sprite to give it a touch of my own? All this will eventually be added to my portfolio so I'm planing to do the best job !!! Even if I have to redesign it 10x anyways thanks mate !!! Everyone gave they're greatest opinion and it's well appreciated !

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
Finished my First Pong Game using SFML (Mac OS X)!
« Reply #5 on: June 02, 2014, 08:42:57 pm »
Here's a famous article that would benefit you greatly: http://gafferongames.com/game-physics/fix-your-timestep/
Current Projects:
Technoport

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Finished my First Pong Game using SFML (Mac OS X)!
« Reply #6 on: June 02, 2014, 08:57:59 pm »
Thanks also should I add textures and sprite to give it a touch of my own?

Only you can answer that, and to answer it you need to determine how you want it to look. If you want a textured game look then with all means go with it. Personally (maybe because I am not an artist) I prefer a plain untextured retro look in these types of games.  ;)


Here's a famous article that would benefit you greatly: http://gafferongames.com/game-physics/fix-your-timestep/

You should really read what has already been posted before saying the same thing.  :P
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
Finished my First Pong Game using SFML (Mac OS X)!
« Reply #7 on: June 02, 2014, 11:35:20 pm »
You're right, I just skimmed his last post. Sorry about that :D
Current Projects:
Technoport

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Finished my First Pong Game using SFML (Mac OS X)!
« Reply #8 on: June 03, 2014, 10:07:05 pm »
Congratulations on finishing a project. That's a lot harder than most people think.
It is easy to start a project. It's a bit harder, but not too hard, to keep working on it. It is very hard to finish it and getting it to the point where you can declare it "done" - congratulations on that.
Even though it is a simple game; being able to finish is an important skill - well done.