A complete C++ game from scratch using SFML

Started by
53 comments, last by Serapth 11 years, 7 months ago
It seems like no matter how much you tell people to not start using C++, many do anyways. That said, I have noticed one thing, many if not most of the tutorials the people are going to start with are complete crap. The vast majority are written as if it was still 1983 and when you see some of the code people post in these forums, you can tell these tutorials are having a negative effect. Now, a simple tutorial cannot be a replacement for a solid study or even a short book. What it can do though, is be a hell of a supplement.

So, I have put together Game From Scratch -- C++ Edition which documents the development of a simple game from the very beginning till the end (using SFML). Instead of being constrained to the small spaces allocated to a book or site sample, I can go on and on and on, and at times, I do! :D Consider it part example game, part programming primer and part soapbox. I am not going to teach you to program, you will need a understanding of the very basics at least, but hopefully I will teach you how to program a little bit better.

It's fairly early on, only five "chapters" thus far, but I think you will find even what is there useful if you are just starting out. Of course, I will be updating and adding content on a nearly daily basis. Although the game is simple, I am coding it in such a way that the practices should be transferable to a project of just about any size.

To the more veteran minded among us, if you see and glaring errors or mistakes, please point them out to me and I will address them... a tutorial isn't much good if its teaching incorrect material! On occasion I do things "badly" to introduce a concept later, but I generally will acknowledge when I do so. On occasion too, I choose clarity over functionality, at least clarity in my opinion.

So if you are just starting out programming, check it out. If you are a wizened master and see a mistake, let me know. I also take reasonable pride in my ability to communicate in English, so if you see glaringly awful abuses of the English language, please let me know!

Cheers and hopefully it's helpful.
Advertisement
Oh, and there are a ton of links(mostly for individual source downloads) and hopefully none of them are broken, if you encounter a broken link, please let me know.

Also, you may notice a bit of a bug, in that the splashscreen and mainmenu don't handle window close events. This is actually intentional at this point.
Nice looking tutorial.
I took a quick look at chapter 4 and one thing that struck me was that each Visual object contains a sf::Image rather than a pointer/reference to a sf::Image.
Wouldn't it be a good idea to separate the images from that class, making it a "global" resource instead? Or at least explain for the reader that storing the image data in each visual object could become a waste of resources in the long run?

Nice looking tutorial.
I took a quick look at chapter 4 and one thing that struck me was that each Visual object contains a sf::Image rather than a pointer/reference to a sf::Image.
Wouldn't it be a good idea to separate the images from that class, making it a "global" resource instead? Or at least explain for the reader that storing the image data in each visual object could become a waste of resources in the long run?



Warning, spoilers... :)

When I introduce the second paddle, which uses the same Image, the behaviour of this code is going to be changed. This is an example of code that's going to change to illustrate a concept, something ill do quite often.


That said, yes, it's is wasteful as soon as the relationship between sprites and images isn't one to one. At this point though, it's not wasteful.
I don't quite like your first introduction to classes. Also, I don't agree with your reasons to do so. Free functions are part of the a class's public interface in C++. If you don't need real class, then why not just use free functions. Free functions would be much softer landing for beginners.

You don't need to expose a singleton in header, nor global objects. If you need global access, just use free function which is global accessor.

Something like:

// Game.h
#pragma once

void StartGame();


// Game.cpp
#include "stdafx.h"
#include "Game.h"

enum GameState { Uninitialized, ShowingSplash, Paused,
ShowingMenu, Playing, Exiting };

GameState _gameState = Uninitialized;
sf::RenderWindow _mainWindow;

bool IsExiting()
{
if(_gameState == Exiting)
return true;
else
return false;
}

void GameLoop()
{
sf::Event currentEvent;
while(_mainWindow.GetEvent(currentEvent))
{

switch(_gameState)
{
case Playing:
{
_mainWindow.Clear(sf::Color(sf::Color(255, 0, 0)));
_mainWindow.Display();

if(currentEvent.Type == sf::Event::Closed)
{
_gameState = Exiting;
}
break;
}
}
}
}

void StartGame()
{
if(_gameState != Uninitialized)
return;

_mainWindow.Create(sf::VideoMode(1024, 768, 32),"Pang!");
_gameState = Playing;

while(!IsExiting())
{
GameLoop();
}

_mainWindow.Close();
}


I mean maybe it's not good to first teach everyone to use statics (or globals), then tell them to unlearn it when projects grow bigger and they run into problems. IMO all static and global instances belong into cpp file in C++, it's easier to get rid of them later.

Also I'm somewhat against private member functions. I'd rather like to see them as free functions (in anonymous namespace) inside the cpp file, or even extracted to implementation detail class.

[quote name='pulpfist' timestamp='1315502665' post='4859122']
Nice looking tutorial.
I took a quick look at chapter 4 and one thing that struck me was that each Visual object contains a sf::Image rather than a pointer/reference to a sf::Image.
Wouldn't it be a good idea to separate the images from that class, making it a "global" resource instead? Or at least explain for the reader that storing the image data in each visual object could become a waste of resources in the long run?



Warning, spoilers... :)

When I introduce the second paddle, which uses the same Image, the behaviour of this code is going to be changed. This is an example of code that's going to change to illustrate a concept, something ill do quite often.


