patterncppMinor
Simon Says / Four tiles game, with C++ and SDL
Viewed 0 times
sdlwithfoursimontilesgamesaysand
Problem
My take on the Prebash Challenge, "Simon Says" game, in less than 300 lines of C++ (plus the header file), using SDL for window management and drawing.
simon_says.hpp:
simon_says.cpp:
```
#include "si
simon_says.hpp:
#ifndef CR_SIMON_SAYS_HPP
#define CR_SIMON_SAYS_HPP
#include "SDL.h"
#include
#include
// --------------------------------------------------------
// "cr" stands for Code-Review, not Coding-Rampage ;)
namespace cr
{
class SimonSaysGame
{
public:
SimonSaysGame() = default;
~SimonSaysGame();
SimonSaysGame(const SimonSaysGame &) = delete;
SimonSaysGame & operator = (const SimonSaysGame &) = delete;
bool initSDL();
void runGameLoop();
private:
// IDs of the four colored squares of "Simon Says".
enum class ColorIndex
{
Green, Red, Yellow, Blue,
// Number of enum entries / invalid dummy:
Count, Invalid = Count
};
// Internal helpers:
void checkAppEvents();
void checkFailCondition();
void renderGameBoard();
void newRandomColors();
void drawColoredSquare(ColorIndex colorIdx, bool halfTone);
// Random colors drawn for the current turn.
std::vector colorsThisTurn;
// User input this turn.
std::vector userInputColors;
ColorIndex lastUserColor = ColorIndex::Invalid;
// Number of colors the player will have to remember next time.
// Start of with an easy 2 colors.
unsigned int numColorsNextTurn = 2;
// Number of colors we still draw before ending
// the display part of the current turn.
unsigned int numColorsLeftToDisplay = 0;
// Pseudo-random engine:
std::mt19937 randGenerator{ std::random_device()() };
std::uniform_int_distribution randDist{ 0, static_cast(ColorIndex::Count) - 1 };
// Misc helper data:
SDL_Window * window = nullptr;
SDL_Renderer * renderer = nullptr;
bool lostGame = false;
bool isDone = false;
};
} // namespace cr {}
#endif // CR_SIMON_SAYS_HPPsimon_says.cpp:
```
#include "si
Solution
Since this is a small project, it doesn't matter much, but if you use SDL with modern C++, don't hesitate to create this kind of custom deleters for SDL objects to use with
Note that I am not sure whether the
Here, using function objects instead of function pointers for the custom deleter of
-
A function pointer type does not tell which function has to be used while
-
If the implementation of
To sum up: you write ten lines of code, then you get an automatic destruction of an SDL object with
std::unique_ptr:struct renderer_delete
{
void operator()(SDL_Renderer* renderer) const
{
if (renderer != nullptr)
{
SDL_DestroyRenderer(renderer);
}
}
};
using renderer_ptr = std::unique_ptr;Note that I am not sure whether the
nullptr is needed or not, I coudn't find anything about it in less than 10 minutes. You can also create an equivalent deleter/pointer pair for SDL_Window and replace the raw pointers for window and renderer in SimonSaysGame by instances of windows_ptr and renderer_ptr.Here, using function objects instead of function pointers for the custom deleter of
std::unique_ptr has two advantages (besides all the benefits of automatic destruction thanks to RAII):-
A function pointer type does not tell which function has to be used while
renderer_delete knows it has to use SDL_DestroyRenderer. With an std::unique_ptr, you would have to give SDL_DestroyRenderer at construction.-
If the implementation of
std::unique_ptr allows empty base class optimization, then using an empty function object (which can be derived from) will result in a lighter std::unique_ptr. Since function pointers cannot be derived from, the empty base class optimization does not work with them.To sum up: you write ten lines of code, then you get an automatic destruction of an SDL object with
std::unique_ptr without any overhead, be it memory or performance overhead. That's awesome.Code Snippets
struct renderer_delete
{
void operator()(SDL_Renderer* renderer) const
{
if (renderer != nullptr)
{
SDL_DestroyRenderer(renderer);
}
}
};
using renderer_ptr = std::unique_ptr<SDL_Renderer, renderer_delete>;Context
StackExchange Code Review Q#71734, answer score: 8
Revisions (0)
No revisions yet.