Entity States & Activation
When dealing with many entities TypeSpriteJS offers the ability to deactivate entities that are not important to current events on the screen. Each Entity is in one of the following states: static
, active
, deactive
, disposed
or in error
. Depending on the states they will consome different amount of CPU load per frame.
City-Example: think of a large simulated 2d top down city. Caps drive around, lights go from green to red, people interact with each other. As a player you can walk around, get into a car and give it a go. Imagine every one of those objects is an Entity and every Entity is composed of many components. This can quickly sum up to 1000 of objects and cause heavy CPU loads.
In the given scenario it's best to figure out which objects are close to the camera and deactivate them if they move out of the camera. Like this:
Active
entities are the ones inside the camera rectangle and deactive
are the ones outside. static
(also called always Active
) are objects that you as a game developer know will always be active. For example an Entity that controls the health bar in the UI will live as long as the world is running. It will never become deavtive because it moves out of the camera.
It's also possible to call dispose()
on an Entity and destroy it and it`s Components. The object then becomes deactive and never come back. Think of a bullet that was fired and is not needed anymore. However, it takes TypeSpriteJS till the end of the current frame to actually remove the object. For this short period of time an Entity is flagged as disposed before it gets freed.
TIP
Like the sprites? Visit Kenney's Assets
Entity States events in Components
When implementing Components there are certain live-cycle-methods that will be called every time the Entity changes it`s activation state:
import {Component} from 'typesprite'
export class MyComponent extends Component {
onInit() {}
onActivate(): void {}
onUpdate(timeDelta:number) {}
onDeactivate(): void {}
onDispose(): void {}
}
\ | When Called | Call Order | Call Times |
---|---|---|---|
onInit() | When an Enitity is spawned. | Frist | Once |
onActivate() | Everytime the Entity switches to active state. | After onInit() | Once or more |
onUpdate() | Once per update step. | After onActivated() | When World & Entity is active |
onDeactivate() | Everytime the Entity switches to deactive state. | Always before onDispose() | Once or more |
onDispose() | Called when entity dies (or world stops/restarts) | Last | Once |
Notes on Errors
During onInit()
it is possible to throw a InitError()
instance. This allows you to make sure that the context in which the given Component is startet is correct. This won't crash the engine but simply skip the current Entity and print a console log output.
The same thing happens during initialization when an annotated field fails:
@res('number', "I am not a Number") // causes an InitError()
private power:number;
In such an event onInit()
won't be called and none of the rest.
Activation behavior
Activation is a very powerful tool to optimize performance. However, it's only helpful when implemented close to your game needs. If not set all worlds use ManualActivator
which has no automatic optimization in place. Entities always start active
and you can manually deactivate them by setting: this.entity.props.active = false;
.
To finetune the activation behvaitor you implement a BaseEntityActivator
and attach it to your world.
TODO Write about...
- how to implement an EntityActivator
- how to set an EntityActivator
- how activation anchor work