import {compose, TickingPromise} from '@avocado/core'; import {Vector} from '@avocado/math'; import {StateProperty, Trait} from '../trait'; const decorate = compose( StateProperty('isMobile'), StateProperty('speed'), ) export class Mobile extends decorate(Trait) { static defaultState() { return { isMobile: true, speed: 0, }; } static type() { return 'mobile'; } constructor(entity, params, state) { super(entity, params, state); this.appliedMovement = [0, 0]; } methods() { return { moveFor: (duration) => { const direction = this.entity.direction; let resolve; const promise = new TickingPromise(_resolve => resolve = _resolve); promise.ticker = (elapsed) => { duration -= elapsed; if (duration <= 0) { return resolve(); } this.entity.requestMovement(Vector.fromDirection(direction)); } return promise; }, applyMovement: (vector) => { this.appliedMovement = Vector.add(this.appliedMovement, vector); }, forceMovement: (movement) => { this.entity.x += movement[0]; this.entity.y += movement[1]; }, requestMovement: (vector) => { if (!this.isMobile) { return; } this.entity.applyMovement(Vector.scale( Vector.normalize(vector), this.speed )); this.entity.emit('movementRequest', this.appliedMovement); }, } } tick(elapsed) { if (Vector.isZero(this.appliedMovement)) { return; } if (this.entity.is('physical')) { this.entity.applyImpulse(this.appliedMovement); } else { const appliedMovement = Vector.scale( this.appliedMovement, elapsed ); this.entity.forceMovement(appliedMovement); } this.appliedMovement = [0, 0]; } }