]>
git.r.bdr.sh - rbdr/sumo/blob - lib/factories/sumo.js
1 import { Bodies
, Constraint
} from 'matter-js';
2 import { Entity
} from '@serpentity/serpentity';
6 import AngleComponent
from '@serpentity/components.angle';
7 import BodyComponent
from '../components/body';
8 import ControlMapComponent
from '../components/control_map';
9 import CoupledEntitiesComponent
from '../components/coupled_entities';
10 import DashComponent
from '../components/dash';
11 import ElasticComponent
from '../components/elastic';
12 import ForceComponent
from '@serpentity/components.force';
13 import GrabAreaComponent
from '../components/grab_area';
14 import GrabbableComponent
from '../components/grabbable';
15 import GrabComponent
from '../components/grab';
16 import MaxVelocityComponent
from '../components/max_velocity';
17 import PointsColliderComponent
from '../components/points_collider';
18 import PointsComponent
from '../components/points';
19 import PositionComponent
from '@serpentity/components.position';
20 import PixiContainerComponent
from '../components/pixi_container';
21 import WinnerComponent
from '../components/winner';
23 import PixiFactory
from '../factories/pixi';
24 import Config
from '../config';
27 kNoEntityError: 'Entity Not Found: This method requires entityA and entityB to be set in the config.',
28 kEntityHasNoBodyError: 'Entity Has No Body: This method requires entities have a BodyComponent.'
32 * Factory object that contains many methods to create prefab entities.
40 * Creates a sumo entity and adds it to the engine. Can override
41 * position in the config object
43 * @function createSumo
44 * @memberof SumoFactory
45 * @param {external:Serpentity} [engine] the serpentity engine to attach
46 * to. If not sent, it will not be attached.
47 * @param {object} [config] the config to override the entity, accepts
48 * the key `position` as an object with an x and y property.
49 * @return {external:Serpentity.Entity} the created entity
51 createSumo(engine
, config
= {}) {
53 const entity
= new Entity();
57 entity
.addComponent(new PositionComponent(config
.position
));
58 const position
= entity
.getComponent(PositionComponent
);
60 entity
.addComponent(new AngleComponent(config
.angle
));
61 const angle
= entity
.getComponent(AngleComponent
);
63 entity
.addComponent(new ForceComponent(config
.force
));
65 config
.maxVelocity
= {
68 entity
.addComponent(new MaxVelocityComponent(config
.maxVelocity
));
70 // CONTROLS & ABILITIES
72 entity
.addComponent(new DashComponent(config
.dash
));
77 const pixiConfig
= Object
.assign({
81 const container
= config
.container
|| {
82 container: PixiFactory
.createSumo(pixiConfig
)
84 container
.container
.position
.x
= position
.x
;
85 container
.container
.position
.y
= position
.y
;
86 container
.container
.rotation
= angle
.angle
;
87 entity
.addComponent(new PixiContainerComponent(container
));
91 const frictionAir
= 0.02;
92 const friction
= 0.01;
93 const frictionStatic
= 0.01;
94 const restitution
= 1;
97 const body
= Bodies
.circle(position
.x
/ Config
.meterSize
, position
.y
/ Config
.meterSize
, radius
/ Config
.meterSize
, {
106 entity
.addComponent(new BodyComponent({ body
}));
110 const areaSizeFactor
= 2; // Multiplier vs the radius
111 const area
= Bodies
.circle(position
.x
/ Config
.meterSize
, position
.y
/ Config
.meterSize
, (radius
* areaSizeFactor
) / Config
.meterSize
, {
112 label: 'Sumo Grab Area',
116 entity
.addComponent(new GrabAreaComponent({ area
}));
117 entity
.addComponent(new GrabComponent({ body
}));
118 entity
.addComponent(new GrabbableComponent({ body
}));
121 engine
.addEntity(entity
);
128 * Creates a rubber band entity and adds it to the engine.
130 * @function createRubberBand
131 * @memberof SumoFactory
132 * @param {external:Serpentity} [engine] the serpentity engine to attach
133 * to. If not sent, it will not be attached.
134 * @param {object} [config] the config to override the entity, it
135 * must include entityA and entityB which will be tied by it. If they
136 * are not sent or don't have a physics body, this will throw.
137 * @return {external:Serpentity.Entity} the created entity
139 createRubberBand(engine
, config
= {}) {
141 const entity
= new Entity();
143 if (!config
.entityA
|| !config
.entityB
) {
144 throw new Error(internals
.kNoEntityError
);
147 if (!config
.entityA
.hasComponent(BodyComponent
) || !config
.entityB
.hasComponent(BodyComponent
)) {
148 throw new Error(internals
.kEntityHasNoBodyError
);
153 const container
= config
.container
|| {
154 container: PixiFactory
.createEmptyGraphic()
156 entity
.addComponent(new PixiContainerComponent(container
));
160 const bodyA
= config
.entityA
.getComponent(BodyComponent
).body
;
161 const bodyB
= config
.entityB
.getComponent(BodyComponent
).body
;
163 const length
= 100 / Config
.meterSize
;
164 const stiffness
= 0.001;
166 const body
= Constraint
.create({
173 entity
.addComponent(new BodyComponent({ body
}));
175 entity
.addComponent(new CoupledEntitiesComponent({
176 coupledEntities: [config
.entityA
, config
.entityB
]
179 entity
.addComponent(new ElasticComponent());
182 engine
.addEntity(entity
);
189 * Creates a controllable sumo entity and adds it to the engine. Can override
190 * position in the config object
192 * @function createControllableSumo
193 * @memberof SumoFactory
194 * @param {external:Serpentity} [engine] the serpentity engine to attach
195 * to. If not sent, it will not be attached.
196 * @param {object} [config] the config to override the entity, accepts
197 * the key `position` as an object with an x and y property.
198 * @return {external:Serpentity.Entity} the created entity
200 createControllableSumo(engine
, config
= {}) {
202 const entity
= this.createSumo(null, config
);
204 entity
.addComponent(new ControlMapComponent(config
.controlMap
));
207 engine
.addEntity(entity
);
214 * Creates a controllable sumo entity and adds it to the engine. Can override
215 * position in the config object. Has contrrol scheme defaults for
218 * @function createPlayer1Sumo
219 * @memberof SumoFactory
220 * @param {external:Serpentity} [engine] the serpentity engine to attach
221 * to. If not sent, it will not be attached.
222 * @param {object} [config] the config to override the entity, accepts
223 * the key `position` as an object with an x and y property.
224 * @return {external:Serpentity.Entity} the created entity
226 createPlayer1Sumo(engine
, config
= {}) {
228 const playerConfig
= Object
.assign({
237 component: ForceComponent
,
239 value: (value
) => -Number(value
)
248 component: ForceComponent
,
250 value: (value
) => Number(value
)
259 component: ForceComponent
,
261 value: (value
) => -Number(value
)
270 component: ForceComponent
,
272 value: (value
) => Number(value
)
281 component: DashComponent
,
291 component: GrabComponent
,
299 gamepadInputSource: 'axes',
300 index: 0 // left stick horizontal
303 component: ForceComponent
,
305 value: (value
) => Number(value
)
312 gamepadInputSource: 'axes',
313 index: 1 // left stick vertical
316 component: ForceComponent
,
318 value: (value
) => Number(value
)
325 gamepadInputSource: 'buttons',
326 index: 2 // left face button
329 component: DashComponent
,
331 value: (value
) => value
.value
338 gamepadInputSource: 'buttons',
339 index: 0 // bottom face button
342 component: GrabComponent
,
343 property: 'grabbing',
344 value: (value
) => value
.value
351 const entity
= this.createControllableSumo(null, playerConfig
);
354 engine
.addEntity(entity
);
361 * Creates a controllable sumo entity and adds it to the engine. Can override
362 * position in the config object. Has contrrol scheme defaults for
365 * @function createPlayer2Sumo
366 * @memberof SumoFactory
367 * @param {external:Serpentity} [engine] the serpentity engine to attach
368 * to. If not sent, it will not be attached.
369 * @param {object} [config] the config to override the entity, accepts
370 * the key `position` as an object with an x and y property.
371 * @return {external:Serpentity.Entity} the created entity
373 createPlayer2Sumo(engine
, config
= {}) {
375 const playerConfig
= Object
.assign({
384 index: 37 // left arrow
387 component: ForceComponent
,
389 value: (value
) => -Number(value
)
395 index: 39 // right arrow
398 component: ForceComponent
,
400 value: (value
) => Number(value
)
406 index: 38 // up arrow
409 component: ForceComponent
,
411 value: (value
) => -Number(value
)
417 index: 40 // down arrow
420 component: ForceComponent
,
422 value: (value
) => Number(value
)
431 component: DashComponent
,
441 component: GrabComponent
,
449 gamepadInputSource: 'axes',
450 index: 0 // left stick horizontal
453 component: ForceComponent
,
455 value: (value
) => Number(value
)
462 gamepadInputSource: 'axes',
463 index: 1 // left stick vertical
466 component: ForceComponent
,
468 value: (value
) => Number(value
)
475 gamepadInputSource: 'buttons',
476 index: 2 // left face button
479 component: DashComponent
,
481 value: (value
) => value
.value
488 gamepadInputSource: 'buttons',
489 index: 0 // bottom face button
492 component: GrabComponent
,
493 property: 'grabbing',
494 value: (value
) => value
.value
501 const entity
= this.createControllableSumo(null, playerConfig
);
504 engine
.addEntity(entity
);
511 * Creates a static harness entity
513 * @function createHarness
514 * @memberof SumoFactory
515 * @param {external:Serpentity} [engine] the serpentity engine to attach
516 * to. If not sent, it will not be attached.
517 * @param {object} [config] the config to override the entity, accepts
518 * the key `position` as an object with an x and y property.
519 * @return {external:Serpentity.Entity} the created entity
521 createHarness(engine
, config
= {}) {
523 const entity
= new Entity();
527 entity
.addComponent(new PositionComponent(config
.position
));
528 const position
= entity
.getComponent(PositionComponent
);
534 const container
= config
.container
|| {
535 container: PixiFactory
.createHarness({ radius
})
537 container
.container
.position
.x
= position
.x
;
538 container
.container
.position
.y
= position
.y
;
539 entity
.addComponent(new PixiContainerComponent(container
));
544 const frictionStatic
= 0;
545 const restitution
= 1;
547 const body
= Bodies
.circle(position
.x
/ Config
.meterSize
, position
.y
/ Config
.meterSize
, radius
/ Config
.meterSize
, {
549 label: 'Harness body',
554 entity
.addComponent(new BodyComponent({ body
}));
557 engine
.addEntity(entity
);
564 * Creates a static arena entity
566 * @function createArena
567 * @memberof SumoFactory
568 * @param {external:Serpentity} [engine] the serpentity engine to attach
569 * to. If not sent, it will not be attached.
570 * @param {object} [config] the config to override the entity, accepts
571 * the key `position` as an object with an x and y property.
572 * @return {external:Serpentity.Entity} the created entity
574 createArena(engine
, config
= {}) {
576 const entity
= new Entity();
580 entity
.addComponent(new PositionComponent(config
.position
));
581 const position
= entity
.getComponent(PositionComponent
);
587 const container
= config
.container
|| {
588 container: PixiFactory
.createArena({ radius
})
590 container
.container
.position
.x
= position
.x
;
591 container
.container
.position
.y
= position
.y
;
592 entity
.addComponent(new PixiContainerComponent(container
));
595 engine
.addEntity(entity
);
602 * Creates an invisible block
604 * @function createInvisibleBlock
605 * @memberof SumoFactory
606 * @param {external:Serpentity} [engine] the serpentity engine to attach
607 * to. If not sent, it will not be attached.
608 * @param {object} [config] the config to override the entity, accepts
609 * the key `position` as an object with an x and y property.
610 * @return {external:Serpentity.Entity} the created entity
612 createInvisibleBlock(engine
, config
= {}) {
614 const entity
= new Entity();
618 entity
.addComponent(new PositionComponent(config
.position
));
619 const position
= entity
.getComponent(PositionComponent
);
624 const frictionStatic
= 0;
625 const restitution
= 1;
626 const label
= config
.label
|| 'Invisible Block';
627 const isSensor
= !!(config
.isSensor
);
629 const body
= Bodies
.rectangle(position
.x
/ Config
.meterSize
,
630 position
.y
/ Config
.meterSize
,
631 config
.width
/ Config
.meterSize
,
632 config
.height
/ Config
.meterSize
,
641 entity
.addComponent(new BodyComponent({ body
}));
644 engine
.addEntity(entity
);
651 * Creates an invisible block that accumulates points if certain
652 * entity collids with it
654 * @function createPointsCollider
655 * @memberof SumoFactory
656 * @param {external:Serpentity} [engine] the serpentity engine to attach
657 * to. If not sent, it will not be attached.
658 * @param {object} [config] the config to override the entity, accepts
659 * the key `position` as an object with an x and y property.
660 * @return {external:Serpentity.Entity} the created entity
662 createPointsCollider(engine
, config
= {}) {
664 const entity
= this.createInvisibleBlock(null, Object
.assign({
666 label: 'Points Detector'
671 entity
.addComponent(new PointsColliderComponent(config
));
674 engine
.addEntity(entity
);
681 * Creates an entity representing the game state
683 * @function createGameState
684 * @memberof SumoFactory
685 * @param {external:Serpentity} [engine] the serpentity engine to attach
686 * to. If not sent, it will not be attached.
687 * @param {object} [config] the config to override the entity, accepts
688 * the key `position` as an object with an x and y property.
689 * @return {external:Serpentity.Entity} the created entity
691 createGameState(engine
, config
= {}) {
693 const entity
= new Entity();
695 entity
.addComponent(new PointsComponent(config
));
696 entity
.addComponent(new WinnerComponent(config
));
699 engine
.addEntity(entity
);