How to make Flappy Bird with C++
terminalroot.com
terminalroot.com
In today's world where so many tools offer web export (from libs to frameworks to engines), I can't justify learning a tool that doesn't support it.
None of that should be shared_ptr, in fact they shouldn't be pointers at all.
>auto flappy = std::make_shared<FlappyBird>(); >flappy->run();
That would work just fine as a global in main.cpp
FlappyBird flappy;
You should not pay the performance hit for features you don't need in a particular program.
In fact: It is reasonable for C++ programs to NOT use all language features.
FlappyBird().run();Code like this is effectively what you get when you have someone that doesn't know how to write C++ but writes it anyway and uses pointers everywhere because they either read that C++ is pointer heavy (it's not) or have learned C++ through some course that is actually a course on algorithms and only uses C"++" as example language and is hence at best showing shitty C with iostream and classes straight out the 1980s. Then those people find the (correct) advice of using smart pointers instead of (owning!!!) raw pointers and just put shared_ptr everywhere without thinking about if there actually is a shared ownership to be expressed and/or if the heap allocation is even needed.
Edit: A may also fulfill its obligation by transferring b to a new owner.
As for why - it's mostly around signaling intent and protecting against leaks. It's much easier to reason about ownership if you don't have to worry about some object deep inside your engine hierarchy holding a `shared_ptr` to the object that owns it. This can still happen with unique_ptr, but is much less likely.
I have been using some shared pointers in a personal project because of its ease of use but I aim to review and refactor this code to follow C++ idioms more appropriately. Thank you!
To do this safely the shared_ptr<> class maintains a reference count which is protected by a mutex. This is pretty inefficient if you never share a pointer across threads.
Better to use unique_ptr<> where the Thing that created it is also the Thing that's responsible for deleting it - after making sure that anything it's shared the pointer with is already safely destroyed (another thread, a collection or some other object).
e: nvm reading hard brain mutex too slow
Most programs don't need to use shared_ptr at all.
Side note, there is also no value in making those member functions "protected".
I have verified this by deleting "#include memory>", all uses of shared_ptr, changing all "->" to ".", and deleting all unary "*".
The window member object is initialized, then, using (drumroll...) member initializer syntax. Most uses of "{}" are better deleted.
in main.cpp
auto flappy = std::make_shared<FlappyBird>();
flappy->run();
you can do this. FlappyBird flappy;
flappy.run();
in flappy.hpp std::shared_ptr<sf::RenderWindow> window;
std::shared_ptr<sf::Sprite> background, bird, pipeBottom, pipeTop;
just do this. sf::RenderWindow window;
sf::Sprite background, bird, pipeBottom, pipeTop;
in flappy.cpp. auto e = std::make_shared<sf::Event>();
while( window->pollEvent( *e ) ){
if( e->type == sf::Event::Closed){
window->close();
}
}
just do this sf::Event event;
while (window.pollEvent(event)) {
if (e.type == sf::Event::Closed) {
window.close();
}
}
It's really that simple. for (std::size_t i {}; i < pipes.size(); ++i) {
C++ has had range based loops for years now, can use that instead here. for (auto& pipe : pipes)
I don't remember if the '&' is needed after the auto though.anyway you should just use Rust, Zig, or Go...
'&' isn't necessary to use auto but you would use it here to avoid making an unnecessary copy of the pipe.
But the code is busted anyway. After it erases the pipe (which is always at index zero) it then skips the pipe that was at index 1, if there was one.
Correct would be to do the check and erase before entering the loop. Then the range-based loop would better.
Looks better already!
There are tons of sites with all type of sprites, opengameart.org, for example.