Skip to content
CXO2 edited this page Jul 16, 2026 · 8 revisions

Overview

The task classes represent the implementation of running logic that can be completed within a certain period of time or when certain conditions are met. The tasks can also be interrupted, reset, or made as if completed at any point in time.

Gx::Task has 4 states that represent the status of the task object:

  • Initial: The task is in the initial state, indicating the instance has been created, or the task has been reset.
  • Running: The task is currently running.
  • Stopped: The task is interrupted and no longer running; All internal states of the task are left as-is.
  • Completed: The task is completed; All internal states of the task are at the expected terminal values.

Starting a task

Like Gx::Animation, you must call Update() with the delta frame time in your game loop to start and run the task after creating the task instance. You don't have to check the task state before calling the Update() function because it will determine its state and only perform the logic when the task is in the appropriate state.

Stopping a task

Call Stop() to stop a task. This will leave all internal states as-is. For example, if you have a task that is designed to fade the color opacity of a Gx::Colorable entity, stopping this task will let the opacity of the entity remain at the last value.

// Create a fade tween that modifies "someEntity" opacity from its current opacity to 255 opacity within 5 seconds
Gx::Fade fade(someEntity, 255, sf::seconds(5.f));

// Update the tween every frame
fade.Update(delta);

// ... Stop the fade after running for some time. "someEntity" opacity will remain as it is
fade.Stop(); // opacity could be between 0 and 255 depending on when you stop the tween

Resetting a task

Call Reset() to reset the task state to Initial, which effectively replays the task. After calling reset, all internal states of the task should be reset to the initial value.

// Create a fade tween that modifies "someEntity" opacity from its current opacity to 255 opacity within 5 seconds
Gx::Fade fade(someEntity, 255, sf::seconds(5.f));

// Update the tween every frame
fade.Update(delta);

// ... Reset the fade after it is stopped or completed; you can also reset it when it is running. 
// "someEntity" opacity will be set to the value when the initial `Update()` is called
fade.Reset();

Important

The resetting of "internal states" will depend on the implementation details of Gx::Task. In other words, it will be your responsibility to define the initial state of the task and override the Reset() to reset the states according to your definition.

For example, the tween classes in Genode will only capture the initial states of the target entity at the first Update() call and not in the constructor. This means if someEntity 's opacity is changed between the fade constructor and the initial fade update call, the "initial value" of the opacity will be the value when the initial update is called and not when the fade is constructed.

Refer to the Tween section for further details.

Completing a task

The tasks can be completed when the task conditions are met. However, you can force a task to mark itself as Completed by calling Complete() function. This will set the task's internal states into the expected terminal state.

// Create a fade tween that modifies "someEntity" opacity from its current opacity to 255 opacity within 5 seconds
Gx::Fade fade(someEntity, 255, sf::seconds(5.f));

// Update the tween every frame
fade.Update(delta);

// ... Complete the fade manually. 
// "someEntity" opacity will be set to 255
fade.Complete();

Important

Similar to Reset(), you will have to define the terminal state on your own and set all states into the terminal state by overriding the Complete() function.

Built-in tasks

Genode provides built-in implementation tasks that you can use out of the box. These small tasks can be chained as building blocks to implement complex logic in your game.

Action

Gx::Action is a task class that invokes the specified std::function upon activation. Once the task is started, it will invoke the function and mark itself as completed. This task is only useful when combined with other tasks.

// Create an action that prints "hello world"
Gx::Action action([] ()
{
    std::cout << "hello world";
});

// Start and update the action every frame, the function will be invoked immediately on the first update call
action.Update(delta);

Delay

Gx::Delay is a task that will do nothing for the specified time before marking itself as completed. This task is only useful when combined with other tasks.

// Create a 5 seconds delay
Gx::Delay delay(sf::seconds(5.f));

// Start and update the delay every frame
delay.Update(delta);

Scheduler

Gx::Scheduler is a task that will run for a specified amount of time and has a callback that will be called in between every certain interval that can be specified.

