feat: Animated trait
This commit is contained in:
parent
068c45842d
commit
b9cbccede8
96
packages/entity/traits/animated.js
Normal file
96
packages/entity/traits/animated.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
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) {
|
||||
super(entity);
|
||||
this.sprite = undefined;
|
||||
}
|
||||
|
||||
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],
|
||||
];
|
||||
}
|
||||
|
||||
fromJSON(json) {
|
||||
super.fromJSON(json);
|
||||
this.frameCount = json.params.frameCount;
|
||||
this.frameRate = json.params.frameRate;
|
||||
this.frameSize = json.params.frameSize;
|
||||
this.image = json.params.image;
|
||||
this.frameCaret = this.frameRate;
|
||||
return this;
|
||||
}
|
||||
|
||||
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) {}
|
|
@ -16,6 +16,9 @@ export function lookupTrait(type) {
|
|||
}
|
||||
|
||||
// Register core traits.
|
||||
import {Animated} from './animated';
|
||||
registerTrait(Animated);
|
||||
|
||||
import {Directional} from './directional';
|
||||
registerTrait(Directional);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user