]>
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 '../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 '../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 PositionComponent
from '@serpentity/components.position';
18 import PixiContainerComponent
from '../components/pixi_container';
20 import PixiFactory
from '../factories/pixi';
21 import Config
from '../config';
24 kNoEntityError: 'Entity Not Found: This method requires entityA and entityB to be set in the config.',
25 kEntityHasNoBodyError: 'Entity Has No Body: This method requires entities have a BodyComponent.'
29 * Factory object that contains many methods to create prefab entities.
37 * Creates a sumo entity and adds it to the engine. Can override
38 * position in the config object
40 * @function createSumo
41 * @memberof SumoFactory
42 * @param {external:Serpentity} [engine] the serpentity engine to attach
43 * to. If not sent, it will not be attached.
44 * @param {object} [config] the config to override the entity, accepts
45 * the key `position` as an object with an x and y property.
46 * @return {external:Serpentity.Entity} the created entity
48 createSumo(engine
, config
= {}) {
50 const entity
= new Entity();
54 entity
.addComponent(new PositionComponent(config
.position
));
55 const position
= entity
.getComponent(PositionComponent
);
57 entity
.addComponent(new AngleComponent(config
.angle
));
58 const angle
= entity
.getComponent(AngleComponent
);
60 entity
.addComponent(new ForceComponent(config
.force
));
62 config
.maxVelocity
= {
65 entity
.addComponent(new MaxVelocityComponent(config
.maxVelocity
));
67 // CONTROLS & ABILITIES
69 entity
.addComponent(new DashComponent(config
.dash
));
74 const pixiConfig
= Object
.assign({
78 const container
= config
.container
|| {
79 container: PixiFactory
.createSumo(pixiConfig
)
81 container
.container
.position
.x
= position
.x
;
82 container
.container
.position
.y
= position
.y
;
83 container
.container
.rotation
= angle
.angle
;
84 entity
.addComponent(new PixiContainerComponent(container
));
88 const frictionAir
= 0.02;
89 const friction
= 0.01;
90 const frictionStatic
= 0.01;
91 const restitution
= 1;
94 const body
= Bodies
.circle(position
.x
/ Config
.meterSize
, position
.y
/ Config
.meterSize
, radius
/ Config
.meterSize
, {
103 entity
.addComponent(new BodyComponent({ body
}));
107 const areaSizeFactor
= 2; // Multiplier vs the radius
108 const area
= Bodies
.circle(position
.x
/ Config
.meterSize
, position
.y
/ Config
.meterSize
, (radius
* areaSizeFactor
) / Config
.meterSize
, {
109 label: 'Sumo Grab Area',
113 entity
.addComponent(new GrabAreaComponent({ area
}));
114 entity
.addComponent(new GrabComponent({ body
}));
115 entity
.addComponent(new GrabbableComponent({ body
}));
118 engine
.addEntity(entity
);
125 * Creates a rubber band entity and adds it to the engine.
127 * @function createRubberBand
128 * @memberof SumoFactory
129 * @param {external:Serpentity} [engine] the serpentity engine to attach
130 * to. If not sent, it will not be attached.
131 * @param {object} [config] the config to override the entity, it
132 * must include entityA and entityB which will be tied by it. If they
133 * are not sent or don't have a physics body, this will throw.
134 * @return {external:Serpentity.Entity} the created entity
136 createRubberBand(engine
, config
= {}) {
138 const entity
= new Entity();
140 if (!config
.entityA
|| !config
.entityB
) {
141 throw new Error(internals
.kNoEntityError
);
144 if (!config
.entityA
.hasComponent(BodyComponent
) || !config
.entityB
.hasComponent(BodyComponent
)) {
145 throw new Error(internals
.kEntityHasNoBodyError
);
150 const container
= config
.container
|| {
151 container: PixiFactory
.createEmptyGraphic()
153 entity
.addComponent(new PixiContainerComponent(container
));
157 const bodyA
= config
.entityA
.getComponent(BodyComponent
).body
;
158 const bodyB
= config
.entityB
.getComponent(BodyComponent
).body
;
160 const length
= 100 / Config
.meterSize
;
161 const stiffness
= 0.001;
163 const body
= Constraint
.create({
170 entity
.addComponent(new BodyComponent({ body
}));
172 entity
.addComponent(new CoupledEntitiesComponent({
173 coupledEntities: [config
.entityA
, config
.entityB
]
176 entity
.addComponent(new ElasticComponent());
179 engine
.addEntity(entity
);
186 * Creates a controllable sumo entity and adds it to the engine. Can override
187 * position in the config object
189 * @function createControllableSumo
190 * @memberof SumoFactory
191 * @param {external:Serpentity} [engine] the serpentity engine to attach
192 * to. If not sent, it will not be attached.
193 * @param {object} [config] the config to override the entity, accepts
194 * the key `position` as an object with an x and y property.
195 * @return {external:Serpentity.Entity} the created entity
197 createControllableSumo(engine
, config
= {}) {
199 const entity
= this.createSumo(null, config
);
201 entity
.addComponent(new ControlMapComponent(config
.controlMap
));
204 engine
.addEntity(entity
);
211 * Creates a controllable sumo entity and adds it to the engine. Can override
212 * position in the config object. Has contrrol scheme defaults for
215 * @function createPlayer1Sumo
216 * @memberof SumoFactory
217 * @param {external:Serpentity} [engine] the serpentity engine to attach
218 * to. If not sent, it will not be attached.
219 * @param {object} [config] the config to override the entity, accepts
220 * the key `position` as an object with an x and y property.
221 * @return {external:Serpentity.Entity} the created entity
223 createPlayer1Sumo(engine
, config
= {}) {
225 const playerConfig
= Object
.assign({
234 component: ForceComponent
,
236 value: (value
) => -Number(value
)
245 component: ForceComponent
,
247 value: (value
) => Number(value
)
256 component: ForceComponent
,
258 value: (value
) => -Number(value
)
267 component: ForceComponent
,
269 value: (value
) => Number(value
)
278 component: DashComponent
,
288 component: GrabComponent
,
296 gamepadInputSource: 'axes',
297 index: 0 // left stick horizontal
300 component: ForceComponent
,
302 value: (value
) => Number(value
)
309 gamepadInputSource: 'axes',
310 index: 1 // left stick vertical
313 component: ForceComponent
,
315 value: (value
) => Number(value
)
322 gamepadInputSource: 'buttons',
323 index: 2 // left face button
326 component: DashComponent
,
328 value: (value
) => value
.value
335 gamepadInputSource: 'buttons',
336 index: 0 // bottom face button
339 component: GrabComponent
,
340 property: 'grabbing',
341 value: (value
) => value
.value
348 const entity
= this.createControllableSumo(null, playerConfig
);
351 engine
.addEntity(entity
);
358 * Creates a controllable sumo entity and adds it to the engine. Can override
359 * position in the config object. Has contrrol scheme defaults for
362 * @function createPlayer2Sumo
363 * @memberof SumoFactory
364 * @param {external:Serpentity} [engine] the serpentity engine to attach
365 * to. If not sent, it will not be attached.
366 * @param {object} [config] the config to override the entity, accepts
367 * the key `position` as an object with an x and y property.
368 * @return {external:Serpentity.Entity} the created entity
370 createPlayer2Sumo(engine
, config
= {}) {
372 const playerConfig
= Object
.assign({
381 index: 37 // left arrow
384 component: ForceComponent
,
386 value: (value
) => -Number(value
)
392 index: 39 // right arrow
395 component: ForceComponent
,
397 value: (value
) => Number(value
)
403 index: 38 // up arrow
406 component: ForceComponent
,
408 value: (value
) => -Number(value
)
414 index: 40 // down arrow
417 component: ForceComponent
,
419 value: (value
) => Number(value
)
428 component: DashComponent
,
438 component: GrabComponent
,
446 gamepadInputSource: 'axes',
447 index: 0 // left stick horizontal
450 component: ForceComponent
,
452 value: (value
) => Number(value
)
459 gamepadInputSource: 'axes',
460 index: 1 // left stick vertical
463 component: ForceComponent
,
465 value: (value
) => Number(value
)
472 gamepadInputSource: 'buttons',
473 index: 2 // left face button
476 component: DashComponent
,
478 value: (value
) => value
.value
485 gamepadInputSource: 'buttons',
486 index: 0 // bottom face button
489 component: GrabComponent
,
490 property: 'grabbing',
491 value: (value
) => value
.value
498 const entity
= this.createControllableSumo(null, playerConfig
);
501 engine
.addEntity(entity
);
508 * Creates a static harness entity
510 * @function createHarness
511 * @memberof SumoFactory
512 * @param {external:Serpentity} [engine] the serpentity engine to attach
513 * to. If not sent, it will not be attached.
514 * @param {object} [config] the config to override the entity, accepts
515 * the key `position` as an object with an x and y property.
516 * @return {external:Serpentity.Entity} the created entity
518 createHarness(engine
, config
= {}) {
520 const entity
= new Entity();
524 entity
.addComponent(new PositionComponent(config
.position
));
525 const position
= entity
.getComponent(PositionComponent
);
531 const container
= config
.container
|| {
532 container: PixiFactory
.createHarness({ radius
})
534 container
.container
.position
.x
= position
.x
;
535 container
.container
.position
.y
= position
.y
;
536 entity
.addComponent(new PixiContainerComponent(container
));
541 const frictionStatic
= 0;
542 const restitution
= 1;
544 const body
= Bodies
.circle(position
.x
/ Config
.meterSize
, position
.y
/ Config
.meterSize
, radius
/ Config
.meterSize
, {
546 label: 'Harness body',
551 entity
.addComponent(new BodyComponent({ body
}));
554 engine
.addEntity(entity
);
561 * Creates a static arena entity
563 * @function createArena
564 * @memberof SumoFactory
565 * @param {external:Serpentity} [engine] the serpentity engine to attach
566 * to. If not sent, it will not be attached.
567 * @param {object} [config] the config to override the entity, accepts
568 * the key `position` as an object with an x and y property.
569 * @return {external:Serpentity.Entity} the created entity
571 createArena(engine
, config
= {}) {
573 const entity
= new Entity();
577 entity
.addComponent(new PositionComponent(config
.position
));
578 const position
= entity
.getComponent(PositionComponent
);
584 const container
= config
.container
|| {
585 container: PixiFactory
.createArena({ radius
})
587 container
.container
.position
.x
= position
.x
;
588 container
.container
.position
.y
= position
.y
;
589 entity
.addComponent(new PixiContainerComponent(container
));
592 engine
.addEntity(entity
);
599 * Creates an invisible block
601 * @function createInvisibleBlock
602 * @memberof SumoFactory
603 * @param {external:Serpentity} [engine] the serpentity engine to attach
604 * to. If not sent, it will not be attached.
605 * @param {object} [config] the config to override the entity, accepts
606 * the key `position` as an object with an x and y property.
607 * @return {external:Serpentity.Entity} the created entity
609 createInvisibleBlock(engine
, config
= {}) {
611 const entity
= new Entity();
615 entity
.addComponent(new PositionComponent(config
.position
));
616 const position
= entity
.getComponent(PositionComponent
);
621 const frictionStatic
= 0;
622 const restitution
= 1;
624 const body
= Bodies
.rectangle(position
.x
/ Config
.meterSize
,
625 position
.y
/ Config
.meterSize
,
626 config
.width
/ Config
.meterSize
,
627 config
.height
/ Config
.meterSize
,
630 label: 'Invisible Block',
635 entity
.addComponent(new BodyComponent({ body
}));
638 engine
.addEntity(entity
);