Skip to content
Flecs v4.1
game_mechanics/scene_management

  • C++

    View on GitHub

    1#include <scene_management.h>
    2#include <iostream>
    3#include <string>
    4
    5// This example shows one possible way to implement scene management
    6// using pipelines.
    7
    8// Scene relationships/tags
    9struct ActiveScene { }; // Represents the current scene
    10struct SceneRoot { }; // Parent for all entities unique to the scene
    11
    12// Scenes
    13using Pipeline = flecs::entity;
    14struct MenuScene { Pipeline pip; };
    15struct GameScene { Pipeline pip; };
    16
    17// Components for Example
    18struct Position { float x, y; };
    19struct Button { std::string text; };
    20struct Character { bool alive; };
    21struct Health { int amount; };
    22
    23// Removes all entities who are children of
    24// the current scene root.
    25void reset_scene(flecs::world& ecs) {
    26 ecs.delete_with(flecs::ChildOf, ecs.entity<SceneRoot>());
    27}
    28
    29void menu_scene(flecs::iter& it, size_t, ActiveScene) {
    30 std::cout << "\n>> ActiveScene has changed to `MenuScene`\n\n";
    31
    32 flecs::world ecs = it.stage();
    33 flecs::entity scene = ecs.component<SceneRoot>();
    34
    35 reset_scene(ecs);
    36
    37 // Creates a start menu button
    38 // when we enter the menu scene.
    39 ecs.entity("Start Button")
    40 .set(Button{ "Play the Game!" })
    41 .set(Position{ 50, 50 })
    42 .child_of(scene);
    43
    44 ecs.set_pipeline(ecs.get<MenuScene>().pip);
    45}
    46
    47void game_scene(flecs::iter& it, size_t, ActiveScene) {
    48 std::cout << "\n>> ActiveScene has changed to `GameScene`\n\n";
    49
    50 flecs::world ecs = it.stage();
    51 flecs::entity scene = ecs.component<SceneRoot>();
    52
    53 reset_scene(ecs);
    54
    55 // Creates a player character
    56 // when we enter the game scene.
    57 ecs.entity("Player")
    58 .set(Character{ })
    59 .set(Health{ 2 })
    60 .set(Position{ 0, 0 })
    61 .child_of(scene);
    62
    63 ecs.set_pipeline(ecs.get<GameScene>().pip);
    64}
    65
    66void init_scenes(flecs::world& ecs) {
    67 // Can only have one active scene
    68 // in a game at a time.
    69 ecs.component<ActiveScene>()
    70 .add(flecs::Exclusive);
    71
    72 // Each scene gets a pipeline that
    73 // runs the associated systems plus
    74 // all other scene-agnostic systems.
    75 flecs::entity menu = ecs.pipeline()
    76 .with(flecs::System)
    77 .without<GameScene>() // Use "without()" of the other scenes
    78 // so that we can run every system that
    79 // doesn't have a scene attached to it.
    80 .build();
    81
    82 flecs::entity game = ecs.pipeline()
    83 .with(flecs::System)
    84 .without<MenuScene>()
    85 .build();
    86
    87 // Set pipeline entities on the scenes
    88 // to easily find them later with get().
    89 ecs.set<MenuScene>({ menu });
    90 ecs.set<GameScene>({ game });
    91
    92 // Observer to call scene change logic for
    93 // MenuScene when added to the ActiveScene.
    94 ecs.observer<ActiveScene>("Scene Change to Menu")
    95 .event(flecs::OnAdd)
    96 .second<MenuScene>()
    97 .each(menu_scene);
    98
    99 // Observer to call scene change logic for
    100 // GameScene when added to the ActiveScene.
    101 ecs.observer<ActiveScene>("Scene Change to Game")
    102 .event(flecs::OnAdd)
    103 .second<GameScene>()
    104 .each(game_scene);
    105}
    106
    107void init_systems(flecs::world& ecs) {
    108 // Will run every time regardless of the
    109 // current scene we're in.
    110 ecs.system<const Position>("Print Position")
    111 .each([](flecs::entity e, const Position& p) {
    112 // Prints out the position of the
    113 // entity.
    114 std::cout << e.name() << ": {" << p.x << ", " << p.y << "}\n";
    115 });
    116
    117 // Will only run when the game scene is
    118 // currently active.
    119 ecs.system<Health>("Characters Lose Health")
    120 .kind<GameScene>()
    121 .each([](Health& h) {
    122 // Prints out the character's health
    123 // and then decrements it by one.
    124 std::cout << h.amount << " health remaining\n";
    125 h.amount--;
    126 });
    127
    128 // Will only run when the menu scene is
    129 // currently active.
    130 ecs.system<const Button>("Print Menu Button Text")
    131 .kind<MenuScene>()
    132 .each([](const Button& b) {
    133 // Prints out the text of the menu
    134 // button.
    135 std::cout << "Button says \"" << b.text << "\"\n";
    136 });
    137}
    138
    139int main(int, char *[]) {
    140 flecs::world ecs;
    141
    142 init_scenes(ecs);
    143 init_systems(ecs);
    144
    145 ecs.add<ActiveScene, MenuScene>();
    146 ecs.progress();
    147
    148 ecs.add<ActiveScene, GameScene>();
    149 ecs.progress();
    150 ecs.progress();
    151 ecs.progress();
    152
    153 ecs.add<ActiveScene, MenuScene>();
    154 ecs.progress();
    155
    156 ecs.add<ActiveScene, GameScene>();
    157 ecs.progress();
    158 ecs.progress();
    159 ecs.progress();
    160
    161 // Output
    162 // >> ActiveScene has changed to `MenuScene`
    163
    164 // Start Button: {50, 50}
    165 // Button says "Play the Game!"
    166
    167 // >> ActiveScene has changed to `GameScene`
    168
    169 // Player: {0, 0}
    170 // 2 health remaining
    171 // Player: {0, 0}
    172 // 1 health remaining
    173 // Player: {0, 0}
    174 // 0 health remaining
    175
    176 // >> ActiveScene has changed to `MenuScene`
    177
    178 // Start Button: {50, 50}
    179 // Button says "Play the Game!"
    180
    181 // >> ActiveScene has changed to `GameScene`
    182
    183 // Player: {0, 0}
    184 // 2 health remaining
    185 // Player: {0, 0}
    186 // 1 health remaining
    187 // Player: {0, 0}
    188 // 0 health remaining
    189}
    flecs::system system(flecs::entity e) const
    Upcast an entity to a system.
    Definition impl.hpp:181
    flecs::component< T > component(Args &&... args) const
    Find or register a component.
    Definition impl.hpp:11
    flecs::entity entity(Args &&... args) const
    Create an entity.
    Definition impl.hpp:195
    flecs::observer observer(flecs::entity e) const
    Observer world mixin.
    Definition impl.hpp:85
    flecs::pipeline_builder pipeline(const char *name=nullptr) const
    Create a new pipeline.
    Definition impl.hpp:25
    bool progress(ecs_ftime_t delta_time=0.0) const
    Progress the world one tick.
    Definition impl.hpp:47
    void set_pipeline(const flecs::entity pip) const
    Set the pipeline.
    Definition impl.hpp:34
    flecs::string_view name() const
    Return the entity name.
    Entity.
    Definition entity.hpp:30
    Class for iterating over query results.
    Definition iter.hpp:68
    system & each(Func &&func)
    Replace the system's each callback.
    Definition impl.hpp:119
    The world.
    Definition world.hpp:129
    void each(Func &&func) const
    Iterate over all entities with components in the argument list of the function.
    void get(const Func &func) const
    Get a singleton component using a callback.
    Definition world.hpp:155
    flecs::event_builder event(flecs::entity_t evt) const
    Create a new event.