UNPKG

@sky-foundry/two.js

Version:

A renderer agnostic two-dimensional drawing api for the web.

252 lines (180 loc) 5.38 kB
(function(Two) { var _ = Two.Utils; var Path = Two.Path; var Rectangle = Two.Rectangle; var Sprite = Two.Sprite = function(path, ox, oy, cols, rows, frameRate) { Path.call(this, [ new Two.Anchor(), new Two.Anchor(), new Two.Anchor(), new Two.Anchor() ], true); this.noStroke(); this.noFill(); if (path instanceof Two.Texture) { this.texture = path; } else if (_.isString(path)) { this.texture = new Two.Texture(path); } this.origin = new Two.Vector(); this._update(); this.translation.set(ox || 0, oy || 0); if (_.isNumber(cols)) { this.columns = cols; } if (_.isNumber(rows)) { this.rows = rows; } if (_.isNumber(frameRate)) { this.frameRate = frameRate; } }; _.extend(Sprite, { Properties: [ 'texture', 'columns', 'rows', 'frameRate', 'index' ], MakeObservable: function(obj) { Rectangle.MakeObservable(obj); _.each(Sprite.Properties, Two.Utils.defineProperty, obj); } }) _.extend(Sprite.prototype, Rectangle.prototype, { _flagTexture: false, _flagColumns: false, _flagRows: false, _flagFrameRate: false, flagIndex: false, // Private variables _amount: 1, _duration: 0, _startTime: 0, _playing: false, _firstFrame: 0, _lastFrame: 0, _loop: true, // Exposed through getter-setter _texture: null, _columns: 1, _rows: 1, _frameRate: 0, _index: 0, _origin: null, constructor: Sprite, play: function(firstFrame, lastFrame, onLastFrame) { this._playing = true; this._firstFrame = 0; this._lastFrame = this.amount - 1; this._startTime = _.performance.now(); if (_.isNumber(firstFrame)) { this._firstFrame = firstFrame; } if (_.isNumber(lastFrame)) { this._lastFrame = lastFrame; } if (_.isFunction(onLastFrame)) { this._onLastFrame = onLastFrame; } else { delete this._onLastFrame; } if (this._index !== this._firstFrame) { this._startTime -= 1000 * Math.abs(this._index - this._firstFrame) / this._frameRate; } return this; }, pause: function() { this._playing = false; return this; }, stop: function() { this._playing = false; this._index = 0; return this; }, clone: function(parent) { var clone = new Sprite( this.texture, this.translation.x, this.translation.y, this.columns, this.rows, this.frameRate ); if (this.playing) { clone.play(this._firstFrame, this._lastFrame); clone._loop = this._loop; } if (parent) { parent.add(clone); } return clone; }, _update: function() { var effect = this._texture; var cols = this._columns; var rows = this._rows; var width, height, elapsed, amount, duration; var index, iw, ih, isRange, frames; if (this._flagColumns || this._flagRows) { this._amount = this._columns * this._rows; } if (this._flagFrameRate) { this._duration = 1000 * this._amount / this._frameRate; } if (this._flagTexture) { this.fill = this._texture; } if (this._texture.loaded) { iw = effect.image.width; ih = effect.image.height; width = iw / cols; height = ih / rows; amount = this._amount; if (this.width !== width) { this.width = width; } if (this.height !== height) { this.height = height; } if (this._playing && this._frameRate > 0) { if (_.isNaN(this._lastFrame)) { this._lastFrame = amount - 1; } // TODO: Offload perf logic to instance of `Two`. elapsed = _.performance.now() - this._startTime; frames = this._lastFrame + 1; duration = 1000 * (frames - this._firstFrame) / this._frameRate; if (this._loop) { elapsed = elapsed % duration; } else { elapsed = Math.min(elapsed, duration); } index = _.lerp(this._firstFrame, frames, elapsed / duration); index = Math.floor(index); if (index !== this._index) { this._index = index; if (index >= this._lastFrame - 1 && this._onLastFrame) { this._onLastFrame(); // Shortcut for chainable sprite animations } } } var col = this._index % cols; var row = Math.floor(this._index / cols); var ox = - width * col + (iw - width) / 2; var oy = - height * row + (ih - height) / 2; // TODO: Improve performance if (ox !== effect.offset.x) { effect.offset.x = ox; } if (oy !== effect.offset.y) { effect.offset.y = oy; } } Rectangle.prototype._update.call(this); return this; }, flagReset: function() { this._flagTexture = this._flagColumns = this._flagRows = this._flagFrameRate = false; Rectangle.prototype.flagReset.call(this); return this; } }); Sprite.MakeObservable(Sprite.prototype); })((typeof global !== 'undefined' ? global : (this || window)).Two);