In this first playable game project we will build a very simple Pong clone. If you don’t know what Pong is then you are much younger than me and you should take a look at its appearance and history before continuing. We will use everything we learnt about C++ Functions and OOP to create a class for each of the objects of the game (a bat and a ball) as well as functions within these classes to make our bat and ball behave as we expect.[widgets_on_pages id=”udemy_advert_cpp_1″][widgets_on_pages id=”udemy_code_details”]
To get started we need to create a new project, complete with all the required properties to work with SFML. If you haven’t completed the Building your first SFML game project you will need to do that first. In that project, we created a Visual Studio project template, so that starting a new SFML project is now a two-minute job instead of a half an hour long chore.
The next steps set up our new SFML C++ project.
- Open Visual Studio and from the main menu choose File | New Project. In the left-hand menu click C++. Select the HelloSFML template and name your project Pong.
- Now click OK.
- Right-click the HelloSFML.cpp file under the Source Files heading from the right-hand Solution Explorer window. Choose Rename and rename the file to Main. This is a more appropriate name as this will indeed be our “main” source file.
- Open Main.cpp by double-clicking it. Now delete all of its contents as we will be starting fresh and discussing all of the code as well.
- Copy & paste the SFML .dll files in the YOUR_DRIVE:\SFML\bin to YOUR_DRIVE:\Visual Studio Stuff\Projects\Pong\Pong.
Now we can get coding.
[widgets_on_pages id=”bcgp_cfgp_gpp”]
Building the Bat class
In the tutorial on coding a C++ class, we mentioned that we should separate the declaration from the definition. As we create the Bat class we will see exactly how to do this. Perhaps unsurprisingly the Bat class will represent the player’s bat.
Right-click on Header Files in the Solution Explorer window. And select ADD | New Item. This step is shown in the next image.
Now select C++ Header File (.h) (1) and enter bat.h in the Name: field (2) as shown next.
Click the Add button (3) and our new file will be created for us.
Coding bat.h
Now we will code the class declaration. This will look a bit different to how it did in the Introduction to OOP in C++ tutorial but when we move on to the definition which will go in a separate file (Bat.cpp) things will look more familiar and will make more sense.
Take a look at the next block of code. This will be the entire contents of our bat.h file. In it, we #include the SFML library that we need, declare some member variables that are private and then declare some functions which are public.
We will discuss the variables and functions in more detail when we use and implement them in Bat.cpp in a minute. For now just note their names, parameters and return types. We have a Vector2f called position which will indeed hold the horizontal and vertical position of the player’s bat. We have an SFML RectangleShape which will be the actual bat that appears on the screen and we have a float called batSpeed that is the number of pixels per frame that the bat can move at.
The functions are as follows. A function called Bat which we learnt is the constructor because it has the same name as the class. Notice it takes two float parameters. This is perfect for initializing the position on the screen when we first create an Bat object. Next is the getPosition function which returns a FloatRect, the four points which define a rectangle. Then we have getShape which returns a RectangleShape. This will be used to return to the main game loop batShape, so it can be drawn.
Finally, we have the moveLeft, moveRight and update functions which take no parameters and return no values. We will see how these are useful to us very soon.
Add all this code we have just discussed to the bat.h file.
#pragma once #include <SFML/Graphics.hpp> using namespace sf; class Bat { private: Vector2f position; // A RectangleShape object RectangleShape batShape; float batSpeed = .3f; public: Bat(float startX, float startY); FloatRect getPosition(); RectangleShape getShape(); void moveLeft(); void moveRight(); void update(); };
Now we can get to the real functionality of the Bat class.
Coding bat.cpp
Let’s create the file then we can start discussing the code. Right-click the Source Files folder in the Solution Explorer window. Now select C++ File (.cpp) and enter Bat.cpp in the Name: field. Click the Add button and our new file will be created for us.
We will divide the code for this file into two to make discussion of it simpler. Take a look at part one of the code and explanation below.
bat .cpp part one
In this first part, we can see that we #include bat.h. This makes all the functions and variables that were declared previously in bat.h available to us. Then we implement the constructor. Notice we use the syntax Bat::Bat as the function name to make it clear we are using the Bat function from the Bat class.
This constructor receives two float values, startX and startY. The next thing that happens is we assign these values to position.x and position.y. The Vector2f named position now holds the values that were passed in and because position is a member variable, these values are accessible throughout the class. Note however that position was declared as private and will not accessible in our Main.cpp file. Not directly anyway. We will see how we resolve this issue soon.
Finally, in the constructor, we initialize our RectangleShape called batShape by setting its size and position.
Add the code we have just discussed to the Bat.cpp file.
#include "stdafx.h" #include "Bat.h" // This the constructor and it is called when we create an object Bat::Bat(float startX, float startY) { position.x = startX; position.y = startY; batShape.setSize(sf::Vector2f(50, 5)); batShape.setPosition(position); }
Now for the rest of the functions.
bat.cpp part two
We have five more functions that we need to code. Let’s go through them one at a time. Refer to the next block of code during this discussion.
First, we have the getPosition function. All it does is return a FloatRect to the code that called it. The batShape.getGlobalBounds, itself returns a FloatRect that is initialized with the coordinates of the four corners of the RectangleShape, batShape. We will use this function in Main.cpp when we are determining whether the ball has hit the bat.
Next, we have getShape. All this function does is pass a copy of batShape to the calling code. This is necessary so we can draw the bat in Main.cpp. When we code a public function with the sole purpose of passing back private data from a class we call it a getter function.
Now we can look at the moveLeft and moveRight functions. All they do is add or subtract batSpeed from position.x. This means that every time we call either moveLeft or moveRight we will tweak the horizontal position of the player’s bat. This is just what we need.
The last function in the Bat class is update. We will call this function one per frame of the game. The update function will grow in complexity as our game objects get more complicated. For now, all we need to do is set the position of batShape with whatever the current values held in position happen to be.
Add the code we have just discussed to the Bat.cpp file right after the previous code we added.
FloatRect Bat::getPosition() { return batShape.getGlobalBounds(); } RectangleShape Bat::getShape() { return batShape; } void Bat::moveLeft() { position.x -= batSpeed; } void Bat::moveRight() { position.x += batSpeed; } void Bat::update() { batShape.setPosition(position); }
That’s it for the Bat class. What we have effectively done is this. We have a RectangleShape that is initialized to a position on the screen that will be determined when we create a Bat. We have the ability to change the position variable to the left or right at any time we choose by calling moveLeft or moveRight. Once per frame the RectangleShape will be moved to whatever position is contained within the position variable. The code in Main.cpp also has the ability to get a copy of this RectangleShape by calling getShape, this is ideal for when we need to draw it. The code in Main.cpp can also call getPosition to get the coordinates that define the four points of the bat which we will use for detecting collisions with the ball.
Let’s make a ball.
Building the Ball class
As we did for the Bat class we will create a new .h file to hold the class declaration for our Ball class. Right-click on Header Files in the Solution Explorer window. And select ADD | New Item. Now select C++ Header File (.h) and enter ball.h in the Name: field. Click the Add button and our new file will be created for us.
Coding ball.h
Take a look at the next block of code. We can see we have another Vector2f for holding the position of the ball. We have another RectangleShape which will be used to draw the ball and we have two float variables xVelocity and yVelocity to represent the horizontal and vertical speeds of the ball. These variables are all private so not accessible directly from outside the code of the class.
We also have a selection of public functions. The one named Ball will obviously be our constructor. Just like our Bat constructor, it takes two float parameters that will set the starting position. Just as we did with the Bat class we have a getPosition and getShape functions that return a FloatRect and RectangleShape respectively.
Now we have the getXVelocity getter function which will return the value of some private data to the calling code.
Now we have something a little bit different that won’t make complete sense until we actually use them. When we make a quick and simple version of a game like Pong it is possible to foresee a couple of problems we will encounter:
- What happens when the ball hits the side of the screen?
- What happens when the ball hits the bat or the top of the screen?
- What happens when the ball hits the bottom of the screen?
The three functions reboundSides, reboundBatOrTop and hitBottom will deal with the above the events. We will see exactly how in a minute.
Finally, just like in the Bat class we have a update function that will be called once per frame of the game to move the ball around.
Add the code we have just discussed to the ball.h file.
#pragma once #include <SFML/Graphics.hpp> using namespace sf; class Ball { private: Vector2f position; // A RectangleShape object called ref RectangleShape ballShape; float xVelocity = .2f; float yVelocity = .2f; public: Ball(float startX, float startY); FloatRect getPosition(); RectangleShape getShape(); float getXVelocity(); void reboundSides(); void reboundBatOrTop(); void hitBottom(); void update(); };
Next for the implementation.
Coding ball.cpp
Let’s create the file then we can start discussing the code. Right-click the Source Files folder in the Solution Explorer window. Now select C++ File (.cpp) and enter Ball.cpp in the Name: field. Click the Add button and our new file will be created for us.
We will divide the code for this file into two to make discussion of it simpler. Take a look at part one of the code and explanation below.
ball.cpp part one
Here we have the constructor and it does exactly the same thing that the Bat constructor did. It captures the required starting position passed in as parameters, sets the size and position of the RectangleShape that will represent the ball on the screen. Add the code below to Ball.cpp.
#include "stdafx.h" #include "Ball.h" // This the constructor and it is called when we create an object Ball::Ball(float startX, float startY) { position.x = startX; position.y = startY; ballShape.setSize(sf::Vector2f(10, 10)); ballShape.setPosition(position); }
The next part of the code is much longer but not complicated in any way.
ball.cpp part two
[widgets_on_pages id=”udemy_advert_cpp_2″][widgets_on_pages id=”udemy_code_details”]
There are seven more functions in
Ball. Let’s run through them one at a time.
First getPosition is a getter which returns a FloatRect to the calling code. We will soon see how we use the getPosition functions from Bat and Ball to do collision detection in our Main.cpp code.
Next we have getShape which does exactly the same job that the getShape function in the Bat class did. It returns a copy of the RectangleShape to be drawn on the screen.
The getXVelocity function is a getter for the xVelocity member variable and does it’s one simple job of returning the value stored in xVelocity.
The reboundSides function will be called every time the ball hits the sides of the screen. Look at the code inside it. It simply makes xVelocity the negative of whatever it currently is. So if it is positive (moving right) it will become negative and move left, and vice versa as well.
The ReboundBatOrTop function is a tiny bit more in-depth, but not much. The first line of code in this function position.y -= (yVelocity * 30) directly alters the position.y value by the equivalent of 30 frames of movement and prevents the ball from getting stuck on the bat. This is a common bug when using simplistic physics like we are here. The second line of code reverses the direction of the ball.
The hitBottom function is very straight forward as well. First, it sets the position.y value to 1, effectively placing the ball back at the top of the screen and the position.x to 500, placing it around about the middle horizontally.
Finally, for the Ball class, we have the update function which is a bit more in-depth than the update function in the Bat class. Unlike a bat, a ball is always moving. So the first thing that happens each frame is we update position.x and position.y by xVelocity and yVelocity. Then, just as we did for the Bat class, we update the position of the RectangleShape with the new values stored in position.
Add the code we have just discussed directly after the previous code, into the Ball.cpp file.
FloatRect Ball::getPosition() { return ballShape.getGlobalBounds(); } RectangleShape Ball::getShape() { return ballShape; } float Ball::getXVelocity() { return xVelocity; } void Ball::reboundSides() { xVelocity = -xVelocity; } void Ball::reboundBatOrTop() { position.y -= (yVelocity * 30); yVelocity = -yVelocity; } void Ball::hitBottom() { position.y = 1; position.x = 500; } void Ball::update() { // Update the ball position variables position.y += yVelocity; position.x += xVelocity; // Move the ball and the bat ballShape.setPosition(position); }
Coding Main.cpp
At last, we are in a position to put our new classes to work and make the Pong game come to life. Switch to the Main.cpp file in Visual Studio and we can discuss the first part of six parts that go to make up the code for this file.
We will be displaying some text known as a HUD (Heads Up Display) in this game which will show the player’s score and remaining lives. For this, we need a font.
- Download this free-for-personal-use font from http://www.dafont.com/theme.php?cat=302.
- Click the Download button.
- Unzip the download.
- Add the DS-DIGIT.ttf file into the YOUR_DRIVE:\Visual Studio Stuff\Projects\Pong\Pong folder.
Main.cpp part one
Add all the following #include directives and the using statement to the top of the file. Notice that we are including our two new classes by the code #include "bat.h" and #include "ball.h".
// These "include" code from the C++ library and SFML too #include "stdafx.h" #include "bat.h" #include "ball.h" #include <sstream> #include <cstdlib> #include <SFML/Graphics.hpp> // Avoid having to put sf in front of all the SFML classes and functions using namespace sf;
Onwards to part two.
Main.cpp part two
In the next block of code, we create a window that is 1024 x 768 pixels in size. As this is going to be a working game we declare two int variables to keep track of the player’s lives and score. Then we create an instance of a Bat and a Ball. We pass in appropriate starting positions for each, as required by their constructors which we coded previously.
All the rest of the code in part two deals with displaying the HUD (score and lives) on the screen. Some of this we have seen previously in the Hello SFML project but some of it is new. We create an SFML Text object called text and an SFML Font object called font. We then load the font that we placed in the project folder a few moments ago. Next, we use setFont to assign our new font to our hud Text object. Next, we set the size followed by the color of the font using setCharacterSize and setFillColor functions.
Add the code we have just discussed to Main.cpp.
// This is where our game starts from int main() { int windowWidth = 1024; int windowHeight = 768; // Make a window that is 1024 by 768 pixels // And has the title "Pong" RenderWindow window(VideoMode(windowWidth, windowHeight), "Pong"); int score = 0; int lives = 3; // create a bat Bat bat (windowWidth / 2, windowHeight - 20); // create a ball Ball ball(windowWidth / 2, 1); // Create a "Text" object called "message". Weird but we will learn about objects soon Text hud; // We need to choose a font Font font; // http://www.dafont.com/theme.php?cat=302 font.loadFromFile("DS-DIGIT.ttf"); // Set the font to our message hud.setFont(font); // Make it really big hud.setCharacterSize(75); // Choose a color hud.setFillColor(sf::Color::White);
We are ready to enter the game loop!
Main.cpp part three
In this third part of the Main.cpp code we will handle the player’s input. There are two ways to handle player input in SFML and I encourage you to research them both further(event handling and keyboard input). Here we use both. First, in the while loop that has the condition window.pollEvent(event), we check if any messages have been sent to the operating system and subsequently passed on to SFML. We could check for lots of different types of messages here but content ourselves by checking if the window was closed. If it was we call window.close and the game will quit.
Next, we explicitly check for the current state of some of the keys at the given moment (as opposed to in a queue). Look carefully at the various if statements and the simple but important code that we call when the if statement is true.
If Keyboard::Left, bat.moveLeft(). Next is if Keyboard::Right, bat.moveRight(). What is happening here is that once each frame we check to see if the left or right arrow (cursor) keys are currently being pressed and if they are we call the appropriate moveLeft or moveRight functions on our bat object. This will have the effect of updating the position.x variable that we coded previously.
// This "while" loop goes round and round- perhaps forever while (window.isOpen()) { /* Handle the player input ********************************************************************* ********************************************************************* ********************************************************************* */ Event event; while (window.pollEvent(event)) { if (event.type == Event::Closed) // Someone closed the window- bye window.close(); } if (Keyboard::isKeyPressed(Keyboard::Left)) { // move left... bat.moveLeft(); } else if (Keyboard::isKeyPressed(Keyboard::Right)) { // move right... bat.moveRight(); } else if (Keyboard::isKeyPressed(sf::Keyboard::Escape)) { // quit... // Someone closed the window- bye window.close(); }
We will soon see the knock-on effect of changing the position.x variable. First let’s work out if any collisions have taken place.
Main.cpp part four
This next block of code comprises four main if statements although one of them has a further nested if statement.
The first main if statement checks whether the ball has hit the bottom of the screen. It does so by using the getPosition function we coded in the Ball class and checking the top variable of the returned FloatRect to see if it has exceeded the height of the screen. If it has then a number of things happen next. First, we call the hitBottom function to reposition the ball at the top of the screen and reverse its direction, then we subtract a life from the player. Next, still inside the if statement that determined the ball hit the bottom, we check if the player has run out of lives. If the player has run out of lives we reset the score to zero and the lives back to three. The player is essentially starting again.
In the next main if statement, we find out if the ball has hit the top of the screen by checking if the top of the ball is at a position less than zero. If it has, all we need to do is call the reboundBatOrTop function which reverses the direction. Furthermore, we add a point to the player’s score.
The next if statement checks for a collision on the left or right-hand side of the screen. The condition uses the logical OR || operator so it can test for the ball’s left-hand side being less than zero or the ball’s right-hand side being greater than the width of the screen in one condition. If the condition is true, all we need to do is call the reboundSides function on ball and the ball’s direction is reversed.
The last if statement is a little bit different to the others because it detects if the ball has hit the bat. It achieves this using the getPosition function just like the other collision detecting if statements did but this time it chains that function call with another call to a function called intersects. Take a look at this if condition closely and we will explore what is going on.
The ball.getPosition() part of the code returns a FloatRect object, just like we coded it to do. Now, because FloatRect, itself is a class, it too has functions that can be called. The returned FloatRect from getPosition is used to call its intersects function passing in as a parameter the returned FloatRect from bat.getposition. Essentially we are saying, does the ball intersect the bat? If it does the condition is true and we call the reboundTopOrBat function which reverses the ball and sends it heading off towards the top of the screen again.
Enter the following code after the previous code we entered.
/* Update the frame ********************************************************************* ********************************************************************* ********************************************************************* */ // Handle ball hitting the bottom if (ball.getPosition().top > windowHeight) { // reverse the ball direction ball.hitBottom(); // Remove a life lives --; // Check for zero lives if (lives < 1) { // reset the score score = 0; // reset the lives lives = 3; } } // Handle ball hitting top if (ball.getPosition().top < 0) { ball.reboundBatOrTop(); // Add a point to the players score score++; } // Handle ball hitting sides if (ball.getPosition().left < 0 || ball.getPosition().left + 10 > windowWidth) { ball.reboundSides(); } // Has the ball hit the bat? if (ball.getPosition().intersects(bat.getPosition())) { // Hit detected so reverse the ball and score a point ball.reboundBatOrTop(); }
Nearly there!
Main.cpp part five
The final part of updating the current frame requires us to call the update functions of both the bat and the ball objects. In the bat update function, we simply update the position and in the ball update method we move the ball in the appropriate direction and then update its position. They are now ready to be drawn.
The last part of the code in this block is totally new. We are declaring an object of type stringstream and calling it ss. We can use ss to concatenate (add together) characters and numerical values to create a single string-like object. This, as we will see, is perfect for displaying a dynamic score and number of lives in our hud object. The slightly strange looking ss << "score:" << score... code does exactly this. We then set the String held in ss to hud which of course is a Text object.
Add the code we have just discussed.
ball.update(); bat.update(); // Update the HUD text std::stringstream ss; ss << "Score:" << score << " Lives:" << lives; hud.setString(ss.str());
Let’s draw.
Main.cpp part six
First, we clear the previous frame with window.clear, then we draw the bat and the ball using window.draw passing in a call to the getShape function of each of our two objects. As these functions return the appropriate RectangleShape the effect is that they are drawn on the screen. We then call window.draw and pass in hud to draw the HUD. Finally we call window.display to draw the current frame to the screen.
/* Draw the frame ********************************************************************* ********************************************************************* ********************************************************************* */ // Clear everything from the last frame window.clear(Color(26, 128, 182,255)); window.draw(bat.getShape()); window.draw(ball.getShape()); // Draw our score window.draw(hud); // Show everything we just drew window.display(); }// This is the end of the "while" loop return 0; }
Run the game and you will be able to entertain yourself, just as I did when I was four years old.
What can we do better next time?
There are a few flaws with our game. Some are obvious and some not quite as obvious.
If you were to run this game on a super-fast PC and then run it on an ageing laptop, you would see that the game actually runs at totally different speeds. A professional game would control the number of frames per second (FPS) so that it ran exactly the same regardless of the speed of the PC. This is not especially tough and we could have incorporated it in this project. I just thought there were enough new ideas already.
Another issue is that we have only used boring shapes for all the game objects. This isn’t too much of an issue for a Pong clone but we will need to use real graphics if we are going to win Indie game of the year anytime soon.
There is also the issue that by creating and managing each and every object individually we will eventually have an extremely cluttered code base. Imagine if we did a Zombie Survival game with dozens of Zombies. How would we manage the zombies? Would we have dozens of zombie objects like z1, z2, z3, z4… etc.?
We will be improving on all these issues and solve the problems as we progress with more C++ tutorials and the next SFML project.
Note to self: Zombie Survival game seems like a good choice for next project.
Thanks alot.It doesn’t work well for me. The bat rectangular desapear when i press the left or the right arrow.
Hi Joory, I just tested it and couldn’t emulate the problem you describe. Have you copy & pasted to make sure the code is exact? I will try and help you get this working. Thanks for letting me know of the issue.
Check your moveLeft and moveRight functions – maybe you typed “position.y” somewhere there and when you pressed an arrow key, it moved off the screen. (I had the same problem)
So I have a general question. Professionally, like being a video game developer, is most of your time spent organizing code from pre-established software to work for you? When does one actually have to write new code?
I ask because in looking through some Cryengine stuff, it seems most entry level stuff is about using Cryengine’s built-in assets, and taking assets from other games, and then using editing software to put it all together. At that level, what part does coding really play? Like in the process of building a game in Cryengine, for what reasons would I need to write, or even assemble, the code itself?
The answer is- it varies massively. If you were a one-man indie doing a 2d game, most of your day would be coding. If you were working with a game engine like cryengine it would depend on your role. You could be coding or using built in assets. Either way, learning to code is a good start. Hope this helps a bit.
All of your tutorials have been an amazing help! Keep up the good work!
Many thanks.
Hi, I ran into a bit of a problem right at the beginning – don’t seem to have the Visual C++ tab, so can’t add the C++ Header File… how can I rectify this?
Hi there,
If there is no C++ option at all, it might be because it wasn’t installed. Double check the setting up Visual Studio project and make sure to get the right version.
I have the same problem — I don’t have anything to add in header file but I am pretty sure I have followed every step to install it. Is it because my system is Windows 10?
Hi there,
Not sure what could be at fault here. Windows 10 shouldn’t be a problem. Have you made the SFML template project?
hello can anyone help me i cant find where to start! please help me
Hi,
The C++/SFML projects start with setting up Visual Studio and SFML and the c++ tutorials start here. They compliment each other. Thanks.
Hi,
so yeah, I re-did the project setup and the project template tutorials a couple of times, but still don’t have the C++ option visible.
Which step of the whole process is actually responsible for adding it? Is it embedded in Visual studio or is it just the question of proper template definition?
Can something be done to add the C++ item class in itself or is it an integral part of the software installation process?
Can I take existing *.h header files, re-name them and edit them accordingly as a work-around to not having the C++ option installed?
Hi there,
I am really confused how this is happening and am genuinely stuck for a solution. Maybe I am misunderstanding you. How did you complete the template tutorial without creating a new C++ project?
Hi,
I had the same problem where I couldn’t add the header file because the C++ option was not visible.
I found a solution here:
https://connect.microsoft.com/VisualStudio/feedback/details/800202/visual-studio-2013-express-rc-no-items-found-in-the-add-new-item-dialog
This workaround was posted in 2013 and says they’d fix the issue for the next Visual Studio release. I’m using VS 2015 yet the bug is still there, but at the least the old workaround still works, too.
Brilliant, this has been bemusing me. Thanks Jan!
Thanks a lot Jan! I too had the same problem.
No problem.
Thank YOU for these great tutorials! I hadn’t expected to find anything of this quality on the web for free. And it’s fun to read because you sound like you’re really enjoying what you’re doing! Are you a professional in the gaming industry?
Anyway, I’m definitely considering pre-ordering your book
Thanks for your kind comment! Made my day. I am not an industry pro just a very keen amateur trying to turn his hobby into a living.
Hi John,
I just wanted to know if we can code a yes or no message box saying ‘game over’ and ‘do you want to try again’ after all lives are lost. Something like that to make it more fun.
And thanks a lot for these great tutorials. They have helped me a lot.
The easiest way to add a message would be to use a nice big font and SFML Text. You could use a boolean to decide when to display the message perhaps, “GAME OVER, press space to play again”. Then of course you can code the space key to restart the game.
This tutorial was updated on 6th September 2016 to work with SFML 2.4. In particular, setColor has been replaced with setFillColor.
Hi. Great tutorials. They are helping my speed along.
I have a problem though
I am getting this error.
Severity Code Description Project File Line Suppression State
Warning C4244 ‘argument': conversion from ‘int’ to ‘float’, possible loss of data CPong xxx\xxx\xxx\xxx\main.cpp 23
These are the lines of code it is talking about………………
Bat bat(windowWidth / 2, windowHeight – 20);
Ball ball(windowWidth / 2, 1);
in main.cpp
Any help would be great thanks!
Actually scratch this. I figured it out.
I had to add #define NOMINMAX to the top line of main.cpp.
Awesome Tutorials. I keep hearing about your book, is it similar to these tutorials? Definitely would like to have it if so.
Thanks very much Caterpillar! More soon.
Awesome! Going to do the Part 8 right now and the Simple C++ Engine too.
I have been writing it out while doing them, it helps a lot instead of copy/paste.
I originally got rid of my warnings by changing those 2 lines I posted above to:
Bat bat(windowWidth / 2.0f, windowHeight – 20.0f);
Ball ball(windowWidth / 2.0f, 1.0f);
that got rid of the warnings but there were still the errors there. That’s where I found the NOMINMAX.
Will I always have to use “stdafx.h” and #define NOMINMAX for all my SFML projects? Most other learning tutorials I’ve been on has never used. #include “stdafx.h” as far as I know? Maybe I just don’t remember.
Thanks for the tips forest! Regarding stdafx, it’s not straight forward. It is simple just to include it. Here is a bit more about it if you want to learn more.
http://stackoverflow.com/questions/4726155/whats-the-use-for-stdafx-h-in-visual-studio
Hello there,
I have been loving your SFML tutorials, thank you for putting out such great content! Can’t wait to start the game engine tutorial that was just posted.
Currently I’m having an issue with compiling the files for the pong game.. I’m currently working from Linux Ubuntu and have been compiling the previous projects in the Command Line and it has been working fine. I think I am just having trouble compiling my files in the right order.. Any help with this would be greatly appreciated. Thank you for your time!
Hi Brian,
Try compiling them individually. Ball, Paddle then main. Once you have the .o files then try linking them. Also, make sure you have correctly linked to/put in the right folder all the SFML files too. I haven’t used Linux for a long time now so I would hesitate to try and give specific steps as I would probably make things worse.
I hope this helps,
John
Hi John,
All of your tutorials are awesome but I am getting a problem in this one. Please help me out.
Error C2065 ‘Bat': undeclared identifier
Error C2146 syntax error: missing ‘;’ before identifier ‘bat’
Similar error for ‘Ball’ and ‘ball’ in the lines:
Bat bat(windowWidth/2, windowHeight – 20);
Ball ball(windowWidth/2, 1);
wherever ‘ball’ and ‘bat’ are used to invoke functions of class ‘Bat’ and ‘Ball’, the system is generating an error.
I cant figure out where I am going wrong.
And I was not able to add header file and c++ files directly as you have shown. I did that like this: File->New File-> header file then save this header file and then in the solution menu Header file-> Add Existing item and then select the header file that I have saved.
Where exactly is the problem????
Hi Aditi,
Make sure you have included bat and ball at the top of the main source file and spelt the file names exactly the same. Try cleaning and rebuilding from the build menu.
I hopr this helps a bit.
Yes I rebuild the file and it runs fine now. Thank you so much.
And your tutorials are just awesome. Keep up the amazing work.
Thanks Aditi. Really pleased you got it working.
This post is really interesting. I have bookmarked it.
Do you allow guest posting on your site ? I can write high quality articles for you.
Let me know.
Hi Rebecca,
Feel free to submit your ideas here: http://gamecodeschool.com/contact-us/
Hello! My name is AnnaMarkova, our company need to advertise on your website. What is your prices? Thank you. Best regards, Mary.
Hi there,
Please contact me via email with some more info about what you would like to do.
Thanks.
Hi,
I just wanted to say these tutorials have been great for me. I have done coding like MATLAB, Python, and such for a while and decided I wanted to code games. I looked all over for tutorials on how to set up an appropriate IDE and how to actually code and just could not find one that suited me. These tutorials are very clear and very efficient at teaching what it intends to. Thanks for making these and putting these up. I’m sure I’m not the only one who appreciates your work.
Hi ZachR,
Thanks very much for your kind comment.
Hey
Ive just made this pong game, and i wanted to try and expand it slightly, where if the score >= 3, the speed doubles, to do this i made the floats xVelocity, yVelocity public, and got rid of the getter functions, then i added a function to the ball.cpp file such as
float Ball::increase()
{
xVelocity = xVelocity * 1.25;
yVelocity = yVelocity * 1.25;
return xVelocity, yVelocity;
}
then in the while loop on main.cpp :
if (score >= 3)
{
ball.increase();
}
When the score gets the 3, the ball disappears and the lives count down and reset very rapidly. Why is this happening?
Hi John,
I don’t understand what this part is return xVelocity, yVelocity;
If ball.increase is called every frame that the score is >= 3 then the ball will quickly accelerate(if it is being called each frame) to an impossible to see speed within a fraction of a second. Could this be happening?
Wow, how did I not see it will be looped every frame!
How do you go about increasing a variable in the game loop only one time, without this happening?
The reason I returned is because I’m used to fortran functions where generally you have an output.
I guess I should go over the function tutorial again!
To solve this problem you could make the speed a multiple of the score.
Hi John, I really like your tutorials but i have encountered some problems. Stdafx.h doesen’t work and visual studio recommends me to include pch.h. I have done this and now i get this error :
“Cannot open precompiled header file: ‘Debug\pong.pch': No such file or directory”
Could you please help me ?
Try rebuilding the project as should the precompiled header or try selecting Build/Clean Solution first.
If not try turning off precompiled headers. Project settings | C/C++ | Precompiled headers | Not Using Precompiled Headers.
Failing the above go back to the first to sfml tutorials that talk about configuring the project, get the first project working and then try pong again.
Hope this helps.
How does the co-ordinate system for the window works? I need to know this because I am getting confused at part 4 of Main.cpp where we need to handle the ball hitting the bottom.
Does the origin of the window lies at the top left corner?
THe coordiantes start at 0,0 in the top left corner.
Yeah, thanks. I figured it out later.
I’m really happy that I actually found some nice tutorial on game development with C++ and would love to see some more tutorials from you covering various aspects of game development. Very nice work,man.
Also, please suggest where/how to proceed now to learn more in this field. Should I move to Unity or stick to SFML right now ?
What you use depends on your goals. If it is your goal to build a first person shooter for example then Unreal Engine or Unity are your best choice. If you are new to c++ and want to learn in a gaming context then SFML is perfect. Also consider that Unreal Engine demands a good understanding of C++.
Have a look at this article which discusses some of your options.
http://gamecodeschool.com/blog/making-games-where-do-i-start/
How is the getXVelocity() function actually affecting the game? I would like to know this because I can’t see this function being used anywhere in Main.cpp directly or indirectly. Please do enlighten me in case I’ve missed out its use.
Thanks in advance.
It just returns the value of velocityx to the calling code which means the variable can be private which is better design.
just wanted to say thank you! cant wait to go futher and see what else i can learn! i had a small issue with the bouncing of the sides and top because i needed to go away from my pc but actually knew myself where in the code it would probally be and fixed it by myself, gives a great feeling! (turned out i continued after the 2 bits for the bounce in the main.cpp so the program didnt give an error or anything)
Thanks Rowan. Really pleased you are finding it satisfying. I solved a programming problem myself today and I know the exact feeling you are talking about.
When I run the program Im just getting the same error for some reason? Heres a screenshot of the errors https://i.gyazo.com/bd13e699287e606d5d95d930db79c43a.png. I did everything right and put the dll files in the pong folder and made the c++ and header files? Why is it erroring?
This could be caused by missing #include… lines.
I deleted #include “stdafx.h” because it was erroring, but I kept all the other ones:https://i.gyazo.com/fb7f916a4aa338ba305ad1ab4359fae1.png.
Your #include lines are correct. This could be a tricky one to solve. I suspect there is a typo somewhere and Visual Studio is misinterepreting things in one or more files. It could be a missing curly brace or semicolon but not necessarily where the error you showed me states it is. Check each individual file for an error (if you haven’t already). Next, check for any missing semicolons (starting with the places mentioned in the error you posted). Next make sure all your curly btrackets match up as a pair. You can highlight a curly bracket an Visual Studio will highlight the matching one. After this I can only suggest copy and pasting sections of the code again to see if you can identify where the error is.
If you google “C++ missing semicolon before identifier with undeclared identifier” there are lots of examples of possible causes. I had an error like this a few days ago and the error VS gives you is often not the real error. Let me know how you get on.
I have sent you an email so you can email me your files if you want to.
There is a slight bug in the game, is that if you are able to get the ball to hit just on the side of the bat, it will kind or glide through the bat. The reboundBatOrTop will cause it the bounce within the bat and the interset will continue to count points, getting a few hundred points in an instant.
Yes you are right the collision detection could be improved greatly. I might get round to doing something more advanced soon. Thanks for your comment.
It seems that in 2020 that the collision code is a little broken. I had to change the < operators to == for the collision to work, as well as to get rod of the .intersect function in "if (ball.getPosition().intersects(bat.getPosition()))" needs to be changed to "if (ball.getPosition() == bat.getPosition())". Is there a reason for this?
Hi,
I was wondering how can I add multiple balls? I have previous c++ experiences form ue4, but it is kinda different from SFML and I decided to learn it (great tutorials btw).
I should be able to call the constructor multiple times, right? But it seems not to work… I guess i am messing up something
Something like
// create a ball
Ball ball(windowWidth / 2, 1);
Ball ball2(windowWidth / 2 + 20, 1);
…
…
ball.update();
ball2.update();
…
…
window.draw(ball.getShape());
window.draw(ball2.getShape());
You will also need to handle the collision detection again.
All the best,
John
Great Website.Thanks for Tutorial.Looking forward to complete this series.
Many thanks
Love this so much, you’re awesome. I’ve figured out how to swap the rectangle shape of the ball for a circle as well, just using a bit of common sense and your tutorial.
I was wondering, if we wanted to save these as little stand alone exe files, would you be able to explain it a bit? I did try to use ‘release’ instead of ‘debug’ and changed the added libraries from -d to -s according to how I saw them in the folder (for release only) but I was getting a billion errors about unresolved tokens. Tried to find some tutorials on it, but they’re a bit over my head as far as the jargon goes.
So I try to compile the code but I get all these errors about how I can’t further define the functions in bat.ccp and ball.ccp because they’ve already been defined in the header files. However, I typed them as you have. I’m really confused.
i get the error that all of these functions have already been defined in the main.obj
Is the following code in the .cpp file
Bat::Bat(float startX, float startY)
{
position.x = startX;
position.y = startY;
batShape.setSize(sf::Vector2f(50, 5));
batShape.setPosition(position);
}
If so it should work. Unless the class is spelt differently, perhaps just a wrong cased letter.
You were exactly right and I found that same solution when I first completed this project.
Sorry for the newbie hassle.
Hello Mr. Horton,
are you still active on these tutorials?
thank you very much by the way for all this work and for people like us who don’t have a clue and started coding at old age just because we want to. I have an issue if you can help me (Severity Code Description Project File Line Suppression State
Warning C26812 The enum type ‘sf::PrimitiveType’ is unscoped. Prefer ‘enum class’ over ‘enum’ (Enum.3). Pong D:\4.C++\Visual Studio Stuff\Projects\Pong\Ball.cpp 21 )
i just copy ..i dont know why this came up.
thank you in advance!
excuse me the previous was a warning ..the error is that one.. sorry about that.. (Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol _main referenced in function “int __cdecl invoke_main(void)” (?invoke_main@@YAHXZ) Pong D:\4.C++\Visual Studio Stuff\Projects\Pong\MSVCRTD.lib(exe_main.obj) 1 )
Hello again,
i have managed to avoid errors (using #include “SFML/Window.hpp” instead of #include “stdafx.h”, i don’t know where to find std.) but the play screen is all white and you cannot see anything. I thought it was the colour, i changed it to black or blue but still nothing.Could you help me? thank you!
Thank you for the tutorial. I would like to end the game and display the score if lives == 0. How do I go about this. Thanks.
I’ve noticed that if you are clicked inside the window the ball/bat moves slower than when you are clicked inside of it. Why is that?
Also great tutorial learning alot!!