]> git.r.bdr.sh - rbdr/sumo/blame_incremental - lib/factories/sumo.js
Physics Engine (#4)
[rbdr/sumo] / lib / factories / sumo.js
... / ...
CommitLineData
1import { Bodies, Constraint } from 'matter-js';
2import { Entity } from '@serpentity/serpentity';
3
4import AngleComponent from '../components/angle';
5import BodyComponent from '../components/body';
6import CoupledEntitiesComponent from '../components/coupled_entities';
7import PositionComponent from '@serpentity/components.position';
8import PixiContainerComponent from '../components/pixi_container';
9import PixiFactory from '../factories/pixi';
10
11const internals = {
12 kNoEntityError: 'Entity Not Found: This method requires entityA and entityB to be set in the config.',
13 kEntityHasNoBodyError: 'Entity Has No Body: This method requires entities have a BodyComponent.'
14};
15
16/**
17 * Factory object that contains many methods to create prefab entities.
18 *
19 * @type object
20 * @name SumoFactory
21 */
22export default {
23
24 /**
25 * Creates a sumo entity and adds it to the engine. Can override
26 * position in the config object
27 *
28 * @function createSumo
29 * @memberof SumoFactory
30 * @param {external:Serpentity} [engine] the serpentity engine to attach
31 * to. If not sent, it will not be attached.
32 * @param {object} [config] the config to override the entity, accepts
33 * the key `position` as an object with an x and y property.
34 * @return {external:Serpentity.Entity} the created entity
35 */
36 createSumo(engine, config = {}) {
37
38 const entity = new Entity();
39
40 // POSITION
41
42 entity.addComponent(new PositionComponent(config.position));
43 const position = entity.getComponent(PositionComponent);
44
45 entity.addComponent(new AngleComponent(config.angle));
46 const angle = entity.getComponent(AngleComponent);
47
48 // RENDERING
49
50 const radius = 25;
51
52 const container = config.container || {
53 container: PixiFactory.createSumo({ radius })
54 };
55 container.container.position.x = position.x;
56 container.container.position.y = position.y;
57 container.container.rotation = angle.angle;
58 entity.addComponent(new PixiContainerComponent(container));
59
60 // PHYSICS
61
62 const frictionAir = 0.00001;
63 const friction = 0.00001;
64 const restitution = 0.9;
65 const density = 0.5;
66
67 const body = Bodies.circle(position.x, position.y, radius, {
68 angle: angle.angle,
69 density,
70 frictionAir,
71 friction,
72 restitution
73 });
74 entity.addComponent(new BodyComponent({ body }));
75
76 if (engine) {
77 engine.addEntity(entity);
78 }
79
80 return entity;
81 },
82
83 /**
84 * Creates a rubber band entity and adds it to the engine.
85 *
86 * @function createRubberBand
87 * @memberof SumoFactory
88 * @param {external:Serpentity} [engine] the serpentity engine to attach
89 * to. If not sent, it will not be attached.
90 * @param {object} [config] the config to override the entity, it
91 * must include entityA and entityB which will be tied by it. If they
92 * are not sent or don't have a physics body, this will throw.
93 * @return {external:Serpentity.Entity} the created entity
94 */
95 createRubberBand(engine, config = {}) {
96
97 const entity = new Entity();
98
99 if (!config.entityA || !config.entityB) {
100 throw new Error(internals.kNoEntityError);
101 }
102
103 if (!config.entityA.hasComponent(BodyComponent) || !config.entityB.hasComponent(BodyComponent)) {
104 throw new Error(internals.kEntityHasNoBodyError);
105 }
106
107 // RENDERING
108
109 const container = config.container || {
110 container: PixiFactory.createEmptyGraphic()
111 };
112 entity.addComponent(new PixiContainerComponent(container));
113
114 // PHYSICS
115
116 const bodyA = config.entityA.getComponent(BodyComponent).body;
117 const bodyB = config.entityB.getComponent(BodyComponent).body;
118 const damping = 0.01;
119 const length = 100;
120 const stiffness = 0.0001;
121 const angularStiffness = 0.0001;
122
123 const body = Constraint.create({
124 bodyA,
125 bodyB,
126 damping,
127 length,
128 stiffness,
129 angularStiffness
130 });
131 entity.addComponent(new BodyComponent({ body }));
132
133 entity.addComponent(new CoupledEntitiesComponent({
134 coupledEntities: [config.entityA, config.entityB]
135 }));
136
137 if (engine) {
138 engine.addEntity(entity);
139 }
140
141 return entity;
142 }
143};