Skip to content

Transitions

Modar Nasser edited this page Feb 4, 2023 · 4 revisions

When changing game screens or levels, you will probably need a way to create a Transition.

Thankfully, the ns::App class provides a very simple way of starting transitions, simply by calling the template method

ns::App::startTransition<TransitionType>(args...);

where TransitionType is a class derived from ns::Transition.

Two custom transitions are provided out of the box (CircleOpen and Circleclose), but you can easily create your own transitions by inheriting the ns::Transition class.

Let's look at an example using Circle transitions :

#include <NasNas/NasNas>
Game::Game() {
    // setting Window clear color to white so we can actually see the transition
    this->getWindow().setClearColor(sf::Color::White);
}

Game::onEvent(const sf::Event& event) {
    if (event.type == sf::Event::Closed) 
        this->getWindow().close();

    if (event.type == sf::Event::KeyPressed) {
        if (event.key.code == sf::Keyboard::T)
            this->startTransition<ns::transition::CircleClose>();

        if (event.key.code == sf::Keyboard::Y)
            this->startTransition<ns::transition::CircleOpen>();
    }
}

Game::update() {}

Pressing T or Y keys will start a CircleClose or CircleOpen transition, it is that simple !

Let's say we want to switch game screen when the CircleClose transition ends, and then directly play a CircleOpen transition; we can do this by using the onEnd method that takes a lambda function as argument:

Game::Game() {
    this->getWindow().setClearColor(sf::Color::White);
}

Game::onEvent(const sf::Event& event) {
    if (event.type == sf::Event::Closed) 
        this->getWindow().close();
    
    if (event.type == sf::Event::KeyPressed) {
        if (event.key.code == sf::Keyboard::T) {
            this->startTransition<ns::transition::CircleClose>().onEnd([&]() {
                // load next level, change game screen ...etc  here
                this->getWindow().setClearColor(sf::Color::Green);
                this->startTransition<ns::transition::CircleOpen>();
            });
        }
    }
}

Game::update() {}

Creating a custom Transition

To create your own transition, you need to inherit from ns::Transition and implement the onUpdate virtual method. In this method, when your transition should end, just call the end method.

The example below implements very basic FadeIn and FadeOut transitions :

class FadeOut : public ns::Transition {
    sf::RectangleShape bg;
public:
    FadeOut() {
        // creating the transition background
        this->bg.setSize(app->getWindow().getAppView().getSize());
        this->bg.setFillColor(sf::Color::Transparent);
        this->addShape(this->bg);
    }
    void onUpdate() override {
        // updating background opacity
        this->bg.setFillColor(this->bg.getFillColor()+sf::Color(0, 0, 0, 5));
        // when the background is opaque, end the transition
        if (this->bg.getFillColor().a >= 255)
            end();
    }
};

class FadeIn : public ns::Transition {
    sf::RectangleShape bg;
public:
    FadeIn() {
        // creating the transition background
        this->bg.setSize(app->getWindow().getAppView().getSize());
        this->bg.setFillColor(sf::Color::Black);
        this->addShape(this->bg);
    }
    void onUpdate() override {
        // updating background opacity
        this->bg.setFillColor(this->bg.getFillColor()-sf::Color(0, 0, 0, 5));
        // when the background is transparent, end the transition
        if (this->bg.getFillColor().a <= 0)
            end();
    }
};

Note : ns::Transition inherits from ns::AppComponent, which means it can access the main App methods by using the app() property (e.g. app().getCamera("main")).

Transitions offer a lot of flexibility and are a powerful tool to create easily customized transitions for your game.