/*global Quintus:false */ Quintus.Anim = function(Q) { Q._animations = {}; Q.animations = function(sprite,animations) { if(!Q._animations[sprite]) { Q._animations[sprite] = {}; } Q._extend(Q._animations[sprite],animations); }; Q.animation = function(sprite,name) { return Q._animations[sprite] && Q._animations[sprite][name]; }; Q.component('animation',{ added: function() { var p = this.entity.p; p.animation = null; p.animationPriority = -1; p.animationFrame = 0; p.animationTime = 0; this.entity.on("step",this,"step"); }, extend: { play: function(name,priority) { this.animation.play(name,priority); } }, step: function(dt) { var entity = this.entity, p = entity.p; if(p.animation) { var anim = Q.animation(p.sprite,p.animation), rate = anim.rate || p.rate, stepped = 0; p.animationTime += dt; if(p.animationChanged) { p.animationChanged = false; } else { p.animationTime += dt; if(p.animationTime > rate) { stepped = Math.floor(p.animationTime / rate); p.animationTime -= stepped * rate; p.animationFrame += stepped; } } if(stepped > 0) { if(p.animationFrame >= anim.frames.length) { if(anim.loop === false || anim.next) { p.animationFrame = anim.frames.length - 1; entity.trigger('animEnd'); entity.trigger('animEnd.' + p.animation); p.animation = null; p.animationPriority = -1; if(anim.trigger) { entity.trigger(anim.trigger,anim.triggerData); } if(anim.next) { this.play(anim.next,anim.nextPriority); } return; } else { entity.trigger('animLoop'); entity.trigger('animLoop.' + p.animation); p.animationFrame = p.animationFrame % anim.frames.length; } } entity.trigger("animFrame"); } p.sheet = anim.sheet || p.sheet; p.frame = anim.frames[p.animationFrame]; } }, play: function(name,priority) { var entity = this.entity, p = entity.p; priority = priority || 0; if(name !== p.animation && priority >= p.animationPriority) { p.animation = name; p.animationChanged = true; p.animationTime = 0; p.animationFrame = 0; p.animationPriority = priority; entity.trigger('anim'); entity.trigger('anim.' + p.animation); } } }); Q.Sprite.extend("Repeater",{ init: function(props) { this._super(Q._defaults(props,{ speedX: 1, speedY: 1, repeatY: true, repeatX: true })); this.p.repeatW = this.p.repeatW || this.p.w; this.p.repeatH = this.p.repeatH || this.p.h; }, draw: function(ctx) { var p = this.p, asset = this.asset(), sheet = this.sheet(), scale = this.parent.viewport ? this.parent.viewport.scale : 1, viewX = this.parent.viewport ? this.parent.viewport.x : 0, viewY = this.parent.viewport ? this.parent.viewport.y : 0, offsetX = p.x + viewX * this.p.speedX, offsetY = p.y + viewY * this.p.speedY, curX, curY, startX; if(p.repeatX) { curX = Math.floor(-offsetX % p.repeatW); if(curX > 0) { curX -= p.repeatW; } } else { curX = p.x - viewX; } if(p.repeatY) { curY = Math.floor(-offsetY % p.repeatH); if(curY > 0) { curY -= p.repeatH; } } else { curY = p.y - viewY; } startX = curX; while(curY < Q.height / scale) { curX = startX; while(curX < Q.width / scale) { if(sheet) { sheet.draw(ctx,Math.floor(curX + viewX), Math.floor(curY + viewY),p.frame); } else { ctx.drawImage(asset,Math.floor(curX + viewX),Math.floor(curY + viewY)); } curX += p.repeatW; if(!p.repeatX) { break; } } curY += p.repeatH; if(!p.repeatY) { break; } } } }); Q.Tween = Q.Class.extend({ init: function(entity,properties,duration,easing,options) { if(Q._isObject(easing)) { options = easing; easing = Q.Easing.Linear } if(Q._isObject(duration)) { options = duration; duration = 1 } this.entity = entity; this.p = (entity instanceof Q.Stage) ? entity.viewport : entity.p; this.duration = duration || 1; this.time = 0; this.options = options || {}; this.delay = this.options.delay || 0; this.easing = easing || this.options.easing || Q.Easing.Linear; this.startFrame = Q._loopFrame + 1; this.start = {}; this.diff = {}; for(var property in properties) { this.start[property] = this.p[property]; if(!Q._isUndefined(this.start[property])) { this.diff[property] = properties[property] - this.start[property]; } } }, step: function(dt) { if(this.startFrame > Q._loopFrame) return true; if(this.delay >= dt) { this.delay -= dt; return true; } if(this.delay > 0) { dt -= this.delay; this.delay = 0; } this.time += dt; var progress = Math.min(1,this.time / this.duration), location = this.easing(progress); for(var property in this.start) { if(!Q._isUndefined(this.p[property])) { this.p[property] = this.start[property] + this.diff[property] * location; } } if(progress >= 1) { if(this.options.callback) { this.options.callback.apply(this.entity); } } return progress < 1; } }); // Code ripped directly from Tween.js // https://github.com/sole/tween.js/blob/master/src/Tween.js Q.Easing = { Linear: function (k) { return k; }, Quadratic: { In: function ( k ) { return k * k; }, Out: function ( k ) {return k * ( 2 - k ); }, InOut: function ( k ) { if ( ( k *= 2 ) < 1 ) return 0.5 * k * k; return - 0.5 * ( --k * ( k - 2 ) - 1 ); } } }; Q.component('tween',{ added: function() { this._tweens = []; this.entity.on("step",this,"step"); }, extend: { animate: function(properties,duration,easing,options) { this.tween._tweens.push(new Q.Tween(this,properties,duration,easing,options)); return this; }, chain: function(properties,duration,easing,options) { if(Q._isObject(easing)) { options = easing; easing = Q.Easing.Linear } // Chain an animation to the end var tweenCnt = this.tween._tweens.length; if(this.tweenCnt > 0) { var lastTween = this.tween._tweens[tweenCnt - 1]; options = options || {}; options['delay'] = lastTween.duration - lastTween.time + lastTween.delay; } this.animate(properties,duration,easing,options); return this; }, stop: function() { this.tween._tweens.length = 0; return this; } }, step: function(dt) { for(var i=this._tweens.length-1;i>=0;i--) { if(!this._tweens[i].step(dt)) { this._tweens.splice(i,1); } } } }); };