0
\$\begingroup\$

I have the following class that animates a 'fade to black' effect:

#pragma once
#include <SDL.h>

class Renderer {
public:
    explicit Renderer(SDL_Renderer *renderer) : renderer(renderer) {}

    void Update(double deltaTime) {
        this->dt = deltaTime;
    };

    void Render() {
        if (fadeout) {
            fadeValue += secondeSteps*dt;

            if (fadeValue > 255) {
                fadeValue = 255;
                fadeout = false;
                //callback?
            }
            SDL_SetRenderDrawColor(renderer, 0,0,0, (int)fadeValue);
            SDL_RenderFillRect(renderer, &screen);
        }
    };

    void FadeOut(SDL_Rect rect, int duration = 1500) {
        fadeout = true;
        secondeSteps = (255.0f/duration)*1000; // opacity change per seconde
        screen = rect;
    }

private:
    float fadeValue {};
    float secondeSteps{};
    bool fadeout = false;
    SDL_Rect screen;
    double dt; 
    SDL_Renderer *renderer;
};

It is run every frame until a desired value is reached, and then a flag is set to indicate we are done (fadeout = false;).

But what I would like is to pass a callback, so that after the effect is done, something like a GameState is changed to a new value, like this:

gameRenderer->FadeOut(SDL_Rect{0,0,windowWidth,windowHeight}, GameState::STATE_LOAD);

Right now, the Renderer class is a unique_ptr inside my Game class, but has no knowledge of the Game object itself.

I've seen many suggestions about using Lambdas or passing function pointers, but I'm not sure what to pick, and what is the most modern solution for,say, c++ compiler 20. There's also async (https://en.cppreference.com/w/cpp/thread/async) functions, could that be useful in this scenario here as well?

Or maybe it's just as easy as passing the current instance of my Game to the Renderer class? That seems kind of messy.

Would gladly hear some suggestions about how to approach this.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

I found a solution that works, using Lambda functions..if anybody can add some additional background as to what is happening, or has a better solution, I'll pick that as the answer.

Adding argument to the FadeOut:

bool FadeOut(SDL_Rect rect, const std::function<void()> &f, int duration = 1500) {

Calling the FadeOut with a Lambda:

gameRenderer->FadeOut
    (SDL_Rect{0,0,windowWidth,windowHeight},
    // less_than
     [&]() {
         ChangeState(GameState::STATE_LOAD);
     }
);
\$\endgroup\$
2
  • \$\begingroup\$ How it is like you wrote, the renderer decides when the state changes. Shouldn't it be other way round? the Game should decide when to fade out but also when it is done. When the game controls for example "The current screen brightness", the renderer can just query the brightness and display accordingly. \$\endgroup\$
    – Raildex
    Aug 11, 2022 at 13:11
  • \$\begingroup\$ Well the structure of the game and rendering is something I'm still thinking about, could be a question here in itself..What if the renderer can do all kinds of effects? That would mean the Game should know about a lot of stuff that seems purely the renderer's domain. I just want to know when the effect is done, not if some pixel is black or white.. \$\endgroup\$
    – Oli
    Aug 11, 2022 at 13:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .