C++ SFML Game Dev Cheat Sheet
A one-page printable reference for SFML window setup, drawing, input, math, animation, collision, audio and common C++ game patterns. Pin it next to your monitor!
A one-page printable reference for SFML window setup, drawing, input, math, animation, collision, audio and common C++ game patterns. Pin it next to your monitor!
#include <SFML/Graphics.hpp> #include <optional> sf::RenderWindow window( sf::VideoMode({800, 600}), "My Game"); window.setFramerateLimit(60); sf::Clock clock; while (window.isOpen()) { while (const std::optional event = window.pollEvent()) { if (event->is<sf::Event::Closed>()) window.close(); } sf::Time dt = clock.restart(); // update & draw window.display(); }
# rectangle sf::RectangleShape rect( sf::Vector2f({100.f, 50.f})); rect.setPosition({200.f, 150.f}); rect.setFillColor(sf::Color::Blue); window.draw(rect); # circle sf::CircleShape circle(40.f); circle.setPosition({300.f, 200.f}); window.draw(circle); # sprite (SFML 3 loads in the constructor) const sf::Texture tex("player.png"); sf::Sprite sprite(tex); window.draw(sprite); # text (the font is the first argument) const sf::Font font("arial.ttf"); sf::Text text(font, "Hello", 24); window.draw(text);
| sf::Keyboard::isKeyPressed() | Poll any key state |
| sf::Keyboard::Key::W | W key constant (enum class) |
| sf::Keyboard::Key::Space | Space key constant |
| sf::Keyboard::Key::Escape | Escape key constant |
| sf::Mouse::getPosition() | Global mouse position |
| sf::Mouse::getPosition(win) | Mouse relative to window |
| event->getIf<sf::Event::KeyPressed>()->code | Key that triggered event |
| event->getIf<sf::Event::MouseButtonPressed>() | Mouse button info |
if (sf::Keyboard::isKeyPressed( sf::Keyboard::Key::W)) player.y -= speed; if (sf::Keyboard::isKeyPressed( sf::Keyboard::Key::Left)) player.x -= speed;
# sf::Vector2f is the core type sf::Vector2f pos(100.f, 200.f); sf::Vector2f vel(0.f, 0.f); # arithmetic pos = pos + vel; pos.x += vel.x * dt.asSeconds(); # transformable sprite.setPosition(pos); sprite.setRotation(45.f); sprite.setScale(2.f, 2.f); # common math float len = std::sqrt(x*x + y*y); float ang = std::atan2(dy, dx);
const sf::Texture sheet("spritesheet.png"); int frameW = 32, frameH = 32; int currentFrame = 0; int totalFrames = 4; float animSpeed = 0.15f; sf::IntRect uvRect(0, 0, frameW, frameH); # update each frame timer += animSpeed; if (timer >= 1.f) { timer = 0.f; currentFrame++; if (currentFrame >= totalFrames) currentFrame = 0; } # set the current frame region uvRect.left = currentFrame * frameW; sprite.setTextureRect(uvRect); window.draw(sprite);
# get bounding boxes sf::FloatRect bounds1 = sprite1.getGlobalBounds(); sf::FloatRect bounds2 = sprite2.getGlobalBounds(); # AABB intersection if (bounds1.intersects(bounds2)) { # collision! } # point inside rect if (bounds1.contains( {mousePos.x, mousePos.y})) { # hover / click } # AABB parameters bounds.left; bounds.top; bounds.width; bounds.height;
# short sound effects sf::SoundBuffer buf; buf.loadFromFile("jump.wav"); sf::Sound sfx(buf); sfx.play(); # background music (streamed) sf::Music music; music.openFromFile("bgm.ogg"); music.setLoop(true); music.setVolume(50.f); music.play(); # control music.pause(); music.stop();
sf::Clock clock; # delta time sf::Time dt = clock.restart(); float sec = dt.asSeconds(); int ms = dt.asMilliseconds(); # elapsed since last restart sf::Time elapsed = clock.getElapsedTime(); # frame-rate independent movement player.x += speed * dt.asSeconds(); # timer pattern float cooldown = 0.f; cooldown -= dt.asSeconds(); if (cooldown <= 0.f) { # fire, then reset cooldown = 1.f; }
โโ FULL GAME LOOP โโ sf::RenderWindow window(sf::VideoMode({800,600}), "Game"); window.setFramerateLimit(60); sf::Clock clock; while (window.isOpen()) { while (const std::optional e = window.pollEvent()) { if (e->is<sf::Event::Closed>()) window.close(); if (const auto* key = e->getIf<sf::Event::KeyPressed>()) if (key->code == sf::Keyboard::Key::Escape) window.close(); } sf::Time dt = clock.restart(); update(dt); window.clear(sf::Color::Black); draw(window); window.display(); } โโ SPRITE ANIMATION โโ int frame = 0; float timer = 0.f; int frameW = tex.getSize().x / cols; int frameH = tex.getSize().y / rows; timer += dt.asSeconds(); if (timer >= animSpeed) { timer = 0.f; frame = (frame + 1) % totalFrames; } sf::IntRect uv((frame % cols) * frameW, (frame / cols) * frameH, frameW, frameH); sprite.setTextureRect(uv); โโ COLLISION WITH RESOLUTION โโ sf::FloatRect a = player.getGlobalBounds(); sf::FloatRect b = wall.getGlobalBounds(); sf::FloatRect overlap; if (a.intersects(b, overlap)) { # push out on smallest axis if (overlap.width < overlap.height) { # horizontal push player.x += (a.left < b.left) ? -overlap.width : overlap.width; } else { player.y += (a.top < b.top) ? -overlap.height : overlap.height; } } โโ SCROLLING BACKGROUND โโ float bgX = 0.f; bgX -= speed * dt.asSeconds(); if (bgX <= -bgTex.getSize().x) bgX += bgTex.getSize().x; bgSprite.setPosition({bgX, 0.f}); bgSprite2.setPosition( {bgX + bgTex.getSize().x, 0.f}); โโ PARTICLE SYSTEM โโ struct Particle { sf::Vector2f pos, vel; float life; }; std::vector<Particle> particles; # spawn particles.push_back({ {x, y}, {rand()%6-3, rand()%4-4}, 1.0f }); # update for (auto& p : particles) { p.pos += p.vel * dt.asSeconds(); p.life -= dt.asSeconds(); } particles.erase( std::remove_if(particles.begin(), particles.end(), [](auto& p){return p.life <= 0.f;}), particles.end());
Follow one of our free step-by-step workshops in the Workshop hub.
๐ง Browse Workshops โ