phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
1,688 lines (1,249 loc) • 65.7 kB
JavaScript
var AnimationState = require('../../src/animations/AnimationState');
var CustomMap = require('../../src/structs/Map');
// ---------------------------------------------------------------------------
// Mock helpers
// ---------------------------------------------------------------------------
function createMockAnimationFrame (textureFrame, progress)
{
return {
textureFrame: textureFrame || 'frame0',
progress: progress !== undefined ? progress : 0,
setAlpha: false,
alpha: 1,
frame: {
texture: {},
customPivot: false,
pivotX: 0,
pivotY: 0,
updateCropUVs: function () {}
}
};
}
function createMockAnimation (key, frameCount)
{
var frames = [];
for (var i = 0; i < (frameCount || 3); i++)
{
frames.push(createMockAnimationFrame('frame' + i, i / Math.max(1, (frameCount || 3) - 1)));
}
return {
key: key || 'testAnim',
frameRate: 24,
duration: 1000,
delay: 0,
repeat: 0,
repeatDelay: 0,
yoyo: false,
showBeforeDelay: false,
showOnStart: false,
hideOnComplete: false,
skipMissedFrames: true,
randomFrame: false,
paused: false,
frames: frames,
getTotalFrames: function () { return this.frames.length; },
calculateDuration: function () {},
getFirstTick: function () {},
getLastFrame: function () { return this.frames[this.frames.length - 1]; },
getFrameByProgress: function () { return this.frames[0]; },
nextFrame: function () {},
previousFrame: function () {}
};
}
function createMockAnimationManager ()
{
return {
textureManager: {},
globalTimeScale: 1,
on: function () {},
off: function () {},
get: function () { return null; },
getMix: function () { return 0; },
generateFrameNames: function () { return []; },
generateFrameNumbers: function () { return []; },
createFromAseprite: function () { return []; }
};
}
function createMockParent (animManager)
{
return {
scene: {
sys: {
anims: animManager
}
},
texture: null,
frame: null,
isCropped: false,
_originComponent: false,
flipX: false,
flipY: false,
alpha: 1,
visible: true,
setVisible: function (v) { this.visible = v; },
setSizeToFrame: function () {},
updateDisplayOrigin: function () {},
setOrigin: function () {},
emit: function () {}
};
}
function createAnimationState ()
{
var manager = createMockAnimationManager();
var parent = createMockParent(manager);
var state = new AnimationState(parent);
return state;
}
// Attach a mock animation directly onto an AnimationState (bypasses load)
function attachMockAnimation (state, anim)
{
state.currentAnim = anim;
state.currentFrame = anim.frames[0];
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
describe('AnimationState', function ()
{
describe('constructor', function ()
{
it('should set default values', function ()
{
var state = createAnimationState();
expect(state.isPlaying).toBe(false);
expect(state.hasStarted).toBe(false);
expect(state.currentAnim).toBeNull();
expect(state.currentFrame).toBeNull();
expect(state.nextAnim).toBeNull();
expect(state.nextAnimsQueue).toEqual([]);
expect(state.timeScale).toBe(1);
expect(state.frameRate).toBe(0);
expect(state.duration).toBe(0);
expect(state.msPerFrame).toBe(0);
expect(state.skipMissedFrames).toBe(true);
expect(state.randomFrame).toBe(false);
expect(state.delay).toBe(0);
expect(state.repeat).toBe(0);
expect(state.repeatDelay).toBe(0);
expect(state.yoyo).toBe(false);
expect(state.showBeforeDelay).toBe(false);
expect(state.showOnStart).toBe(false);
expect(state.hideOnComplete).toBe(false);
expect(state.forward).toBe(true);
expect(state.inReverse).toBe(false);
expect(state.accumulator).toBe(0);
expect(state.nextTick).toBe(0);
expect(state.delayCounter).toBe(0);
expect(state.repeatCounter).toBe(0);
expect(state.pendingRepeat).toBe(false);
expect(state.anims).toBeNull();
});
it('should store the parent reference', function ()
{
var manager = createMockAnimationManager();
var parent = createMockParent(manager);
var state = new AnimationState(parent);
expect(state.parent).toBe(parent);
});
it('should store the animationManager reference', function ()
{
var manager = createMockAnimationManager();
var parent = createMockParent(manager);
var state = new AnimationState(parent);
expect(state.animationManager).toBe(manager);
});
it('should register globalRemove listener on the animation manager', function ()
{
var manager = createMockAnimationManager();
var calledWith = null;
manager.on = function (event, cb, ctx)
{
calledWith = { event: event, cb: cb, ctx: ctx };
};
var parent = createMockParent(manager);
var state = new AnimationState(parent);
expect(calledWith).not.toBeNull();
expect(calledWith.cb).toBe(state.globalRemove);
expect(calledWith.ctx).toBe(state);
});
});
// -----------------------------------------------------------------------
describe('chain', function ()
{
it('should set nextAnim when no animation is queued', function ()
{
var state = createAnimationState();
state.chain('walk');
expect(state.nextAnim).toBe('walk');
expect(state.nextAnimsQueue.length).toBe(0);
});
it('should push additional animations into the queue', function ()
{
var state = createAnimationState();
state.chain('walk');
state.chain('run');
state.chain('idle');
expect(state.nextAnim).toBe('walk');
expect(state.nextAnimsQueue).toEqual([ 'run', 'idle' ]);
});
it('should accept an array of keys', function ()
{
var state = createAnimationState();
state.chain([ 'walk', 'run', 'idle' ]);
expect(state.nextAnim).toBe('walk');
expect(state.nextAnimsQueue).toEqual([ 'run', 'idle' ]);
});
it('should clear nextAnim and the queue when called with no arguments', function ()
{
var state = createAnimationState();
state.chain('walk');
state.chain('run');
state.chain();
expect(state.nextAnim).toBeNull();
expect(state.nextAnimsQueue.length).toBe(0);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.chain('walk');
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('getName', function ()
{
it('should return an empty string when no animation is loaded', function ()
{
var state = createAnimationState();
expect(state.getName()).toBe('');
});
it('should return the key of the current animation', function ()
{
var state = createAnimationState();
state.currentAnim = { key: 'run' };
expect(state.getName()).toBe('run');
});
});
// -----------------------------------------------------------------------
describe('getFrameName', function ()
{
it('should return an empty string when no frame is loaded', function ()
{
var state = createAnimationState();
expect(state.getFrameName()).toBe('');
});
it('should return the textureFrame of the current frame', function ()
{
var state = createAnimationState();
state.currentFrame = { textureFrame: 'sprite_0001' };
expect(state.getFrameName()).toBe('sprite_0001');
});
});
// -----------------------------------------------------------------------
describe('pause', function ()
{
it('should set _paused to true', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.pause();
expect(state._paused).toBe(true);
});
it('should store the previous isPlaying state in _wasPlaying', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.pause();
expect(state._wasPlaying).toBe(true);
});
it('should set isPlaying to false', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.pause();
expect(state.isPlaying).toBe(false);
});
it('should not change _wasPlaying if already paused', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.pause(); // _wasPlaying = true
state.isPlaying = false;
state.pause(); // should NOT overwrite _wasPlaying
expect(state._wasPlaying).toBe(true);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.pause();
expect(result).toBe(state.parent);
});
it('should call setCurrentFrame with the provided frame', function ()
{
var state = createAnimationState();
var frame = createMockAnimationFrame('f0');
var called = false;
state.setCurrentFrame = function (f)
{
called = true;
expect(f).toBe(frame);
return state.parent;
};
state.pause(frame);
expect(called).toBe(true);
});
});
// -----------------------------------------------------------------------
describe('resume', function ()
{
it('should clear _paused and restore isPlaying from _wasPlaying', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.pause();
expect(state._paused).toBe(true);
expect(state.isPlaying).toBe(false);
state.resume();
expect(state._paused).toBe(false);
expect(state.isPlaying).toBe(true);
});
it('should not change isPlaying if not paused', function ()
{
var state = createAnimationState();
state.isPlaying = false;
state._paused = false;
state.resume();
expect(state.isPlaying).toBe(false);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.resume();
expect(result).toBe(state.parent);
});
it('should call setCurrentFrame with the provided frame', function ()
{
var state = createAnimationState();
var frame = createMockAnimationFrame('f0');
var called = false;
state._paused = true;
state.setCurrentFrame = function (f)
{
called = true;
expect(f).toBe(frame);
return state.parent;
};
state.resume(frame);
expect(called).toBe(true);
});
});
// -----------------------------------------------------------------------
describe('isPaused (getter)', function ()
{
it('should reflect _paused state', function ()
{
var state = createAnimationState();
expect(state.isPaused).toBe(false);
state._paused = true;
expect(state.isPaused).toBe(true);
});
});
// -----------------------------------------------------------------------
describe('reverse', function ()
{
it('should toggle inReverse and forward when playing', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.inReverse = false;
state.forward = true;
state.reverse();
expect(state.inReverse).toBe(true);
expect(state.forward).toBe(false);
});
it('should toggle back on second call', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.inReverse = false;
state.forward = true;
state.reverse();
state.reverse();
expect(state.inReverse).toBe(false);
expect(state.forward).toBe(true);
});
it('should not toggle when not playing', function ()
{
var state = createAnimationState();
state.isPlaying = false;
state.inReverse = false;
state.forward = true;
state.reverse();
expect(state.inReverse).toBe(false);
expect(state.forward).toBe(true);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.reverse();
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('getProgress', function ()
{
it('should return 0 when no current frame', function ()
{
var state = createAnimationState();
state.currentFrame = null;
expect(state.getProgress()).toBe(0);
});
it('should return frame progress when playing forward', function ()
{
var state = createAnimationState();
state.currentFrame = { progress: 0.5 };
state.inReverse = false;
expect(state.getProgress()).toBe(0.5);
});
it('should return negative progress when in reverse', function ()
{
var state = createAnimationState();
state.currentFrame = { progress: 0.5 };
state.inReverse = true;
expect(state.getProgress()).toBe(-0.5);
});
it('should return 0 progress when at start frame', function ()
{
var state = createAnimationState();
state.currentFrame = { progress: 0 };
state.inReverse = false;
expect(state.getProgress()).toBe(0);
});
it('should return 1 progress when at last frame', function ()
{
var state = createAnimationState();
state.currentFrame = { progress: 1 };
state.inReverse = false;
expect(state.getProgress()).toBe(1);
});
});
// -----------------------------------------------------------------------
describe('setRepeat', function ()
{
it('should set repeatCounter to the given value', function ()
{
var state = createAnimationState();
state.setRepeat(5);
expect(state.repeatCounter).toBe(5);
});
it('should set repeatCounter to Number.MAX_VALUE when value is -1', function ()
{
var state = createAnimationState();
state.setRepeat(-1);
expect(state.repeatCounter).toBe(Number.MAX_VALUE);
});
it('should set repeatCounter to 0', function ()
{
var state = createAnimationState();
state.repeatCounter = 5;
state.setRepeat(0);
expect(state.repeatCounter).toBe(0);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.setRepeat(3);
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('getTotalFrames', function ()
{
it('should return 0 when no animation is loaded', function ()
{
var state = createAnimationState();
expect(state.getTotalFrames()).toBe(0);
});
it('should return the frame count from the current animation', function ()
{
var state = createAnimationState();
state.currentAnim = { getTotalFrames: function () { return 8; } };
expect(state.getTotalFrames()).toBe(8);
});
});
// -----------------------------------------------------------------------
describe('stopAfterDelay', function ()
{
it('should set _pendingStop to 1', function ()
{
var state = createAnimationState();
state.stopAfterDelay(500);
expect(state._pendingStop).toBe(1);
});
it('should store the delay in _pendingStopValue', function ()
{
var state = createAnimationState();
state.stopAfterDelay(500);
expect(state._pendingStopValue).toBe(500);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.stopAfterDelay(500);
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('stopAfterRepeat', function ()
{
it('should set _pendingStop to 2', function ()
{
var state = createAnimationState();
state.stopAfterRepeat(2);
expect(state._pendingStop).toBe(2);
});
it('should store the repeat count in _pendingStopValue', function ()
{
var state = createAnimationState();
state.repeatCounter = -1;
state.stopAfterRepeat(3);
expect(state._pendingStopValue).toBe(3);
});
it('should default repeatCount to 1', function ()
{
var state = createAnimationState();
state.repeatCounter = -1;
state.stopAfterRepeat();
expect(state._pendingStopValue).toBe(1);
});
it('should clamp repeatCount to repeatCounter when repeatCounter is not -1', function ()
{
var state = createAnimationState();
state.repeatCounter = 2;
state.stopAfterRepeat(10);
expect(state._pendingStopValue).toBe(2);
});
it('should not clamp when repeatCounter is -1', function ()
{
var state = createAnimationState();
state.repeatCounter = -1;
state.stopAfterRepeat(10);
expect(state._pendingStopValue).toBe(10);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.stopAfterRepeat(1);
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('stopOnFrame', function ()
{
it('should set _pendingStop to 3', function ()
{
var state = createAnimationState();
var frame = createMockAnimationFrame();
state.stopOnFrame(frame);
expect(state._pendingStop).toBe(3);
});
it('should store the frame in _pendingStopValue', function ()
{
var state = createAnimationState();
var frame = createMockAnimationFrame('myFrame');
state.stopOnFrame(frame);
expect(state._pendingStopValue).toBe(frame);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.stopOnFrame(createMockAnimationFrame());
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('get', function ()
{
it('should return null when anims map is null', function ()
{
var state = createAnimationState();
expect(state.get('walk')).toBeNull();
});
it('should return the animation by key', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk');
state.anims = new CustomMap();
state.anims.set('walk', anim);
expect(state.get('walk')).toBe(anim);
});
it('should return undefined for a missing key in an existing map', function ()
{
var state = createAnimationState();
state.anims = new CustomMap();
expect(state.get('missing')).toBeUndefined();
});
});
// -----------------------------------------------------------------------
describe('exists', function ()
{
it('should return false when anims map is null', function ()
{
var state = createAnimationState();
expect(state.exists('walk')).toBe(false);
});
it('should return true when the animation key exists', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk');
state.anims = new CustomMap();
state.anims.set('walk', anim);
expect(state.exists('walk')).toBe(true);
});
it('should return false when the animation key does not exist', function ()
{
var state = createAnimationState();
state.anims = new CustomMap();
expect(state.exists('walk')).toBe(false);
});
});
// -----------------------------------------------------------------------
describe('create', function ()
{
it('should return false when config has no key', function ()
{
var state = createAnimationState();
var result = state.create({ frames: [] });
expect(result).toBe(false);
});
it('should return existing animation when key already exists', function ()
{
var state = createAnimationState();
var existing = createMockAnimation('walk');
state.anims = new CustomMap();
state.anims.set('walk', existing);
var result = state.create({ key: 'walk' });
expect(result).toBe(existing);
});
it('should create an anims map if one does not exist', function ()
{
var state = createAnimationState();
expect(state.anims).toBeNull();
state.create({ key: 'walk', frames: [], frameRate: 10 });
expect(state.anims).not.toBeNull();
});
it('should return an animation object when created successfully', function ()
{
var state = createAnimationState();
var result = state.create({ key: 'walk', frames: [], frameRate: 10 });
expect(result).not.toBe(false);
expect(typeof result).toBe('object');
});
it('should make the animation retrievable via get() after creation', function ()
{
var state = createAnimationState();
state.create({ key: 'walk', frames: [], frameRate: 10 });
expect(state.exists('walk')).toBe(true);
expect(state.get('walk')).not.toBeNull();
});
});
// -----------------------------------------------------------------------
describe('remove', function ()
{
it('should return undefined when the key does not exist', function ()
{
var state = createAnimationState();
state.anims = new CustomMap();
var result = state.remove('ghost');
expect(result).toBeUndefined();
});
it('should remove the animation from the local map', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk');
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.remove('walk');
expect(state.exists('walk')).toBe(false);
});
it('should return the removed animation', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk');
state.anims = new CustomMap();
state.anims.set('walk', anim);
var result = state.remove('walk');
expect(result).toBe(anim);
});
it('should call stop if the removed animation is the current one', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk');
var stopCalled = false;
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.currentAnim = anim;
state.stop = function () { stopCalled = true; return state.parent; };
state.remove('walk');
expect(stopCalled).toBe(true);
});
it('should not call stop if the removed animation is not the current one', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk');
var otherAnim = createMockAnimation('run');
var stopCalled = false;
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.currentAnim = otherAnim;
state.stop = function () { stopCalled = true; return state.parent; };
state.remove('walk');
expect(stopCalled).toBe(false);
});
});
// -----------------------------------------------------------------------
describe('globalRemove', function ()
{
it('should stop the animation if it is currently playing', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk');
var stopCalled = false;
state.isPlaying = true;
state.currentAnim = anim;
state.stop = function () { stopCalled = true; return state.parent; };
state.setCurrentFrame = function () { return state.parent; };
state.globalRemove('walk', anim);
expect(stopCalled).toBe(true);
});
it('should not stop if a different animation is removed', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk');
var otherAnim = createMockAnimation('run');
var stopCalled = false;
state.isPlaying = true;
state.currentAnim = anim;
state.stop = function () { stopCalled = true; return state.parent; };
state.globalRemove('run', otherAnim);
expect(stopCalled).toBe(false);
});
it('should not stop if not currently playing', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk');
var stopCalled = false;
state.isPlaying = false;
state.currentAnim = anim;
state.stop = function () { stopCalled = true; return state.parent; };
state.globalRemove('walk', anim);
expect(stopCalled).toBe(false);
});
});
// -----------------------------------------------------------------------
describe('load', function ()
{
it('should return the parent when the animation key does not exist', function ()
{
var state = createAnimationState();
var result = state.load('nonexistent');
expect(result).toBe(state.parent);
});
it('should set currentAnim when loading a local animation', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 4);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.load('walk');
expect(state.currentAnim).toBe(anim);
});
it('should set currentFrame to the first frame', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.load('walk');
expect(state.currentFrame).toBe(anim.frames[0]);
});
it('should set currentFrame to the last frame when playing in reverse', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.forward = false;
state.load('walk');
expect(state.currentFrame).toBe(anim.frames[anim.frames.length - 1]);
});
it('should stop a playing animation before loading a new one', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
var stopCalled = false;
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.isPlaying = true;
state.stop = function () { stopCalled = true; state.isPlaying = false; return state.parent; };
state.load('walk');
expect(stopCalled).toBe(true);
});
it('should apply delay, repeat, yoyo from the animation config', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
anim.delay = 200;
anim.repeat = 3;
anim.yoyo = true;
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.load('walk');
expect(state.delay).toBe(200);
expect(state.repeat).toBe(3);
expect(state.yoyo).toBe(true);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.load('missingKey');
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('startAnimation', function ()
{
it('should set isPlaying to true when animation is found', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.setCurrentFrame = function () { return state.parent; };
state.startAnimation('walk');
expect(state.isPlaying).toBe(true);
});
it('should set hasStarted to true when no delay', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.setCurrentFrame = function () { return state.parent; };
state.startAnimation('walk');
expect(state.hasStarted).toBe(true);
});
it('should set pendingRepeat to false', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.setCurrentFrame = function () { return state.parent; };
state.pendingRepeat = true;
state.startAnimation('walk');
expect(state.pendingRepeat).toBe(false);
});
it('should set repeatCounter to repeat value', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
anim.repeat = 5;
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.setCurrentFrame = function () { return state.parent; };
state.startAnimation('walk');
expect(state.repeatCounter).toBe(5);
});
it('should set repeatCounter to MAX_VALUE when repeat is -1', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
anim.repeat = -1;
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.setCurrentFrame = function () { return state.parent; };
state.startAnimation('walk');
expect(state.repeatCounter).toBe(Number.MAX_VALUE);
});
it('should return parent without starting if animation not found', function ()
{
var state = createAnimationState();
var result = state.startAnimation('missing');
expect(result).toBe(state.parent);
expect(state.isPlaying).toBe(false);
});
});
// -----------------------------------------------------------------------
describe('play', function ()
{
it('should set forward to true and inReverse to false', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.setCurrentFrame = function () { return state.parent; };
state.forward = false;
state.inReverse = true;
state.play('walk');
expect(state.forward).toBe(true);
expect(state.inReverse).toBe(false);
});
it('should return parent immediately if ignoreIfPlaying and same animation', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.currentAnim = { key: 'walk' };
var result = state.play('walk', true);
expect(result).toBe(state.parent);
});
it('should not ignore if a different animation is playing', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('run', 3);
state.anims = new CustomMap();
state.anims.set('run', anim);
state.isPlaying = true;
state.currentAnim = { key: 'walk' };
state.currentFrame = createMockAnimationFrame();
state.setCurrentFrame = function () { return state.parent; };
state.animationManager.getMix = function () { return 0; };
state.play('run', true);
expect(state.currentAnim).toBe(anim);
});
it('should call playAfterDelay when mix time is > 0', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('run', 3);
var mixCalledWith = null;
state.anims = new CustomMap();
state.anims.set('run', anim);
state.isPlaying = true;
state.currentAnim = { key: 'walk' };
state.animationManager.getMix = function () { return 500; };
state.playAfterDelay = function (key, mix)
{
mixCalledWith = { key: key, mix: mix };
return state.parent;
};
state.play('run');
expect(mixCalledWith).not.toBeNull();
expect(mixCalledWith.mix).toBe(500);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.setCurrentFrame = function () { return state.parent; };
var result = state.play('walk');
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('playReverse', function ()
{
it('should set forward to false and inReverse to true', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.setCurrentFrame = function () { return state.parent; };
state.playReverse('walk');
expect(state.forward).toBe(false);
expect(state.inReverse).toBe(true);
});
it('should return parent immediately if ignoreIfPlaying and same animation', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.currentAnim = { key: 'walk' };
var result = state.playReverse('walk', true);
expect(result).toBe(state.parent);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
state.anims = new CustomMap();
state.anims.set('walk', anim);
state.setCurrentFrame = function () { return state.parent; };
var result = state.playReverse('walk');
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('playAfterDelay', function ()
{
it('should call play with the key when not already playing', function ()
{
var state = createAnimationState();
var playCalled = false;
state.isPlaying = false;
state.play = function () { playCalled = true; return state.parent; };
state.playAfterDelay('walk', 300);
expect(playCalled).toBe(true);
});
it('should set delayCounter when not already playing', function ()
{
var state = createAnimationState();
state.isPlaying = false;
state.play = function () { return state.parent; };
state.playAfterDelay('walk', 300);
expect(state.delayCounter).toBe(300);
});
it('should queue the key as nextAnim when already playing', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.nextAnim = null;
state.playAfterDelay('walk', 300);
expect(state.nextAnim).toBe('walk');
});
it('should push existing nextAnim to the front of the queue when already playing', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.nextAnim = 'idle';
state.playAfterDelay('walk', 300);
expect(state.nextAnim).toBe('walk');
expect(state.nextAnimsQueue[0]).toBe('idle');
});
it('should set _pendingStop to 1 when already playing', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.playAfterDelay('walk', 300);
expect(state._pendingStop).toBe(1);
expect(state._pendingStopValue).toBe(300);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
state.isPlaying = false;
state.play = function () { return state.parent; };
var result = state.playAfterDelay('walk', 300);
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('playAfterRepeat', function ()
{
it('should call play when not already playing', function ()
{
var state = createAnimationState();
var playCalled = false;
state.isPlaying = false;
state.play = function () { playCalled = true; return state.parent; };
state.playAfterRepeat('walk', 2);
expect(playCalled).toBe(true);
});
it('should default repeatCount to 1', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.repeatCounter = 5;
state.playAfterRepeat('walk');
expect(state._pendingStopValue).toBe(1);
});
it('should set _pendingStop to 2 when already playing', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.repeatCounter = 5;
state.playAfterRepeat('walk', 2);
expect(state._pendingStop).toBe(2);
});
it('should clamp repeatCount to repeatCounter when less', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.repeatCounter = 3;
state.playAfterRepeat('walk', 10);
expect(state._pendingStopValue).toBe(3);
});
it('should push existing nextAnim to front of queue', function ()
{
var state = createAnimationState();
state.isPlaying = true;
state.repeatCounter = 5;
state.nextAnim = 'idle';
state.playAfterRepeat('walk', 2);
expect(state.nextAnim).toBe('walk');
expect(state.nextAnimsQueue[0]).toBe('idle');
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
state.isPlaying = false;
state.play = function () { return state.parent; };
var result = state.playAfterRepeat('walk', 2);
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('restart', function ()
{
it('should return parent without action when no animation is loaded', function ()
{
var state = createAnimationState();
var result = state.restart();
expect(result).toBe(state.parent);
expect(state.isPlaying).toBe(false);
});
it('should set isPlaying to true', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.setCurrentFrame = function () { return state.parent; };
state.restart();
expect(state.isPlaying).toBe(true);
});
it('should set pendingRepeat to false', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.setCurrentFrame = function () { return state.parent; };
state.pendingRepeat = true;
state.restart();
expect(state.pendingRepeat).toBe(false);
});
it('should reset repeatCounter when resetRepeats is true', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.repeat = 4;
state.repeatCounter = 0;
state.setCurrentFrame = function () { return state.parent; };
state.restart(false, true);
expect(state.repeatCounter).toBe(4);
});
it('should set hasStarted to true when includeDelay is false', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.setCurrentFrame = function () { return state.parent; };
state.restart(false);
expect(state.hasStarted).toBe(true);
});
it('should set hasStarted to false when includeDelay is true', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.setCurrentFrame = function () { return state.parent; };
state.restart(true);
expect(state.hasStarted).toBe(false);
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.setCurrentFrame = function () { return state.parent; };
var result = state.restart();
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('stop', function ()
{
it('should set isPlaying to false', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.isPlaying = true;
state.parent.emit = function () {};
state.stop();
expect(state.isPlaying).toBe(false);
});
it('should reset _pendingStop to 0', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state._pendingStop = 2;
state.parent.emit = function () {};
state.stop();
expect(state._pendingStop).toBe(0);
});
it('should reset delayCounter to 0', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.delayCounter = 500;
state.parent.emit = function () {};
state.stop();
expect(state.delayCounter).toBe(0);
});
it('should play nextAnim if one is queued', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
var playCalled = null;
attachMockAnimation(state, anim);
state.parent.emit = function () {};
state.nextAnim = 'run';
state.play = function (key) { playCalled = key; return state.parent; };
state.stop();
expect(playCalled).toBe('run');
});
it('should shift the queue into nextAnim when playing the queued animation', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.parent.emit = function () {};
state.nextAnim = 'run';
state.nextAnimsQueue = [ 'idle' ];
state.play = function () { return state.parent; };
state.stop();
expect(state.nextAnim).toBe('idle');
});
it('should return the parent game object', function ()
{
var state = createAnimationState();
var result = state.stop();
expect(result).toBe(state.parent);
});
});
// -----------------------------------------------------------------------
describe('complete', function ()
{
it('should set isPlaying to false', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state.isPlaying = true;
state.parent.emit = function () {};
state.complete();
expect(state.isPlaying).toBe(false);
});
it('should reset _pendingStop to 0', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
attachMockAnimation(state, anim);
state._pendingStop = 1;
state.parent.emit = function () {};
state.complete();
expect(state._pendingStop).toBe(0);
});
it('should play nextAnim when one is queued', function ()
{
var state = createAnimationState();
var anim = createMockAnimation('walk', 3);
var playCalled = null;
attachMockAnimation(state, anim);
state.parent.emit = function () {};
state.nextAnim = 'run