]> git.r.bdr.sh - rbdr/sumo/commitdiff
Physics Engine (#4)
authorRubén Beltrán del Río <redacted>
Sat, 21 Apr 2018 22:45:38 +0000 (17:45 -0500)
committerGitHub <redacted>
Sat, 21 Apr 2018 22:45:38 +0000 (17:45 -0500)
* Add matter-js as a dependency

* Add body component

* Fix renderable node doc

* Add the physics node type

* Correct typo in physics enabled node types

* Update docs on render system

* Add physics system

* Update changelog

* Add physics engine to main app

* Tweak the gravity of the world

* Add body to sumo factory

* Add angle component

* Add angle to entity

* Add angle to the nodes

* Pass angle between systems

* Set default angle to 0

* Split systems and nodes

* Fix indentaion in physics world control

* Add third sumo entity

* Adjust values for constriants and physics

* Correct docs in new nodes

* Update built-in docs

20 files changed:
CHANGELOG.md
doc/README.md
lib/components/angle.js [new file with mode: 0644]
lib/components/body.js [new file with mode: 0644]
lib/components/coupled_entities.js [new file with mode: 0644]
lib/factories/pixi.js
lib/factories/sumo.js
lib/nodes/physical.js [new file with mode: 0644]
lib/nodes/physical_with_attributes.js [new file with mode: 0644]
lib/nodes/renderable.js
lib/nodes/renderable_couple.js [new file with mode: 0644]
lib/nodes/renderable_with_attributes.js [new file with mode: 0644]
lib/sumo.js
lib/systems/attributes_to_renderable.js [new file with mode: 0644]
lib/systems/create_coupling_line.js [new file with mode: 0644]
lib/systems/physics_to_attributes.js [new file with mode: 0644]
lib/systems/physics_world_control.js [new file with mode: 0644]
lib/systems/render.js
package-lock.json
package.json

index d5e5ad3e4d110e983c804f86aa1c245f7196b735..5fc6da332cd6592d2f80b24a5a8126da192b50fb 100644 (file)
@@ -15,5 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 - This CHANGELOG
 - A README
 - A CONTRIBUTING guide
 - This CHANGELOG
 - A README
 - A CONTRIBUTING guide
+- Pixi powered renderer system
+- Matter-js powered physics system
 
 [Unreleased]: https://github.com/rbdr/sumo/compare/master...develop
 
 [Unreleased]: https://github.com/rbdr/sumo/compare/master...develop
index 2d79f303c85fad80b3489e3e5782b3bbffe7ee31..2d367a52284b7e4d538f84573a5dfdf9e183d8e7 100644 (file)
@@ -1,3 +1,268 @@
+## Classes
+
+<dl>
+<dt><a href="#AngleComponent">AngleComponent</a> ⇐ <code>external:Serpentity.Component</code></dt>
+<dd></dd>
+<dt><a href="#BodyComponent">BodyComponent</a> ⇐ <code>external:Serpentity.Component</code></dt>
+<dd></dd>
+<dt><a href="#CoupledEntitiesComponent">CoupledEntitiesComponent</a> ⇐ <code>external:Serpentity.Component</code></dt>
+<dd></dd>
+<dt><a href="#PixiContainerComponent">PixiContainerComponent</a> ⇐ <code>external:Serpentity.Component</code></dt>
+<dd></dd>
+<dt><a href="#PhysicalWithAttributesNode">PhysicalWithAttributesNode</a> ⇐ <code>external:Serpentity.Node</code></dt>
+<dd></dd>
+<dt><a href="#PhysicalNode">PhysicalNode</a> ⇐ <code>external:Serpentity.Node</code></dt>
+<dd></dd>
+<dt><a href="#RenderableCoupleNode">RenderableCoupleNode</a> ⇐ <code>external:Serpentity.Node</code></dt>
+<dd></dd>
+<dt><a href="#RenderableWithAttributesNode">RenderableWithAttributesNode</a> ⇐ <code>external:Serpentity.Node</code></dt>
+<dd></dd>
+<dt><a href="#RenderableNode">RenderableNode</a> ⇐ <code>external:Serpentity.Node</code></dt>
+<dd></dd>
+<dt><a href="#Sumo">Sumo</a></dt>
+<dd></dd>
+<dt><a href="#AttributesToRenderableSystem">AttributesToRenderableSystem</a> ⇐ <code>external:Serpentity.System</code></dt>
+<dd></dd>
+<dt><a href="#CreateCouplingLineSystem">CreateCouplingLineSystem</a> ⇐ <code>external:Serpentity.System</code></dt>
+<dd></dd>
+<dt><a href="#PhysicsToAttributesSystem">PhysicsToAttributesSystem</a> ⇐ <code>external:Serpentity.System</code></dt>
+<dd></dd>
+<dt><a href="#PhysicsWorldControlSystem">PhysicsWorldControlSystem</a> ⇐ <code>external:Serpentity.System</code></dt>
+<dd></dd>
+<dt><a href="#RenderSystem">RenderSystem</a> ⇐ <code>external:Serpentity.System</code></dt>
+<dd></dd>
+</dl>
+
+## Members
+
+<dl>
+<dt><a href="#PixiFactory">PixiFactory</a> : <code>object</code></dt>
+<dd><p>Factory object that contains many methods to create prefab pixi
+objects</p>
+</dd>
+<dt><a href="#SumoFactory">SumoFactory</a> : <code>object</code></dt>
+<dd><p>Factory object that contains many methods to create prefab entities.</p>
+</dd>
+</dl>
+
+<a name="AngleComponent"></a>
+
+## AngleComponent ⇐ <code>external:Serpentity.Component</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.Component</code>  
+<a name="new_AngleComponent_new"></a>
+
+### new AngleComponent(config)
+Component that stores an angle
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| config | <code>object</code> | a configuration object to extend. |
+
+<a name="BodyComponent"></a>
+
+## BodyComponent ⇐ <code>external:Serpentity.Component</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.Component</code>  
+<a name="new_BodyComponent_new"></a>
+
+### new BodyComponent(config)
+Component that stores a body for physics calculation
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| config | <code>object</code> | a configuration object to extend. |
+
+<a name="CoupledEntitiesComponent"></a>
+
+## CoupledEntitiesComponent ⇐ <code>external:Serpentity.Component</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.Component</code>  
+<a name="new_CoupledEntitiesComponent_new"></a>
+
+### new CoupledEntitiesComponent(config)
+Component that stores a number of entities coupled to this one.
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| config | <code>object</code> | a configuration object to extend. |
+
+<a name="PixiContainerComponent"></a>
+
+## PixiContainerComponent ⇐ <code>external:Serpentity.Component</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.Component</code>  
+
+* [PixiContainerComponent](#PixiContainerComponent) ⇐ <code>external:Serpentity.Component</code>
+    * [new PixiContainerComponent(config)](#new_PixiContainerComponent_new)
+    * [.container](#PixiContainerComponent+container)
+
+<a name="new_PixiContainerComponent_new"></a>
+
+### new PixiContainerComponent(config)
+Component that stores a pixi container
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| config | <code>object</code> | a configuration object to extend. |
+
+<a name="PixiContainerComponent+container"></a>
+
+### pixiContainerComponent.container
+The properthy that holds the pixi container
+
+**Kind**: instance property of [<code>PixiContainerComponent</code>](#PixiContainerComponent)  
+**Properties**
+
+| Name | Type |
+| --- | --- |
+| container | <code>external:PixiJs.Container</code> | 
+
+<a name="PhysicalWithAttributesNode"></a>
+
+## PhysicalWithAttributesNode ⇐ <code>external:Serpentity.Node</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.Node</code>  
+
+* [PhysicalWithAttributesNode](#PhysicalWithAttributesNode) ⇐ <code>external:Serpentity.Node</code>
+    * [new PhysicalWithAttributesNode()](#new_PhysicalWithAttributesNode_new)
+    * [.types](#PhysicalWithAttributesNode.types)
+
+<a name="new_PhysicalWithAttributesNode_new"></a>
+
+### new PhysicalWithAttributesNode()
+Node identifying an entity that can interact with physics and has
+components updated from its values
+
+<a name="PhysicalWithAttributesNode.types"></a>
+
+### PhysicalWithAttributesNode.types
+Holds the types that are used to identify an entity with a physics
+object and external attributes
+
+**Kind**: static property of [<code>PhysicalWithAttributesNode</code>](#PhysicalWithAttributesNode)  
+**Properties**
+
+| Name | Type |
+| --- | --- |
+| types | <code>object</code> | 
+
+<a name="PhysicalNode"></a>
+
+## PhysicalNode ⇐ <code>external:Serpentity.Node</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.Node</code>  
+
+* [PhysicalNode](#PhysicalNode) ⇐ <code>external:Serpentity.Node</code>
+    * [new PhysicalNode()](#new_PhysicalNode_new)
+    * [.types](#PhysicalNode.types)
+
+<a name="new_PhysicalNode_new"></a>
+
+### new PhysicalNode()
+Node identifying an entity that can interact with physics
+
+<a name="PhysicalNode.types"></a>
+
+### PhysicalNode.types
+Holds the types that are used to identify an entity with a physical
+body
+
+**Kind**: static property of [<code>PhysicalNode</code>](#PhysicalNode)  
+**Properties**
+
+| Name | Type |
+| --- | --- |
+| types | <code>object</code> | 
+
+<a name="RenderableCoupleNode"></a>
+
+## RenderableCoupleNode ⇐ <code>external:Serpentity.Node</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.Node</code>  
+
+* [RenderableCoupleNode](#RenderableCoupleNode) ⇐ <code>external:Serpentity.Node</code>
+    * [new RenderableCoupleNode()](#new_RenderableCoupleNode_new)
+    * [.types](#RenderableCoupleNode.types)
+
+<a name="new_RenderableCoupleNode_new"></a>
+
+### new RenderableCoupleNode()
+Node identifying an entity that has coupled entities and can be
+rendered
+
+<a name="RenderableCoupleNode.types"></a>
+
+### RenderableCoupleNode.types
+Holds the types that are used to identify a renderable couple
+
+**Kind**: static property of [<code>RenderableCoupleNode</code>](#RenderableCoupleNode)  
+**Properties**
+
+| Name | Type |
+| --- | --- |
+| types | <code>object</code> | 
+
+<a name="RenderableWithAttributesNode"></a>
+
+## RenderableWithAttributesNode ⇐ <code>external:Serpentity.Node</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.Node</code>  
+
+* [RenderableWithAttributesNode](#RenderableWithAttributesNode) ⇐ <code>external:Serpentity.Node</code>
+    * [new RenderableWithAttributesNode()](#new_RenderableWithAttributesNode_new)
+    * [.types](#RenderableWithAttributesNode.types)
+
+<a name="new_RenderableWithAttributesNode_new"></a>
+
+### new RenderableWithAttributesNode()
+Node identifying a renderable entity, should have position and a
+symbol to render
+
+<a name="RenderableWithAttributesNode.types"></a>
+
+### RenderableWithAttributesNode.types
+Holds the types that are used to identify a renderable with external
+attributes
+
+**Kind**: static property of [<code>RenderableWithAttributesNode</code>](#RenderableWithAttributesNode)  
+**Properties**
+
+| Name | Type |
+| --- | --- |
+| types | <code>object</code> | 
+
+<a name="RenderableNode"></a>
+
+## RenderableNode ⇐ <code>external:Serpentity.Node</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.Node</code>  
+
+* [RenderableNode](#RenderableNode) ⇐ <code>external:Serpentity.Node</code>
+    * [new RenderableNode()](#new_RenderableNode_new)
+    * [.types](#RenderableNode.types)
+
+<a name="new_RenderableNode_new"></a>
+
+### new RenderableNode()
+Node identifying a renderable entity, should have a pixi renderable
+
+<a name="RenderableNode.types"></a>
+
+### RenderableNode.types
+Holds the types that are used to identify a renderable entity
+
+**Kind**: static property of [<code>RenderableNode</code>](#RenderableNode)  
+**Properties**
+
+| Name | Type |
+| --- | --- |
+| types | <code>object</code> | 
+
 <a name="Sumo"></a>
 
 ## Sumo
 <a name="Sumo"></a>
 
 ## Sumo
@@ -40,3 +305,322 @@ live until after you stop and start the loop)
 Pauses the loop
 
 **Kind**: instance method of [<code>Sumo</code>](#Sumo)  
 Pauses the loop
 
 **Kind**: instance method of [<code>Sumo</code>](#Sumo)  
+<a name="AttributesToRenderableSystem"></a>
+
+## AttributesToRenderableSystem ⇐ <code>external:Serpentity.System</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.System</code>  
+
+* [AttributesToRenderableSystem](#AttributesToRenderableSystem) ⇐ <code>external:Serpentity.System</code>
+    * [new AttributesToRenderableSystem(config)](#new_AttributesToRenderableSystem_new)
+    * [.added(engine)](#AttributesToRenderableSystem+added)
+    * [.removed()](#AttributesToRenderableSystem+removed)
+    * [.update(currentFrameDuration)](#AttributesToRenderableSystem+update)
+
+<a name="new_AttributesToRenderableSystem_new"></a>
+
+### new AttributesToRenderableSystem(config)
+Updates the renderables based on their attribuets
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| config | <code>object</code> | a configuration object to extend. |
+
+<a name="AttributesToRenderableSystem+added"></a>
+
+### attributesToRenderableSystem.added(engine)
+Initializes system when added. Requests renderable nodes and
+attaches to event listeners to add / remove them to pixi stage
+
+**Kind**: instance method of [<code>AttributesToRenderableSystem</code>](#AttributesToRenderableSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| engine | <code>external:Serpentity.Engine</code> | the serpentity engine to which we are getting added |
+
+<a name="AttributesToRenderableSystem+removed"></a>
+
+### attributesToRenderableSystem.removed()
+Clears system resources when removed.
+
+**Kind**: instance method of [<code>AttributesToRenderableSystem</code>](#AttributesToRenderableSystem)  
+<a name="AttributesToRenderableSystem+update"></a>
+
+### attributesToRenderableSystem.update(currentFrameDuration)
+Runs on every update of the loop. Updates the graphics so they're
+rendered correctly
+
+**Kind**: instance method of [<code>AttributesToRenderableSystem</code>](#AttributesToRenderableSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| currentFrameDuration | <code>Number</code> | the duration of the current frame |
+
+<a name="CreateCouplingLineSystem"></a>
+
+## CreateCouplingLineSystem ⇐ <code>external:Serpentity.System</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.System</code>  
+
+* [CreateCouplingLineSystem](#CreateCouplingLineSystem) ⇐ <code>external:Serpentity.System</code>
+    * [new CreateCouplingLineSystem(config)](#new_CreateCouplingLineSystem_new)
+    * [.added(engine)](#CreateCouplingLineSystem+added)
+    * [.removed()](#CreateCouplingLineSystem+removed)
+    * [.update(currentFrameDuration)](#CreateCouplingLineSystem+update)
+
+<a name="new_CreateCouplingLineSystem_new"></a>
+
+### new CreateCouplingLineSystem(config)
+Renders renderable objects using pixi
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| config | <code>object</code> | a configuration object to extend. |
+
+<a name="CreateCouplingLineSystem+added"></a>
+
+### createCouplingLineSystem.added(engine)
+Initializes system when added. Requests renderable nodes and
+
+**Kind**: instance method of [<code>CreateCouplingLineSystem</code>](#CreateCouplingLineSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| engine | <code>external:Serpentity.Engine</code> | the serpentity engine to which we are getting added |
+
+<a name="CreateCouplingLineSystem+removed"></a>
+
+### createCouplingLineSystem.removed()
+Clears system resources when removed.
+
+**Kind**: instance method of [<code>CreateCouplingLineSystem</code>](#CreateCouplingLineSystem)  
+<a name="CreateCouplingLineSystem+update"></a>
+
+### createCouplingLineSystem.update(currentFrameDuration)
+Runs on every update of the loop. Does nothing.
+
+**Kind**: instance method of [<code>CreateCouplingLineSystem</code>](#CreateCouplingLineSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| currentFrameDuration | <code>Number</code> | the duration of the current frame |
+
+<a name="PhysicsToAttributesSystem"></a>
+
+## PhysicsToAttributesSystem ⇐ <code>external:Serpentity.System</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.System</code>  
+
+* [PhysicsToAttributesSystem](#PhysicsToAttributesSystem) ⇐ <code>external:Serpentity.System</code>
+    * [new PhysicsToAttributesSystem(config)](#new_PhysicsToAttributesSystem_new)
+    * [.added(engine)](#PhysicsToAttributesSystem+added)
+    * [.removed()](#PhysicsToAttributesSystem+removed)
+    * [.update(currentFrameDuration)](#PhysicsToAttributesSystem+update)
+
+<a name="new_PhysicsToAttributesSystem_new"></a>
+
+### new PhysicsToAttributesSystem(config)
+Distribuets physics data to the related components
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| config | <code>object</code> | a configuration object to extend. |
+
+<a name="PhysicsToAttributesSystem+added"></a>
+
+### physicsToAttributesSystem.added(engine)
+Initializes system when added. Requests physics nodes
+
+**Kind**: instance method of [<code>PhysicsToAttributesSystem</code>](#PhysicsToAttributesSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| engine | <code>external:Serpentity.Engine</code> | the serpentity engine to which we are getting added |
+
+<a name="PhysicsToAttributesSystem+removed"></a>
+
+### physicsToAttributesSystem.removed()
+Clears system resources when removed.
+
+**Kind**: instance method of [<code>PhysicsToAttributesSystem</code>](#PhysicsToAttributesSystem)  
+<a name="PhysicsToAttributesSystem+update"></a>
+
+### physicsToAttributesSystem.update(currentFrameDuration)
+Runs on every update of the loop. Updates the other components
+based on physics
+
+**Kind**: instance method of [<code>PhysicsToAttributesSystem</code>](#PhysicsToAttributesSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| currentFrameDuration | <code>Number</code> | the duration of the current frame |
+
+<a name="PhysicsWorldControlSystem"></a>
+
+## PhysicsWorldControlSystem ⇐ <code>external:Serpentity.System</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.System</code>  
+
+* [PhysicsWorldControlSystem](#PhysicsWorldControlSystem) ⇐ <code>external:Serpentity.System</code>
+    * [new PhysicsWorldControlSystem(config)](#new_PhysicsWorldControlSystem_new)
+    * [.added(engine)](#PhysicsWorldControlSystem+added)
+    * [.removed()](#PhysicsWorldControlSystem+removed)
+    * [.update(currentFrameDuration)](#PhysicsWorldControlSystem+update)
+
+<a name="new_PhysicsWorldControlSystem_new"></a>
+
+### new PhysicsWorldControlSystem(config)
+Adds and removes objects to the physics world and calls update
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| config | <code>object</code> | a configuration object to extend. |
+
+<a name="PhysicsWorldControlSystem+added"></a>
+
+### physicsWorldControlSystem.added(engine)
+Initializes system when added. Requests physics nodes and
+attaches to event listeners to add / remove them to pixi stage
+
+**Kind**: instance method of [<code>PhysicsWorldControlSystem</code>](#PhysicsWorldControlSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| engine | <code>external:Serpentity.Engine</code> | the serpentity engine to which we are getting added |
+
+<a name="PhysicsWorldControlSystem+removed"></a>
+
+### physicsWorldControlSystem.removed()
+Clears system resources when removed.
+
+**Kind**: instance method of [<code>PhysicsWorldControlSystem</code>](#PhysicsWorldControlSystem)  
+<a name="PhysicsWorldControlSystem+update"></a>
+
+### physicsWorldControlSystem.update(currentFrameDuration)
+Runs on every update of the loop. Updates the physics
+
+**Kind**: instance method of [<code>PhysicsWorldControlSystem</code>](#PhysicsWorldControlSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| currentFrameDuration | <code>Number</code> | the duration of the current frame |
+
+<a name="RenderSystem"></a>
+
+## RenderSystem ⇐ <code>external:Serpentity.System</code>
+**Kind**: global class  
+**Extends**: <code>external:Serpentity.System</code>  
+
+* [RenderSystem](#RenderSystem) ⇐ <code>external:Serpentity.System</code>
+    * [new RenderSystem(config)](#new_RenderSystem_new)
+    * [.added(engine)](#RenderSystem+added)
+    * [.removed()](#RenderSystem+removed)
+    * [.update(currentFrameDuration)](#RenderSystem+update)
+
+<a name="new_RenderSystem_new"></a>
+
+### new RenderSystem(config)
+Renders renderable objects using pixi
+
+
+| Param | Type | Description |
+| --- | --- | --- |
+| config | <code>object</code> | a configuration object to extend. |
+
+<a name="RenderSystem+added"></a>
+
+### renderSystem.added(engine)
+Initializes system when added. Requests renderable nodes and
+attaches to event listeners to add / remove them to pixi stage
+
+**Kind**: instance method of [<code>RenderSystem</code>](#RenderSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| engine | <code>external:Serpentity.Engine</code> | the serpentity engine to which we are getting added |
+
+<a name="RenderSystem+removed"></a>
+
+### renderSystem.removed()
+Clears system resources when removed.
+
+**Kind**: instance method of [<code>RenderSystem</code>](#RenderSystem)  
+<a name="RenderSystem+update"></a>
+
+### renderSystem.update(currentFrameDuration)
+Runs on every update of the loop. Does nothing.
+
+**Kind**: instance method of [<code>RenderSystem</code>](#RenderSystem)  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| currentFrameDuration | <code>Number</code> | the duration of the current frame |
+
+<a name="PixiFactory"></a>
+
+## PixiFactory : <code>object</code>
+Factory object that contains many methods to create prefab pixi
+objects
+
+**Kind**: global variable  
+
+* [PixiFactory](#PixiFactory) : <code>object</code>
+    * [.createSumo()](#PixiFactory.createSumo) ⇒ <code>external:CreateJs.Container</code>
+    * [.createEmptyGraphic()](#PixiFactory.createEmptyGraphic) ⇒ <code>external:CreateJs.Container</code>
+
+<a name="PixiFactory.createSumo"></a>
+
+### PixiFactory.createSumo() ⇒ <code>external:CreateJs.Container</code>
+Creates a sumo container
+
+**Kind**: static method of [<code>PixiFactory</code>](#PixiFactory)  
+**Returns**: <code>external:CreateJs.Container</code> - the created container  
+<a name="PixiFactory.createEmptyGraphic"></a>
+
+### PixiFactory.createEmptyGraphic() ⇒ <code>external:CreateJs.Container</code>
+Creates an empty graphic
+
+**Kind**: static method of [<code>PixiFactory</code>](#PixiFactory)  
+**Returns**: <code>external:CreateJs.Container</code> - the created container  
+<a name="SumoFactory"></a>
+
+## SumoFactory : <code>object</code>
+Factory object that contains many methods to create prefab entities.
+
+**Kind**: global variable  
+
+* [SumoFactory](#SumoFactory) : <code>object</code>
+    * [.createSumo([engine], [config])](#SumoFactory.createSumo) ⇒ <code>external:Serpentity.Entity</code>
+    * [.createRubberBand([engine], [config])](#SumoFactory.createRubberBand) ⇒ <code>external:Serpentity.Entity</code>
+
+<a name="SumoFactory.createSumo"></a>
+
+### SumoFactory.createSumo([engine], [config]) ⇒ <code>external:Serpentity.Entity</code>
+Creates a sumo entity and adds it to the engine. Can override
+position in the config object
+
+**Kind**: static method of [<code>SumoFactory</code>](#SumoFactory)  
+**Returns**: <code>external:Serpentity.Entity</code> - the created entity  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| [engine] | <code>external:Serpentity</code> | the serpentity engine to attach to. If not sent, it will not be attached. |
+| [config] | <code>object</code> | the config to override the entity, accepts the key `position` as an object with an x and y property. |
+
+<a name="SumoFactory.createRubberBand"></a>
+
+### SumoFactory.createRubberBand([engine], [config]) ⇒ <code>external:Serpentity.Entity</code>
+Creates a rubber band entity and adds it to the engine.
+
+**Kind**: static method of [<code>SumoFactory</code>](#SumoFactory)  
+**Returns**: <code>external:Serpentity.Entity</code> - the created entity  
+
+| Param | Type | Description |
+| --- | --- | --- |
+| [engine] | <code>external:Serpentity</code> | the serpentity engine to attach to. If not sent, it will not be attached. |
+| [config] | <code>object</code> | the config to override the entity, it must include entityA and entityB which will be tied by it. If they are not sent or don't have a physics body, this will throw. |
+
diff --git a/lib/components/angle.js b/lib/components/angle.js
new file mode 100644 (file)
index 0000000..4de9764
--- /dev/null
@@ -0,0 +1,25 @@
+import { Component } from '@serpentity/serpentity';
+
+/**
+ * Component that stores an angle
+ *
+ * @extends {external:Serpentity.Component}
+ * @class AngleComponent
+ * @param {object} config a configuration object to extend.
+ */
+export default class AngleComponent extends Component {
+  constructor(config) {
+
+    super(config);
+
+    /**
+     * The properthy that holds the pixi container
+     *
+     * @property {external:MatterJs.Angle} angle
+     * @instance
+     * @memberof AngleComponent
+     */
+    this.angle = this.angle || 0;
+  }
+};
+
diff --git a/lib/components/body.js b/lib/components/body.js
new file mode 100644 (file)
index 0000000..7438dc3
--- /dev/null
@@ -0,0 +1,25 @@
+import { Component } from '@serpentity/serpentity';
+
+/**
+ * Component that stores a body for physics calculation
+ *
+ * @extends {external:Serpentity.Component}
+ * @class BodyComponent
+ * @param {object} config a configuration object to extend.
+ */
+export default class BodyComponent extends Component {
+  constructor(config) {
+
+    super(config);
+
+    /**
+     * The properthy that holds the pixi container
+     *
+     * @property {external:MatterJs.Body} body
+     * @instance
+     * @memberof BodyComponent
+     */
+    this.body = this.body || null;
+  }
+};
+
diff --git a/lib/components/coupled_entities.js b/lib/components/coupled_entities.js
new file mode 100644 (file)
index 0000000..29db813
--- /dev/null
@@ -0,0 +1,25 @@
+import { Component } from '@serpentity/serpentity';
+
+/**
+ * Component that stores a number of entities coupled to this one.
+ *
+ * @extends {external:Serpentity.Component}
+ * @class CoupledEntitiesComponent
+ * @param {object} config a configuration object to extend.
+ */
+export default class CoupledEntitiesComponent extends Component {
+  constructor(config) {
+
+    super(config);
+
+    /**
+     * An array of coupled entities
+     *
+     * @property {Array<external:Serpentity.Entity>} coupledEntities
+     * @instance
+     * @memberof CoupledEntitiesComponent
+     */
+    this.coupledEntities = this.coupledEntities || [];
+  }
+};
+
index e3c1b5acb06b587d688947137e18ffa1d38e65c7..851a07459b11e7ff6db427b956c461f86cc63d90 100644 (file)
@@ -16,9 +16,9 @@ export default {
    * @memberof PixiFactory
    * @return {external:CreateJs.Container} the created container
    */
    * @memberof PixiFactory
    * @return {external:CreateJs.Container} the created container
    */
-  createSumo() {
+  createSumo(config) {
 
 
-    const radius = 25;
+    const radius = config.radius;
 
     // The body
     const body = new Graphics();
 
     // The body
     const body = new Graphics();
@@ -61,6 +61,18 @@ export default {
     body.addChild(rightPupil);
 
     return body;
     body.addChild(rightPupil);
 
     return body;
+  },
+
+  /**
+   * Creates an empty graphic
+   *
+   * @function createEmptyGraphic
+   * @memberof PixiFactory
+   * @return {external:CreateJs.Container} the created container
+   */
+  createEmptyGraphic(config) {
+
+    return new Graphics();
   }
 };
 
   }
 };
 
index b0e5416bf545f652fb82dcc9c95d4e05ce7f6fdf..d1f31f0628bf04ddcbbbb1b3ad9322e74737a982 100644 (file)
@@ -1,9 +1,18 @@
+import { Bodies, Constraint } from 'matter-js';
 import { Entity } from '@serpentity/serpentity';
 
 import { Entity } from '@serpentity/serpentity';
 
+import AngleComponent from '../components/angle';
+import BodyComponent from '../components/body';
+import CoupledEntitiesComponent from '../components/coupled_entities';
 import PositionComponent from '@serpentity/components.position';
 import PixiContainerComponent from '../components/pixi_container';
 import PixiFactory from '../factories/pixi';
 
 import PositionComponent from '@serpentity/components.position';
 import PixiContainerComponent from '../components/pixi_container';
 import PixiFactory from '../factories/pixi';
 
+const internals = {
+  kNoEntityError: 'Entity Not Found: This method requires entityA and entityB to be set in the config.',
+  kEntityHasNoBodyError: 'Entity Has No Body: This method requires entities have a BodyComponent.'
+};
+
 /**
  * Factory object that contains many methods to create prefab entities.
  *
 /**
  * Factory object that contains many methods to create prefab entities.
  *
@@ -28,20 +37,103 @@ export default {
 
     const entity = new Entity();
 
 
     const entity = new Entity();
 
+    // POSITION
+
     entity.addComponent(new PositionComponent(config.position));
     entity.addComponent(new PositionComponent(config.position));
+    const position = entity.getComponent(PositionComponent);
+
+    entity.addComponent(new AngleComponent(config.angle));
+    const angle = entity.getComponent(AngleComponent);
+
+    // RENDERING
+
+    const radius = 25;
 
     const container = config.container || {
 
     const container = config.container || {
-      container: PixiFactory.createSumo()
+      container: PixiFactory.createSumo({ radius })
     };
     };
-
-    // Match the symbol position with the entity position on init
-    // Otherwise it's up to systems
-    const position = entity.getComponent(PositionComponent);
     container.container.position.x = position.x;
     container.container.position.y = position.y;
     container.container.position.x = position.x;
     container.container.position.y = position.y;
+    container.container.rotation = angle.angle;
+    entity.addComponent(new PixiContainerComponent(container));
+
+    // PHYSICS
+
+    const frictionAir = 0.00001;
+    const friction = 0.00001;
+    const restitution = 0.9;
+    const density = 0.5;
+
+    const body = Bodies.circle(position.x, position.y, radius, {
+      angle: angle.angle,
+      density,
+      frictionAir,
+      friction,
+      restitution
+    });
+    entity.addComponent(new BodyComponent({ body }));
+
+    if (engine) {
+      engine.addEntity(entity);
+    }
+
+    return entity;
+  },
+
+  /**
+   * Creates a rubber band entity and adds it to the engine.
+   *
+   * @function createRubberBand
+   * @memberof SumoFactory
+   * @param {external:Serpentity} [engine] the serpentity engine to attach
+   * to. If not sent, it will not be attached.
+   * @param {object} [config] the config to override the entity, it
+   * must include entityA and entityB which will be tied by it. If they
+   * are not sent or don't have a physics body, this will throw.
+   * @return {external:Serpentity.Entity} the created entity
+   */
+  createRubberBand(engine, config = {}) {
+
+    const entity = new Entity();
+
+    if (!config.entityA || !config.entityB) {
+      throw new Error(internals.kNoEntityError);
+    }
+
+    if (!config.entityA.hasComponent(BodyComponent) || !config.entityB.hasComponent(BodyComponent)) {
+      throw new Error(internals.kEntityHasNoBodyError);
+    }
 
 
+    // RENDERING
+
+    const container = config.container || {
+      container: PixiFactory.createEmptyGraphic()
+    };
     entity.addComponent(new PixiContainerComponent(container));
 
     entity.addComponent(new PixiContainerComponent(container));
 
+    // PHYSICS
+
+    const bodyA = config.entityA.getComponent(BodyComponent).body;
+    const bodyB = config.entityB.getComponent(BodyComponent).body;
+    const damping = 0.01;
+    const length = 100;
+    const stiffness = 0.0001;
+    const angularStiffness = 0.0001;
+
+    const body = Constraint.create({
+      bodyA,
+      bodyB,
+      damping,
+      length,
+      stiffness,
+      angularStiffness
+    });
+    entity.addComponent(new BodyComponent({ body }));
+
+    entity.addComponent(new CoupledEntitiesComponent({
+      coupledEntities: [config.entityA, config.entityB]
+    }));
+
     if (engine) {
       engine.addEntity(entity);
     }
     if (engine) {
       engine.addEntity(entity);
     }
diff --git a/lib/nodes/physical.js b/lib/nodes/physical.js
new file mode 100644 (file)
index 0000000..77139ec
--- /dev/null
@@ -0,0 +1,26 @@
+import { Node } from '@serpentity/serpentity';
+
+import BodyComponent from '../components/body';
+
+/**
+ * Node identifying an entity that can interact with physics
+ *
+ * @extends {external:Serpentity.Node}
+ * @class PhysicalNode
+ */
+export default class PhysicalNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify an entity with a physical
+ * body
+ *
+ * @property {object} types
+ * @name types
+ * @memberof PhysicalNode
+ */
+PhysicalNode.types = {
+  body: BodyComponent
+};
+
diff --git a/lib/nodes/physical_with_attributes.js b/lib/nodes/physical_with_attributes.js
new file mode 100644 (file)
index 0000000..96ba79d
--- /dev/null
@@ -0,0 +1,31 @@
+import { Node } from '@serpentity/serpentity';
+
+import AngleComponent from '../components/angle';
+import BodyComponent from '../components/body';
+import PositionComponent from '@serpentity/components.position';
+
+/**
+ * Node identifying an entity that can interact with physics and has
+ * components updated from its values
+ *
+ * @extends {external:Serpentity.Node}
+ * @class PhysicalWithAttributesNode
+ */
+export default class PhysicalWithAttributesNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify an entity with a physics
+ * object and external attributes
+ *
+ * @property {object} types
+ * @name types
+ * @memberof PhysicalWithAttributesNode
+ */
+PhysicalWithAttributesNode.types = {
+  angle: AngleComponent,
+  position: PositionComponent,
+  body: BodyComponent
+};
+
index 0a3a1117c4ff160535255793c8103f97be3e2479..12227a39e242d7755a179be6dba980c2729c2cf6 100644 (file)
@@ -1,11 +1,9 @@
 import { Node } from '@serpentity/serpentity';
 
 import PixiContainerComponent from '../components/pixi_container';
 import { Node } from '@serpentity/serpentity';
 
 import PixiContainerComponent from '../components/pixi_container';
-import PositionComponent from '@serpentity/components.position';
 
 /**
 
 /**
- * Node identifying a renderable entity, should have position and a
- * symbol to render
+ * Node identifying a renderable entity, should have a pixi renderable
  *
  * @extends {external:Serpentity.Node}
  * @class RenderableNode
  *
  * @extends {external:Serpentity.Node}
  * @class RenderableNode
@@ -15,13 +13,12 @@ export default class RenderableNode extends Node {
 };
 
 /**
 };
 
 /**
- * Holds the types that are used to identify a wave entity
+ * Holds the types that are used to identify a renderable entity
  *
  * @property {object} types
  * @name types
  *
  * @property {object} types
  * @name types
- * @memberof WaveNode
+ * @memberof RenderableNode
  */
 RenderableNode.types = {
  */
 RenderableNode.types = {
-  position: PositionComponent,
   container: PixiContainerComponent
 };
   container: PixiContainerComponent
 };
diff --git a/lib/nodes/renderable_couple.js b/lib/nodes/renderable_couple.js
new file mode 100644 (file)
index 0000000..39ab886
--- /dev/null
@@ -0,0 +1,28 @@
+import { Node } from '@serpentity/serpentity';
+
+import CoupledEntitiesComponent from '../components/coupled_entities';
+import PixiContainerComponent from '../components/pixi_container';
+
+/**
+ * Node identifying an entity that has coupled entities and can be
+ * rendered
+ *
+ * @extends {external:Serpentity.Node}
+ * @class RenderableCoupleNode
+ */
+export default class RenderableCoupleNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify a renderable couple
+ *
+ * @property {object} types
+ * @name types
+ * @memberof RenderableCoupleNode
+ */
+RenderableCoupleNode.types = {
+  coupledEntities: CoupledEntitiesComponent,
+  container: PixiContainerComponent
+};
+
diff --git a/lib/nodes/renderable_with_attributes.js b/lib/nodes/renderable_with_attributes.js
new file mode 100644 (file)
index 0000000..817036c
--- /dev/null
@@ -0,0 +1,30 @@
+import { Node } from '@serpentity/serpentity';
+
+import AngleComponent from '../components/angle';
+import PixiContainerComponent from '../components/pixi_container';
+import PositionComponent from '@serpentity/components.position';
+
+/**
+ * Node identifying a renderable entity, should have position and a
+ * symbol to render
+ *
+ * @extends {external:Serpentity.Node}
+ * @class RenderableWithAttributesNode
+ */
+export default class RenderableWithAttributesNode extends Node {
+
+};
+
+/**
+ * Holds the types that are used to identify a renderable with external
+ * attributes
+ *
+ * @property {object} types
+ * @name types
+ * @memberof RenderableWithAttributesNode
+ */
+RenderableWithAttributesNode.types = {
+  angle: AngleComponent,
+  position: PositionComponent,
+  container: PixiContainerComponent
+};
index 81f948f74848695144ca298d546e6a6b66714fa5..d79826f95d57bda94f42cef92acae10965761ad6 100644 (file)
@@ -1,7 +1,12 @@
+import PhysicsWorldControlSystem from './systems/physics_world_control';
+import PhysicsToAttributesSystem from './systems/physics_to_attributes';
+import CreateCouplingLineSystem from './systems/create_coupling_line';
 import RenderSystem from './systems/render';
 import RenderSystem from './systems/render';
+import AttributesToRenderableSystem from './systems/attributes_to_renderable';
 import SumoFactory from './factories/sumo';
 import Serpentity from '@serpentity/serpentity';
 import { Application } from 'pixi.js';
 import SumoFactory from './factories/sumo';
 import Serpentity from '@serpentity/serpentity';
 import { Application } from 'pixi.js';
+import { Engine } from 'matter-js';
 
 /* global window document */
 
 
 /* global window document */
 
@@ -60,6 +65,7 @@ internals.Sumo = class Sumo {
 
     // Initialization functions
     this._initializeCanvas();
 
     // Initialization functions
     this._initializeCanvas();
+    this._initializeMatter();
     this._initializePixi();
     this._initializeSystems();
     this._initializeEntities();
     this._initializePixi();
     this._initializeSystems();
     this._initializeEntities();
@@ -124,6 +130,15 @@ internals.Sumo = class Sumo {
     window.addEventListener('resize', this._resizeCanvas.bind(this));
   }
 
     window.addEventListener('resize', this._resizeCanvas.bind(this));
   }
 
+  // Initialize MatterJs
+
+  _initializeMatter() {
+
+    this._matterJs = Engine.create();
+
+    this._matterJs.world.gravity.y = 0;
+  }
+
   // Initialize Pixi
 
   _initializePixi() {
   // Initialize Pixi
 
   _initializePixi() {
@@ -160,6 +175,16 @@ internals.Sumo = class Sumo {
 
   _initializeSystems() {
 
 
   _initializeSystems() {
 
+    this._engine.addSystem(new PhysicsWorldControlSystem({
+      engine: this._matterJs
+    }));
+
+    this._engine.addSystem(new PhysicsToAttributesSystem());
+
+    this._engine.addSystem(new AttributesToRenderableSystem());
+
+    this._engine.addSystem(new CreateCouplingLineSystem());
+
     this._engine.addSystem(new RenderSystem({
       application: this._pixi
     }));
     this._engine.addSystem(new RenderSystem({
       application: this._pixi
     }));
@@ -169,19 +194,42 @@ internals.Sumo = class Sumo {
 
   _initializeEntities() {
 
 
   _initializeEntities() {
 
-    SumoFactory.createSumo(this._engine, {
+    const entityA = SumoFactory.createSumo(null, {
       position: {
         x: 50,
         y: 50
       }
     });
 
       position: {
         x: 50,
         y: 50
       }
     });
 
-    SumoFactory.createSumo(this._engine, {
+    const entityB = SumoFactory.createSumo(null, {
       position: {
         x: 309,
         y: 112
       }
     });
       position: {
         x: 309,
         y: 112
       }
     });
+
+    const entityC = SumoFactory.createSumo(null, {
+      position: {
+        x: 500,
+        y: 78
+      }
+    });
+
+    SumoFactory.createRubberBand(this._engine, {
+      entityA,
+      entityB
+    });
+
+    SumoFactory.createRubberBand(this._engine, {
+      entityA: entityC,
+      entityB
+    });
+
+    // To keep the coupling behind, we'll manually add the sumos later
+
+    this._engine.addEntity(entityA);
+    this._engine.addEntity(entityB);
+    this._engine.addEntity(entityC);
   }
 };
 
   }
 };
 
diff --git a/lib/systems/attributes_to_renderable.js b/lib/systems/attributes_to_renderable.js
new file mode 100644 (file)
index 0000000..e5c66a0
--- /dev/null
@@ -0,0 +1,73 @@
+import { System } from '@serpentity/serpentity';
+
+import RenderableWithAttributesNode from '../nodes/renderable_with_attributes';
+
+/**
+ * Updates the renderables based on their attribuets
+ *
+ * @extends {external:Serpentity.System}
+ * @class AttributesToRenderableSystem
+ * @param {object} config a configuration object to extend.
+ */
+export default class AttributesToRenderableSystem extends System {
+
+  constructor(config = {}) {
+
+    super();
+
+    /**
+     * The node collection of renderable entities
+     *
+     * @property {external:Serpentity.NodeCollection} renderables
+     * @instance
+     * @memberof AttributesToRenderableSystem
+     */
+    this.renderables = null;
+  }
+
+  /**
+   * Initializes system when added. Requests renderable nodes and
+   * attaches to event listeners to add / remove them to pixi stage
+   *
+   * @function added
+   * @memberof AttributesToRenderableSystem
+   * @instance
+   * @param {external:Serpentity.Engine} engine the serpentity engine to
+   * which we are getting added
+   */
+  added(engine) {
+
+    this.renderables = engine.getNodes(RenderableWithAttributesNode);
+  }
+
+  /**
+   * Clears system resources when removed.
+   *
+   * @function removed
+   * @instance
+   * @memberof AttributesToRenderableSystem
+   */
+  removed() {
+
+    this.renderables = null;
+  }
+
+  /**
+   * Runs on every update of the loop. Updates the graphics so they're
+   * rendered correctly
+   *
+   * @function update
+   * @instance
+   * @param {Number} currentFrameDuration the duration of the current
+   * frame
+   * @memberof AttributesToRenderableSystem
+   */
+  update(currentFrameDuration) {
+
+    for (const renderable of this.renderables) {
+      renderable.container.container.position.x = renderable.position.x;
+      renderable.container.container.position.y = renderable.position.y;
+      renderable.container.container.rotation = renderable.angle.angle;
+    }
+  }
+};
diff --git a/lib/systems/create_coupling_line.js b/lib/systems/create_coupling_line.js
new file mode 100644 (file)
index 0000000..8e5e9d7
--- /dev/null
@@ -0,0 +1,96 @@
+import { System } from '@serpentity/serpentity';
+import { Graphics } from 'pixi.js';
+
+import PositionComponent from '@serpentity/components.position';
+
+import RenderableCoupleNode from '../nodes/renderable_couple';
+
+/**
+ * Renders renderable objects using pixi
+ *
+ * @extends {external:Serpentity.System}
+ * @class CreateCouplingLineSystem
+ * @param {object} config a configuration object to extend.
+ */
+export default class CreateCouplingLineSystem extends System {
+
+  constructor(config = {}) {
+
+    super();
+
+    /**
+     * The node collection of coupled entities entities
+     *
+     * @property {external:Serpentity.NodeCollection} coupledEntities
+     * @instance
+     * @memberof CreateCouplingLineSystem
+     */
+    this.coupledEntities = null;
+  }
+
+  /**
+   * Initializes system when added. Requests renderable nodes and
+   *
+   * @function added
+   * @memberof CreateCouplingLineSystem
+   * @instance
+   * @param {external:Serpentity.Engine} engine the serpentity engine to
+   * which we are getting added
+   */
+  added(engine) {
+
+    this.coupledEntities = engine.getNodes(RenderableCoupleNode);
+  }
+
+  /**
+   * Clears system resources when removed.
+   *
+   * @function removed
+   * @instance
+   * @memberof CreateCouplingLineSystem
+   */
+  removed() {
+
+    this.coupledEntities = null;
+  }
+
+  /**
+   * Runs on every update of the loop. Does nothing.
+   *
+   * @function update
+   * @instance
+   * @param {Number} currentFrameDuration the duration of the current
+   * frame
+   * @memberof CreateCouplingLineSystem
+   */
+  update(currentFrameDuration) {
+
+    for (const rootEntity of this.coupledEntities) {
+
+      const rootGraphic = rootEntity.container.container;
+      rootGraphic.removeChildren();
+
+      let lineGraphic = new Graphics();
+      lineGraphic = lineGraphic.lineStyle(5, 0xffffff, 0.9);
+
+      let initialPosition = false;
+
+      for (const coupledEntity of rootEntity.coupledEntities.coupledEntities) {
+        if (coupledEntity.hasComponent(PositionComponent)) {
+
+          const position = coupledEntity.getComponent(PositionComponent);
+
+          if (!initialPosition) {
+            lineGraphic = lineGraphic.moveTo(position.x, position.y);
+            initialPosition = true;
+            continue;
+          }
+          lineGraphic = lineGraphic.lineTo(position.x, position.y);
+        }
+      }
+
+      rootGraphic.addChild(lineGraphic);
+    }
+  }
+};
+
diff --git a/lib/systems/physics_to_attributes.js b/lib/systems/physics_to_attributes.js
new file mode 100644 (file)
index 0000000..a49a16b
--- /dev/null
@@ -0,0 +1,72 @@
+import { System } from '@serpentity/serpentity';
+
+import PhysicalWithAttributesNode from '../nodes/physical_with_attributes';
+
+/**
+ * Distribuets physics data to the related components
+ *
+ * @extends {external:Serpentity.System}
+ * @class PhysicsToAttributesSystem
+ * @param {object} config a configuration object to extend.
+ */
+export default class PhysicsToAttributesSystem extends System {
+
+  constructor(config = {}) {
+
+    super();
+
+    /**
+     * The node collection of physics entities
+     *
+     * @property {external:Serpentity.NodeCollection} physicalEntities
+     * @instance
+     * @memberof PhysicsToAttributesSystem
+     */
+    this.physicalEntities = null;
+  }
+
+  /**
+   * Initializes system when added. Requests physics nodes
+   *
+   * @function added
+   * @memberof PhysicsToAttributesSystem
+   * @instance
+   * @param {external:Serpentity.Engine} engine the serpentity engine to
+   * which we are getting added
+   */
+  added(engine) {
+
+    this.physicalEntities = engine.getNodes(PhysicalWithAttributesNode);
+  }
+
+  /**
+   * Clears system resources when removed.
+   *
+   * @function removed
+   * @instance
+   * @memberof PhysicsToAttributesSystem
+   */
+  removed() {
+
+    this.physicalEntities = null;
+  }
+
+  /**
+   * Runs on every update of the loop. Updates the other components
+   * based on physics
+   *
+   * @function update
+   * @instance
+   * @param {Number} currentFrameDuration the duration of the current
+   * frame
+   * @memberof PhysicsToAttributesSystem
+   */
+  update(currentFrameDuration) {
+
+    for (const physicalEntity of this.physicalEntities) {
+      physicalEntity.position.x = physicalEntity.body.body.position.x;
+      physicalEntity.position.y = physicalEntity.body.body.position.y;
+      physicalEntity.angle.angle = physicalEntity.body.body.angle;
+    }
+  }
+};
diff --git a/lib/systems/physics_world_control.js b/lib/systems/physics_world_control.js
new file mode 100644 (file)
index 0000000..daa39c1
--- /dev/null
@@ -0,0 +1,98 @@
+import { System } from '@serpentity/serpentity';
+import { Engine, World } from 'matter-js';
+
+import PhysicalNode from '../nodes/physical';
+
+const internals = {
+  kNoEngine: 'No matter js physics engine found. Make sure you set the `engine` key in the config object when initializing.'
+};
+
+/**
+ * Adds and removes objects to the physics world and calls update
+ *
+ * @extends {external:Serpentity.System}
+ * @class PhysicsWorldControlSystem
+ * @param {object} config a configuration object to extend.
+ */
+export default class PhysicsWorldControlSystem extends System {
+
+  constructor(config = {}) {
+
+    super();
+
+    /**
+     * The node collection of physics entities
+     *
+     * @property {external:Serpentity.NodeCollection} physicalEntities
+     * @instance
+     * @memberof PhysicsWorldControlSystem
+     */
+    this.physicalEntities = null;
+
+    /**
+     * The matter-js engine we will use to process physics
+     *
+     * @property {external:MatterJs.Engine} engine
+     * @instance
+     * @memberof PhysicsWorldControlSystem
+     */
+    this.engine = config.engine;
+
+    if (!this.engine) {
+      throw new Error(internals.kNoEngine);
+    }
+  }
+
+  /**
+   * Initializes system when added. Requests physics nodes and
+   * attaches to event listeners to add / remove them to pixi stage
+   *
+   * @function added
+   * @memberof PhysicsWorldControlSystem
+   * @instance
+   * @param {external:Serpentity.Engine} engine the serpentity engine to
+   * which we are getting added
+   */
+  added(engine) {
+
+    this.physicalEntities = engine.getNodes(PhysicalNode);
+    this.physicalEntities.on('nodeAdded', (event) => {
+
+      World.add(this.engine.world, [event.node.body.body]);
+    });
+    this.physicalEntities.on('nodeRemoved', (event) => {
+
+      World.remove(this.engine.world, [event.node.body.body]);
+    });
+  }
+
+  /**
+   * Clears system resources when removed.
+   *
+   * @function removed
+   * @instance
+   * @memberof PhysicsWorldControlSystem
+   */
+  removed() {
+
+    this.physicalEntities.removeAllListeners('nodeAdded');
+    this.physicalEntities.removeAllListeners('nodeRemoved');
+    this.physicalEntities = null;
+  }
+
+  /**
+   * Runs on every update of the loop. Updates the physics
+   *
+   * @function update
+   * @instance
+   * @param {Number} currentFrameDuration the duration of the current
+   * frame
+   * @memberof PhysicsWorldControlSystem
+   */
+  update(currentFrameDuration) {
+
+    Engine.run(this.engine);
+  }
+};
+
+
index 8d3d4468ed8b3c4104ae89ccbab13a114ef8a83d..a2e30203639355569251ded345adda2b9a83c1e0 100644 (file)
@@ -7,7 +7,7 @@ const internals = {
 };
 
 /**
 };
 
 /**
- * Renders renderable objects to console
+ * Renders renderable objects using pixi
  *
  * @extends {external:Serpentity.System}
  * @class RenderSystem
  *
  * @extends {external:Serpentity.System}
  * @class RenderSystem
@@ -80,8 +80,7 @@ export default class RenderSystem extends System {
   }
 
   /**
   }
 
   /**
-   * Runs on every update of the loop. Prints the location of every
-   * renderable
+   * Runs on every update of the loop. Does nothing.
    *
    * @function update
    * @instance
    *
    * @function update
    * @instance
@@ -89,11 +88,5 @@ export default class RenderSystem extends System {
    * frame
    * @memberof RenderSystem
    */
    * frame
    * @memberof RenderSystem
    */
-  update(currentFrameDuration) {
-
-    for (const renderable of this.renderables) {
-      renderable.container.container.position.x = renderable.position.x;
-      renderable.container.container.position.y = renderable.position.y;
-    }
-  }
+  update(currentFrameDuration) {}
 };
 };
index 43c41d36c429c5fd0b28bb8f454258ece88bafc5..17d34da920aec748553b2d7e00f72a8141eb5ab5 100644 (file)
       "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
       "dev": true
     },
       "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==",
       "dev": true
     },
+    "matter-js": {
+      "version": "0.14.1",
+      "resolved": "https://registry.npmjs.org/matter-js/-/matter-js-0.14.1.tgz",
+      "integrity": "sha512-qbPBf5NpjPfNlxiRXpoJHAnMMF4WNP22mRhkas0hsUnVTztFBt3QpxRChEws4j1YuaH2bCXEd2i4qmRwADqyuA=="
+    },
     "md5.js": {
       "version": "1.3.4",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
     "md5.js": {
       "version": "1.3.4",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
index 50f2a47bd91c7d997826893b5ee4a3f0dca2fc8e..21ab9f3dc6377f91d1eba68d011be1c8bb1fc329 100644 (file)
@@ -24,6 +24,7 @@
     "@serpentity/components.debug": "^2.0.0",
     "@serpentity/components.position": "^2.0.0",
     "@serpentity/serpentity": "^2.1.0",
     "@serpentity/components.debug": "^2.0.0",
     "@serpentity/components.position": "^2.0.0",
     "@serpentity/serpentity": "^2.1.0",
+    "matter-js": "^0.14.1",
     "pixi.js": "^4.7.3"
   },
   "browserslist": "last two versions",
     "pixi.js": "^4.7.3"
   },
   "browserslist": "last two versions",