/// class SpriteAnimator extends SpriteRenderer { /** 在动画完成时触发,包括动画名称; */ public onAnimationCompletedEvent: Function; /** 动画播放速度 */ public speed = 1; /** 动画的当前状态 */ public animationState = State.none; /** 当前动画 */ public currentAnimation: SpriteAnimation; /** 当前动画的名称 */ public currentAnimationName: string; /** 当前动画的精灵数组中当前帧的索引 */ public currentFrame: number; /** 检查当前动画是否正在运行 */ public get isRunning(): boolean{ return this.animationState == State.running; } private _animations: Map = new Map(); private _elapsedTime: number = 0; private _loopMode: LoopMode; constructor(sprite?: Sprite){ super(); if (sprite) this.setSprite(sprite); } /** * 添加一个SpriteAnimation * @param name * @param animation */ public addAnimation(name: string, animation: SpriteAnimation): SpriteAnimator{ if (!this.sprite && animation.sprites.length > 0) this.setSprite(animation.sprites[0]); this._animations[name] = animation; return this; } /** * 以给定的名称放置动画。如果没有指定循环模式,则默认为循环 * @param name * @param loopMode */ public play(name: string, loopMode: LoopMode = null){ this.currentAnimation = this._animations[name]; this.currentAnimationName = name; this.currentFrame = 0; this.animationState = State.running; this.sprite = this.currentAnimation.sprites[0]; this._elapsedTime = 0; this._loopMode = loopMode ? loopMode : LoopMode.loop; } /** * 检查动画是否正在播放(即动画是活动的)。它可能仍然处于暂停状态) * @param name */ public isAnimationActive(name: string): boolean{ return this.currentAnimation && this.currentAnimationName == name; } /** * 暂停动画 */ public pause(){ this.animationState = State.paused; } /** * 继续动画 */ public unPause(){ this.animationState = State.running; } /** * 停止当前动画并将其设为null */ public stop(){ this.currentAnimation = null; this.currentAnimationName = null; this.currentFrame = 0; this.animationState = State.none; } public update(){ if (this.animationState != State.running || !this.currentAnimation) return; let animation = this.currentAnimation; let secondsPerFrame = 1 / (animation.frameRate * this.speed); let iterationDuration = secondsPerFrame * animation.sprites.length; this._elapsedTime += Time.deltaTime; let time = Math.abs(this._elapsedTime); if (this._loopMode == LoopMode.once && time > iterationDuration || this._loopMode == LoopMode.pingPongOnce && time > iterationDuration * 2){ this.animationState = State.completed; this._elapsedTime = 0; this.currentFrame = 0; this.sprite = animation.sprites[this.currentFrame]; return; } // 弄清楚我们在哪个坐标系上 let i = Math.floor(time / secondsPerFrame); let n = animation.sprites.length; if (n > 2 && (this._loopMode == LoopMode.pingPong || this._loopMode == LoopMode.pingPongOnce)){ // pingpong let maxIndex = n - 1; this.currentFrame = maxIndex - Math.abs(maxIndex - i % (maxIndex * 2)); }else{ this.currentFrame = i % n; } this.sprite = animation.sprites[this.currentFrame]; } } enum LoopMode { /** 在一个循环序列[A][B][C][A][B][C][A][B][C]... */ loop, /** [A][B][C]然后暂停,设置时间为0 [A] */ once, /** [A][B][C]。当它到达终点时,它会继续播放最后一帧,并且不会停止播放 */ clampForever, /** 以一个乒乓循环的方式永远播放这个序列 [A][B][C][B][A][B][C][B]... */ pingPong, /** 将顺序向前播放一次,然后返回到开始[A][B][C][B][A],然后暂停并设置时间为0 */ pingPongOnce, } enum State { none, running, paused, completed, }