Skip to content

Flambe core

Mark Knol edited this page Jun 24, 2014 · 29 revisions
### Philosophy > Flambe mostly uses composition over inheritance. Flambe uses an entity/component system rather than sprawling inheritance hierarchies. The composition pattern also comes up repeatedly in other parts of Flambe's design.

How does the entity-component system work?

An entity is an object in a game. Entities don't do anything on their own, Components are attached to them to add data and logic. Entities are also hierarchical -- they can have other entities as children. This hierarchy when combined with the Sprite component, delivers the familiar Flash-like scene graph, but with the flexibility of being able to add other types of components.

Some components override each other if they have a common parent class. Adding a FillSprite to an entity for example will replace its ImageSprite. That's because they both extend Sprite. Since Sprite extends Component, anything that subclasses Sprite will share the "Sprite" namespace. Under the hood, this is implemented by giving a unique ID to each class that directly extends Component.

Entities

The entity is a general purpose object. You can nest Entities inside an Entity (addChild-function) but you can also add Components (add-function). You cannot extend a Entity. The Entities define the hierarchy and order of the 'displaylist'/rendering order. In Flambe, every entity has these important functions:

  • addChild(entity:Entity) Adds a child Entity (to nest entities)
  • removeChild(entity:Entity) Remove a child Entity
  • add(component:Component) Add a component to this entity. Any previous component of this type will be replaced.
  • remove(component:Component) Remove a component from this entity.
  • get(componentClass:Class) Gets a component of a given type from this entity.
  • getComponent(name:String) Gets a component by name from this entity.
  • has(componentClass:Class) Checks if this entity has a component of the given type.
  • disposeChildren() Dispose all of this entity's children, without touching its own components or removing itself from its parent.
  • dispose() Removes this entity from its parent, and disposes all its components and children.

Entity API Docs

Components

Components are bits of data and logic that can be added to entities. The component consists of a minimal set of data needed for a specific purpose. In Flambe, every component has 4 important functions:

  • onAdded() Called after this component has been added to an entity. owner is available after being added. The order of adding matters, in case you want to grab other components from the owner inside this function.
  • onUpdate(deltaTime:Float) Called when this component receives a game update.
  • onRemoved() Called just before this component has been removed from its entity.
  • dispose() Removes this component from its owning entity.
  • owner The Entity this component is attached to (can be null).

Component API Docs

The game timer is in every component

The onUpdate-function is called when this component receives a 'game' update, with delta time (The time elapsed since the last 'frame'). Flambe is framerate independent, but targeted at 60 FPS (frames per second). All animation/coded motion should be based on time using this delta time.

Destruction

This dispose function removes this component from its owning entity. You should override the dispose-function in order to dispose objects yourself, to prevent memory leaks.

Code examples

Create entity, add components

This is a example to illustrate how to add a entity to the root, with a visual component that displays a blue square of 100x100px, using a FillSprite

// Create Sprite Component
var mySprite:FillSprite = new FillSprite(0x154d79, 100, 100);
// Set position
mySprite.setXY(30,30);

// Create Entity
var myEntity:Entity = new Entity();
// Add the component
myEntity.add(mySprite); 

// Add Entity to the root of the System, so it will show up on your screen.
System.root.addChild(myEntity);

This can be written much shorter.

// Create entity and add a Sprite Component.
System.root.addChild(new Entity()
	.add(new FillSprite(0x154d79, 100, 100).setXY(30,30))
);

Nesting entities

This is a example to illustrate how to nest two Sprites.

var myEntity = new Entity()
	.add(new FillSprite(0x154d79, 100, 100)); // blue square

var myNestedEntity = new Entity()
	.add(new FillSprite(0xefbf74, 40, 40)); // orange square

System.root.addChild(myEntity);
myEntity.addChild(myNestedEntity);

This can also be written shorter:

System.root.addChild(new Entity()
	.add(new FillSprite(0x154d79, 100, 100))
	.addChild(new Entity()
		.add(new FillSprite(0xefbf74, 40, 40)))
);

The short notation is very useful when you want to add a lot of components, imagine all these (non-existent) components. This is how you could plug features.

System.root.addChild(new Entity()
	.add(new FillSprite(0x154d79, 100, 100))
   	.add(new Disposer())
   	.add(new CarAccelerator())
   	.add(new LapCounter())
   	.add(new Path(myPath))
   	.add(new PathFollower())
	.add(new SpeedDetector())
   	.add(new PowerUpApplier())
   	.add(new Progress(1.0))
   	.add(new Bot())
);

Grab a component from Entity

In this example an Entity has a Sprite. We try to grab it back out of the Entity. Sometimes, you can assume there is a class of given type in the Entity (based on your code architecture), but to be sure it is really there, you could do a null-check. Alternatively you can also choose to check with entity.has(Sprite).

var sprite = myEntity.get(Sprite); 

if (sprite != null) 
{ 
	trace('sprite found in entity: $sprite');
}
else
{
	trace('Warn: No sprite found.');
}

The fun part of this, is that you can swap the actual Sprite with any other Sprite (like FillSprite, ImageSprite, PatternSprite etc..). If you still use entity.get(Sprite), it returns that sprite. That allows you to create loose assumptions, which gives some flexibility.

Get the entity inside a component class

You can grab the owner of the component, this is the Entity. The owner is available in the onAdded- function, not in the constructor.

package;
class MyComponent extends Component
{
   override public function onAdded()
   {
       // get the entity this component is attached to
       trace( owner ); 

       // get Sprite in current Entity
       trace( owner.get(Sprite) ); 

       // get Sprite x position in current Entity
       trace( owner.get(Sprite).x._ ); 
   }
}

Loop through components of an Entity

To iterate over the hierarchy, use the parent, firstChild, next and firstComponent fields. For example:

var child = entity.firstComponent;
while (child != null) 
{
	var next = child.next; 
	
	// do something with child here
	doSomethingWith(child);
	
	child = next;
}

More info on entity/component system

Working with Entities and components can be confusing if you are used to OOP. There are better (non-Flambe) articles written by skilled developers about this workflow with entities and components. Some article describe slightly other implementations of the whole system; some even in other programming languages. It could give a bit more understanding about this interesting concept, but also about code organization and how to get familiar with it.

Wikipedia: Entity component system
Game Programming Patterns: Component
Evolve Your Hierarchy
T-Machine Entity Systems
Case study: Bomberman mechanics
Component-based engine design
What is an entity framework

Clone this wiki locally