That said, yes, it's is wasteful as soon as the relationship between sprites and images isn't one to one. At this point though, it's not wasteful.
[/quote]


Fair enough, but I would still mention it early.


I don't quite like your first introduction to classes. Also, I don't agree with your reasons to do so. Free functions are part of the a class's public interface in C++. If you don't need real class, then why not just use free functions. Free functions would be much softer landing for beginners.

You don't need to expose a singleton in header, nor global objects. If you need global access, just use free function which is global accessor.

Something like:

// Game.h
#pragma once

void StartGame();


// Game.cpp
#include "stdafx.h"
#include "Game.h"

enum GameState { Uninitialized, ShowingSplash, Paused,
ShowingMenu, Playing, Exiting };

GameState _gameState = Uninitialized;
sf::RenderWindow _mainWindow;

bool IsExiting()
{
if(_gameState == Exiting)
return true;
else
return false;
}

void GameLoop()
{
sf::Event currentEvent;
while(_mainWindow.GetEvent(currentEvent))
{

switch(_gameState)
{
case Playing:
{
_mainWindow.Clear(sf::Color(sf::Color(255, 0, 0)));
_mainWindow.Display();

if(currentEvent.Type == sf::Event::Closed)
{
_gameState = Exiting;
}
break;
}
}
}
}

void StartGame()
{
if(_gameState != Uninitialized)
return;

_mainWindow.Create(sf::VideoMode(1024, 768, 32),"Pang!");
_gameState = Playing;

while(!IsExiting())
{
GameLoop();
}

_mainWindow.Close();
}


I mean maybe it's not good to first teach everyone to use statics (or globals), then tell them to unlearn it when projects grow bigger and they run into problems. IMO all static and global instances belong into cpp file in C++, it's easier to get rid of them later.

Also I'm somewhat against private member functions. I'd rather like to see them as free functions (in anonymous namespace) inside the cpp file, or even extracted to implementation detail class.


This is actually one of those area's ( actually the area ) I most hummed and hawed about if I was introducing needless complexity or not. However, as time goes on, there actually will be some (justified) global instances with Game:: being the sole point of contact. I don't actually swear users off them, as frankly in a few cases, they make sense. ( I have also grown to dislike how I named Gameloop )


I am curious though why you are anti private member functions?

[quote name='Serapth' timestamp='1315503212' post='4859124']
[quote name='pulpfist' timestamp='1315502665' post='4859122']
Nice looking tutorial.
I took a quick look at chapter 4 and one thing that struck me was that each Visual object contains a sf::Image rather than a pointer/reference to a sf::Image.
Wouldn't it be a good idea to separate the images from that class, making it a "global" resource instead? Or at least explain for the reader that storing the image data in each visual object could become a waste of resources in the long run?



Warning, spoilers... :)

When I introduce the second paddle, which uses the same Image, the behaviour of this code is going to be changed. This is an example of code that's going to change to illustrate a concept, something ill do quite often.


That said, yes, it's is wasteful as soon as the relationship between sprites and images isn't one to one. At this point though, it's not wasteful.
[/quote]


Fair enough, but I would still mention it early.


[/quote]


I wonder if I can come up with a clean solution to mark code as "going to be improved later".


This is actually one of those area's ( actually the area ) I most hummed and hawed about if I was introducing needless complexity or not. However, as time goes on, there actually will be some (justified) global instances with Game:: being the sole point of contact. I don't actually swear users off them, as frankly in a few cases, they make sense. ( I have also grown to dislike how I named Gameloop )


I am curious though why you are anti private member functions?

Well, they clutter the public interface. Private member functions are implementation detail of the class, not related to the public interface. Sometimes they introduce new types to the header, so you have to either predeclare or include them. Causes recompilations when the implementation changes.

So basically the encapsulation is better without private member functions.

This is pretty recent realization for me, but I'm constantly more convinced about it. It's a fun experiment to take some random class with a lot of private functions, and then extract them to a new class as public functions. This new class can be visible only to the one class they're from, but this does clear up things. Also if you want to re-use the private functions in another class, no inheritance is required.

[quote name='pulpfist' timestamp='1315512274' post='4859195']
[quote name='Serapth' timestamp='1315503212' post='4859124']
[quote name='pulpfist' timestamp='1315502665' post='4859122']
Nice looking tutorial.
I took a quick look at chapter 4 and one thing that struck me was that each Visual object contains a sf::Image rather than a pointer/reference to a sf::Image.
Wouldn't it be a good idea to separate the images from that class, making it a "global" resource instead? Or at least explain for the reader that storing the image data in each visual object could become a waste of resources in the long run?



Warning, spoilers... :)

When I introduce the second paddle, which uses the same Image, the behaviour of this code is going to be changed. This is an example of code that's going to change to illustrate a concept, something ill do quite often.


That said, yes, it's is wasteful as soon as the relationship between sprites and images isn't one to one. At this point though, it's not wasteful.
[/quote]


Fair enough, but I would still mention it early.


[/quote]


I wonder if I can come up with a clean solution to mark code as "going to be improved later".


[/quote]

Yea... I though about that. It wouldn't be easy.
I was thinking about simple drawings and sketches. That way you might be able to tap into the readers subconsciousness without filling their heads with uninterpreted info too early.

This topic is closed to new replies.

Advertisement