Oxygen

We (the Flame organization) built an ECS (Entity Component System) named Oxygen.

If you want to use Oxygen specifically for Flame as a replacement for the FCS(Flame Component System) you should use our bridge library flame_oxygen and if you just want to use it in a Dart project you can use the oxygen library directly.

If you are not familiar with Oxygen yet we recommend you read up on its documentation.

To use it in your game you just need to add flame_oxygen to your pubspec.yaml, as can be seen in the Oxygen example and in the pub.dev installation instructions.

OxygenGame (Game extension)

If you are going to use Oxygen in your project it can be a good idea to use the Oxygen specific extension of the Game class.

It is called OxygenGame and it will give you full access to the Oxygen framework while also having full access to the Flame game loop.

Instead of using onLoad, as you are used to with Flame, OxygenGame comes with the init method. This method is called in the onLoad but before the world initialization, allowing you to register components and systems and do anything else that you normally would do in onLoad.

A simple OxygenGame implementation example can be seen in the example folder.

The OxygenGame also comes with it’s own createEntity method that automatically adds certain default components on the entity. This is especially helpful when you are using the BaseSystem as your base.

Systems

Systems define the logic of your game. In FCS you normally would add your logic inside a component with Oxygen we use systems for that. Oxygen itself is completely platform agnostic, meaning it has no render loop. It only knows execute, which is a method equal to the update method in Flame.

On each execute Oxygen automatically calls all the systems that were registered in order. But in Flame we can have different logic for different loops (render/update). So in flame_oxygen we introduced the RenderSystem and UpdateSystem mixin. These mixins allow you to add the render method and the update method respectively to your custom system. For more information see the RenderSystem and UpdateSystem section.

If you are coming from FCS you might expect certain default functionality that you normally got from the PositionComponent. As mentioned before components do not contain any kind of logic, but to give you the same default functionality we also created a class called BaseSystem. This system acts almost identical to the prerender logic from the PositionComponent in FCS. You only have to subclass it to your own system. For more information see the BaseSystem section.

Systems can be registered to the world using the world.registerSystem method on OxygenGame.

mixin GameRef

The GameRef mixin allows a system to become aware of the OxygenGame instance its attached to. This allows easy access to the methods on the game class.

class YourSystem extends System with GameRef<YourGame> {
  @override
  void init() {
    // Access to game using the .game property
  }

  // ...
}

mixin RenderSystem

The RenderSystem mixin allows a system to be registered for the render loop. By adding a render method to the system you get full access to the canvas as you normally would in Flame.

class SimpleRenderSystem extends System with RenderSystem {
  Query? _query;

  @override
  void init() {
    _query = createQuery([/* Your filters */]);
  }

  void render(Canvas canvas) {
    for (final entity in _query?.entities ?? <Entity>[]) {
      // Render entity based on components
    }
  }
}

mixin UpdateSystem

The MixinSystem mixin allows a system to be registered for the update loop. By adding a update method to the system you get full access to the delta time as you normally would in Flame.

class SimpleUpdateSystem extends System with UpdateSystem {
  Query? _query;

  @override
  void init() {
    _query = createQuery([/* Your filters */]);
  }

  void update(double dt) {
    for (final entity in _query?.entities ?? <Entity>[]) {
      // Update components values
    }
  }
}

BaseSystem

The BaseSystem is an abstract class whose logic can be compared to the PositionComponent from FCS. The BaseSystem automatically filters all entities that have the PositionComponent and SizeComponent from flame_oxygen. On top of that you can add your own filters by defining a getter called filters. These filters are then used to filter down the entities you are interested in.

The BaseSystem is also fully aware of the game instance. You can access the game instance by using the game property. This also gives you access to the createEntity helper method on OxygenGame.

On each render loop the BaseSystem will prepare your canvas the same way the PositionComponent from FCS would (translating, rotating and setting the anchor. After that it will call the renderEntity method so you can add your own render logic for that entity on a prepared canvas.

The following components will be checked by BaseSystem for the preparation of the canvas:

  • PositionComponent (required)

  • SizeComponent (required)

  • AnchorComponent (optional, defaults to Anchor.topLeft)

  • AngleComponent (optional, defaults to 0)

class SimpleBaseSystem extends BaseSystem {
  @override
  List<Filter<Component>> get filters => [];

  @override
  void renderEntity(Canvas canvas, Entity entity) {
    // The canvas is translated, rotated and fully prepared for rendering.
  }
}

ParticleSystem

The ParticleSystem is a simple system that brings the Particle API from Flame to Oxygen. This allows you to use the ParticleComponent without having to worry about how it will render or when to update it. As most of that logic is already contained in the Particle itself.

Simply register the ParticleSystem and the ParticleComponent to your world like so:

world.registerSystem(ParticleSystem());

world.registerComponent<ParticleComponent, Particle>(() => ParticleComponent);

You can now create a new entity with a ParticleComponent. For more info about that see the ParticleComponent section.