// Create a scheduler object
Gx::Scheduler scheduler
(
    sf::seconds(60),                                      // Scheduler will run for 60 seconds
    sf::seconds(10),                                      // Scheduler update callback will be called every 10 seconds for 60 seconds
    [] (const Gx::Scheduler& it, const sf::Time& delta) // The scheduler update callback, the delta time is the time elapsed between this callback and the previous callback call, expressed in sf::Time
    {
        // Note that it is NOT guaranteed it will only be called 6 times (e.g. the callback is called when the task is marked as completed)
        std::cout << "hello from scheduler"; 
    }
);

// Alternatively, you can schedule a scheduler once, which give you something equivalent to combining Gx::Delay and Gx::Action
Gx::Scheduler scheduler = Gx::Scheduler::Once(sf::seconds(5.f), [] (const Gx::Scheduler& it, const sf::Time& delta)
{
    std::cout << "this callback will be called at least once after 5 seconds";
});

// Start and update the scheduler every frame
scheduler.Update(delta);

Sequence

Gx::Sequence represents a collection of tasks that will be executed sequentially. This class can be used as a building block to chain multiple tasks and build complex logic.

// Create the sequence
Gx::Sequence sequence = Gx::Sequence([] ()
    {
        // Callback when all tasks in the sequence has been completed
        std::cout << "completed all tasks!";
    },
    Gx::Delay(sf::seconds(5.f)),
    Gx::Action([]() { std::cout << "hello world"; })
);

// Start and update the sequence every frame
// This will print "hello world" and "completed all tasks!" after 5 seconds delay
sequence.Update(delta);

Tween

The tween classes implement Gx::Task abstract class and interact with the Gx::Colorable and the Gx::Transformable as the target entity.

All of these tween share the same constructor conventions which accepts 3 parameters:

  • target: The entity that the tween will target. For example, Gx::Fade accept the Gx::Colorable entity.
  • destination: Represents the final value set to the target entity once the tween is completely finished. For example, Gx::Fade accepts the final opacity value.
  • duration: The tween duration expressed in sf::Time.

It is important to note that this tween will calculate the difference values between the target initial and destination values during the first call of Update, particularly when the task is transitioned from Initial to Running. This means the initial value is not captured/computed when the target is passed to the tween constructor.

The following code illustrates the above behavior.

// Retrieve a colorable object
Gx::Colorable& entity = //.. get the colorable from somewhere

// Set the opacity to 100
entity.SetColor(sf::Color(255, 255, 255, 100));

// Create fade tween that turn opacity into 255 in 5 seconds
auto fader = Gx::Fade(colorable, 255, sf::seconds(5.f));

// At this point, if you `Update()` the `fader`, the tween will compute the delta alpha with the initial value of 100
// And any subsequent `Reset()` call in `fader` object will set the `colorable` alpha to 100

// ... However, if you change the alpha before the initial `fader.Update()` call like so:
entity.SetColor(sf::Color(255, 255, 255, 0)); // set opacity to 0

// The initial opacity would be 0 instead. To finalize the initial value, `Update()` the tween
fader.Update(delta); // assuming the fader is in `Initial` state, the initial alpha value will be captured as 0

This design allows you to write dynamic tween that take the last state of your target entity. A task like Gx::Sequence can take advantage of this design allowing you to chain multiple tweens without explicitly specifying the initial values:

Gx::Colorable& colorable = // ...
entity.SetColor(sf::Color(255, 255, 255, 0)); // set opacity to 0

auto sequence = Gx::Sequence(
    Gx::Fade(colorable, 255, sf::seconds(1.f)), // Fade in the colorable opacity from 0 to 255 within 1 second
    Gx::Fade(colorable, 000, sf::seconds(1.f))  // Fade out the colorable opacity from the last value (that would be 255) to 0 within 1 second 
);

Buit-in tweens

Genode provides 4 built-in tween classes as follows:

  • Gx::Fade: perform opacity fading of a Gx::Colorable entity between initial and specified opacity.
  • Gx::Move: perform transform translation (move) of a Gx::Transformable between the initial and specified positions.
  • Gx::Rotate: perform transform rotation of a Gx::Transformable between the initial and specified angles.
  • Gx::Move: perform transform scaling of a Gx::Transformable between the initial and specified scales.

Clone this wiki locally