import {compose} from '@avocado/core'; import {Color, Container, Primitives} from '@avocado/graphics'; import {Rectangle, Vector} from '@avocado/math'; import {BodyView, shapeFromJSON, ShapeView} from '@avocado/physics'; import {StateProperty, Trait} from '../trait'; const decorate = compose( ); export class Physical extends decorate(Trait) { static defaultParams() { return { shape: undefined, }; } initialize() { this._body = undefined; this.bodyView = undefined; this._shape = shapeFromJSON(this.params.get('shape').toJS()); this.shapeView = undefined; this._world = undefined; } destroy() { if (this._world) { this._world.removeBody(this._body); } if (this.bodyView) { this.bodyView.destroy(); } if (this.shapeView) { this.shapeView.destroy(); } } get body() { return this._body; } get shape() { return this._shape; } set world(world) { if (this._world) { this._world.removeBody(this._body); } if (this.bodyView) { this.bodyView.destroy(); } this._world = world; if (world) { const body = world.createBody(this.entity.shape); world.associateBodyWithEntity(body, this.entity); world.addBody(body); this._body = body; if (this.entity.container) { this.bodyView = new BodyView(body); this.bodyView.position = Vector.scale(this.entity.position, -1); this.bodyView.zIndex = 101; this.entity.container.addChild(this.bodyView); } } } listeners() { return { addedToRoom: () => { this.entity.world = this.entity.room.world; }, positionChanged: () => { if (this._body) { const position = this.entity.position; this._body.position = position; } }, traitAdded: (type) => { if (this.entity.container) { if (!this.shapeView) { this.shapeView = new ShapeView(this.entity.shape); this.shapeView.zIndex = 100; this.entity.container.addChild(this.shapeView); } } } }; } methods() { return { applyForce: (force) => { if (this._world) { this._body.applyForce(force); } }, applyImpulse: (impulse, elapsed) => { if (this._world) { this._body.applyImpulse(impulse, elapsed); } }, } } }