UNPKG

4.5 kBMarkdownView Raw
1# super-ecs
2Entity Component System library for JavaScript/TypeScript games.
3
4- **API Docs:** https://goldenratio.github.io/super-ecs/
5- **Example Repo:** https://github.com/goldenratio/super-ecs-example
6- **Example Repo (Vanilla JS):** https://github.com/goldenratio/super-ecs-vanilla-js-example
7- **CDN:** https://unpkg.com/browse/super-ecs/dist/
8
9> npm install --save super-ecs
10
11https://www.npmjs.com/package/super-ecs
12
13## Basic Usage
14To define a new component, simply implement `Component`.
15Note that each component should have a unique `name` property.
16
17```js
18const COMPONENT_NAMES = {
19 Position: Symbol('Position'),
20 Velocity: Symbol('Velocity'),
21 Health: Symbol('Health')
22};
23
24class Position {
25 name = COMPONENT_NAMES.Position;
26 constructor({ x = 0, y = 0 }) {
27 this.x = x;
28 this.y = y;
29 }
30}
31
32class Velocity {
33 name = COMPONENT_NAMES.Velocity;
34 constructor({ x = 0, y = 0 }) {
35 this.x = x;
36 this.y = y;
37 }
38}
39
40class Health {
41 name = COMPONENT_NAMES.Health;
42 constructor({ maxHealth = 100 }) {
43 this.health = maxHealth;
44 this.maxHealth = maxHealth;
45 }
46
47 isDead() {
48 return this.health <= 0;
49 }
50
51 receiveDamage(damage) {
52 this.health -= damage;
53 }
54}
55```
56
57An entity is essentially a container of one or more components.
58
59```js
60const hero = new Entity();
61hero.addComponent(new Position({ x: 0, y: 0 }));
62hero.addComponent(new Velocity({ x: 0, y: 0 }));
63hero.addComponent(new Health({ maxHealth: 50 }));
64```
65
66The system is responsible for updating the entities.
67In a real game there may be a lot of systems, like `CollisionSystem`,
68`RenderSystem`, `ControlSystem` etc.
69
70```js
71class PhysicSystem extends System {
72
73 update(delta) {
74
75 const entities = this.world.getEntities([COMPONENT_NAMES.Position, COMPONENT_NAMES.Velocity]);
76 entities.forEach(entity => {
77 const position = entity.getComponent(COMPONENT_NAMES.Position);
78 const velocity = entity.getComponent(COMPONENT_NAMES.Velocity);
79 if (position && velocity) {
80 position.x += velocity.x * delta;
81 position.y += velocity.y * delta;
82 }
83 });
84 }
85}
86```
87
88The world is the container of all the entities and systems.
89Calling the `update` method will *sequentially* update all the systems,
90in the order they were added.
91
92```js
93const world = new World();
94
95world.addEntity(hero);
96// ... add other entities
97
98world.addSystem(new PhysicSystem());
99// ... add other systems
100
101requestAnimationFrame(function () {
102 world.update(/* interval */);
103})
104```
105
106A system is notified when it is added or removed from the world:
107
108```js
109class MySystem extends System {
110
111 addedToWorld(world) {
112 super.addedToWorld(world);
113 // Code to handle being added to world. Remember to call `super`.
114 }
115
116 removedFromWorld(world) {
117 super.removedFromWorld(world);
118 // Code to handle being removed from world.. Remember to call `super`.
119 }
120}
121```
122
123The world emits Observable when entities are added or removed. You can listen for
124specific entities and handle the Observable accordingly:
125
126```js
127class MySystem extends System {
128
129 removedFromWorld(world) {
130 super.removedFromWorld(world);
131 if (this._disposeBag) {
132 this._disposeBag.dispose();
133 }
134 }
135
136 addedToWorld(world) {
137 super.addedToWorld(world);
138 // Code to handle being added to world. Remember to call `super`.
139
140 this._disposeBag = new DisposeBag();
141
142 this._disposeBag.completable$(world.entityAdded$([COMPONENT_NAMES.Position, COMPONENT_NAMES.Velocity]))
143 .subscribe(entity => {
144 // This function is called whenever an entity with both 'position' and
145 // 'velocity' components is added to the world. It can also be called when
146 // a component is added to an entity; for example, when an entity with
147 // only 'position' has 'velocity' added to it.
148 });
149
150 this._disposeBag.completable$(world.entityRemoved$([COMPONENT_NAMES.Position, COMPONENT_NAMES.Velocity]))
151 .subscribe(entity => {
152 // This function is called whenever an entity with both 'position' and
153 // 'velocity' components is removed from the world. It can also be called
154 // when a component is removed from an entity; for example, when an entity
155 // with both 'position' and 'velocity' has 'velocity' removed from it.
156 });
157 }
158}
159```
160
161Port of [CES.js](https://github.com/qiao/ces.js) with some changes,
162- instead of `signal`, we use `rxjs`
163- component names should be of type `symbol`
164
165## Release
166```
167npm version {major | minor | patch}
168npm publish
169```