]>
git.r.bdr.sh - rbdr/sumo/blob - lib/systems/grab.js
1 import { System
} from '@serpentity/serpentity';
2 import { Body
, Constraint
, SAT
, World
} from 'matter-js';
4 import GrabberNode
from '../nodes/grabber';
5 import GrabbableNode
from '../nodes/grabbable';
7 import Config
from '../config';
11 kNoEngine: 'No matter js physics engine found. Make sure you set the `engine` key in the config object when initializing.'
15 * Handles grabbing between entities
17 * @extends {external:Serpentity.System}
19 * @param {object} config a configuration object to extend.
21 export default class GrabSystem
extends System
{
23 constructor(config
= {}) {
28 * The node collection of grabbers
30 * @property {external:Serpentity.NodeCollection} grabbers
32 * @memberof GrabSystem
37 * The node collection of grabbables
39 * @property {external:Serpentity.NodeCollection} grabbables
41 * @memberof GrabSystem
43 this.grabbables
= null;
46 * The matter-js engine we will use to add and remove constraints
48 * @property {external:MatterJs.Engine} engine
50 * @memberof GrabSystem
52 this.engine
= config
.engine
;
55 throw new Error(internals
.kNoEngine
);
60 * Initializes system when added. Requests grabber and grabbable nodes
63 * @memberof GrabSystem
65 * @param {external:Serpentity.Engine} engine the serpentity engine to
66 * which we are getting added
70 this.grabbers
= engine
.getNodes(GrabberNode
);
71 this.grabbables
= engine
.getNodes(GrabbableNode
);
75 * Clears system resources when removed.
79 * @memberof GrabSystem
84 this.grabbables
= null;
88 * Runs on every update of the loop. Triggers grab and manages cooldown
92 * @param {Number} currentFrameDuration the duration of the current
94 * @memberof GrabSystem
96 update(currentFrameDuration
) {
98 for (const grabber
of this.grabbers
) {
100 const grab
= grabber
.grab
;
102 if (grab
.grabbing
&& !grab
.locked
) {
106 const isGrabReleased
= !grab
.grabbing
|| grab
.currentCooldown
>= grab
.cooldown
;
107 if (grab
.constraint
&& isGrabReleased
) {
108 this._release(grabber
);
111 if (!grab
.grabbing
&& grab
.locked
&& grab
.currentCooldown
>= grab
.cooldown
) {
112 this._unlock(grabber
);
116 grab
.currentCooldown
+= currentFrameDuration
;
123 // Executes the dash action
127 const grab
= grabber
.grab
;
130 grab
.currentCooldown
= 0;
132 Body
.setPosition(grabber
.grabArea
.area
, grabber
.body
.body
.position
);
134 for (const grabbable
of this.grabbables
) {
136 if (grabbable
.entity
=== grabber
.entity
) {
140 const collision
= SAT
.collides(grabber
.grabArea
.area
, grabbable
.body
.body
);
141 if (collision
.collided
) {
142 grab
.constraint
= this._createConstraint(grabber
.body
.body
, grabbable
.body
.body
);
147 // Executes the unlock action
151 grabber
.grab
.locked
= false;
154 // Releases a constraint
158 World
.remove(this.engine
.world
, grabber
.grab
.constraint
);
159 grabber
.grab
.currentCooldown
= 0;
160 grabber
.grab
.constraint
= null;
163 // Performs a grab between two entities
165 _createConstraint(grabber
, grabbable
) {
167 const constraint
= Constraint
.create({ // Attach the sensor to the body
171 length: internals
.kGrabRadius
/ Config
.meterSize
,
175 World
.add(this.engine
.world
, [constraint
]);