import {compose} from '@avocado/core'; import {Image, Sprite} from '@avocado/graphics'; import {Vector} from '@avocado/math'; import {simpleState, Trait} from '../trait'; const decorate = compose( simpleState('currentFrame', { track: true, }), ); class AnimatedBase extends Trait { static defaultParams() { return { frameCount: 0, frameRate: 0, frameSize: [0, 0], image: '', }; } static defaultState() { return { currentFrame: 0, }; } constructor(entity, params, state) { super(entity, params, state); this.sprite = undefined; this.frameCount = this.params.get('frameCount'); this.frameRate = this.params.get('frameRate'); this.frameSize = this.params.get('frameSize'); this.image = this.params.get('image'); this.frameCaret = this.frameRate; } get frameRect() { const direction = ('direction' in this.entity) ? this.entity.direction : 0; return [ this.entity.currentFrame * this.frameSize[0], direction * this.frameSize[1], this.frameSize[0], this.frameSize[1], ]; } listeners() { return { currentFrameChanged: () => { if (this.sprite) { this.sprite.sourceRectangle = this.frameRect; } }, directionChanged: () => { if (this.sprite) { this.sprite.sourceRectangle = this.frameRect; } }, tick: (elapsed) => { this.frameCaret -= elapsed; if (this.frameCaret > 0) { return; } const newFrame = (this.entity.currentFrame + 1) % this.frameCount; this.entity.currentFrame = newFrame; if (this.frameCaret < 0) { this.frameCaret = this.frameRate - this.frameCaret; } }, traitAdded: (trait) => { if ('graphical' !== trait.constructor.type()) { return; } if (!this.entity.container.isValid) { return; } Image.load(this.image).then((image) => { this.sprite = new Sprite(image); this.sprite.sourceRectangle = this.frameRect; this.entity.container.addChild(this.sprite); }); }, }; } } export class Animated extends decorate(AnimatedBase) {}