mirror of
https://github.com/hiloteam/Hilo.git
synced 2025-12-08 20:35:59 +00:00
251 lines
8.1 KiB
JavaScript
251 lines
8.1 KiB
JavaScript
/**
|
|
* Hilo
|
|
* Copyright 2015 alibaba.com
|
|
* Licensed under the MIT License
|
|
*/
|
|
|
|
/**
|
|
* <iframe src='../../../examples/Sprite.html?noHeader' width = '550' height = '400' scrolling='no'></iframe>
|
|
* <br/>
|
|
* @class Sprite animation class.
|
|
* @augments View
|
|
* @module hilo/view/Sprite
|
|
* @requires hilo/core/Hilo
|
|
* @requires hilo/core/Class
|
|
* @requires hilo/view/View
|
|
* @requires hilo/view/Drawable
|
|
* @param properties Properties parameters for creating object, include all writable properties of this class, also include:
|
|
* <ul>
|
|
* <li><b>frames</b> - Sprite animation frames data object.</li>
|
|
* </ul>
|
|
* @property {number} currentFrame Current showing frame index, range from 0, readoly!
|
|
* @property {boolean} paused Is sprite paused, default value is false.
|
|
* @property {boolean} loop Is sprite play in loop, default value is false.
|
|
* @property {boolean} timeBased Is sprite animate base on time, default value is false (base on frame).
|
|
* @property {number} interval Interval between sprite animation frames. If timeBased is true, measured in ms, otherwise, measured in frames.
|
|
*/
|
|
var Sprite = Class.create(/** @lends Sprite.prototype */{
|
|
Extends: View,
|
|
constructor: function(properties){
|
|
properties = properties || {};
|
|
this.id = this.id || properties.id || Hilo.getUid("Sprite");
|
|
Sprite.superclass.constructor.call(this, properties);
|
|
|
|
this._frames = [];
|
|
this._frameNames = {};
|
|
this.drawable = new Drawable();
|
|
if(properties.frames) this.addFrame(properties.frames);
|
|
},
|
|
|
|
_frames: null, //所有帧的集合 Collection of all frames
|
|
_frameNames: null, //带名字name的帧的集合 Collection of frames that with name
|
|
_frameElapsed: 0, //当前帧持续的时间或帧数 Elapsed time of current frame.
|
|
_firstRender: true, //标记是否是第一次渲染 Is the first render.
|
|
|
|
paused: false,
|
|
loop: true,
|
|
timeBased: false,
|
|
interval: 1,
|
|
currentFrame: 0, //当前帧的索引 Index of current frame
|
|
|
|
/**
|
|
* Return the total amount of sprite animation frames.
|
|
* @returns {Uint} The total amount of frames.
|
|
*/
|
|
getNumFrames: function(){
|
|
return this._frames ? this._frames.length : 0;
|
|
},
|
|
|
|
/**
|
|
* Add frame into sprite.
|
|
* @param {Object} frame Frames to add into.
|
|
* @param {Int} startIndex The index to start adding frame, if is not given, add at the end of sprite.
|
|
* @returns {Sprite} Sprite itself.
|
|
*/
|
|
addFrame: function(frame, startIndex){
|
|
var start = startIndex != null ? startIndex : this._frames.length;
|
|
if(frame instanceof Array){
|
|
for(var i = 0, len = frame.length; i < len; i++){
|
|
this.setFrame(frame[i], start + i);
|
|
}
|
|
}else{
|
|
this.setFrame(frame, start);
|
|
}
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the frame on the given index.
|
|
* @param {Object} frame The frame data to set on that index.
|
|
* @param {Int} index Index of the frame to set.
|
|
* @returns {Sprite} Sprite itself.
|
|
*/
|
|
setFrame: function(frame, index){
|
|
var frames = this._frames,
|
|
total = frames.length;
|
|
index = index < 0 ? 0 : index > total ? total : index;
|
|
frames[index] = frame;
|
|
if(frame.name) this._frameNames[frame.name] = frame;
|
|
if(index == 0 && !this.width || !this.height){
|
|
this.width = frame.rect[2];
|
|
this.height = frame.rect[3];
|
|
}
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Get the frame of given parameter from sprite.
|
|
* @param {Object} indexOrName The index or name of the frame.
|
|
* @returns {Object} The sprite object.
|
|
*/
|
|
getFrame: function(indexOrName){
|
|
if(typeof indexOrName === 'number'){
|
|
var frames = this._frames;
|
|
if(indexOrName < 0 || indexOrName >= frames.length) return null;
|
|
return frames[indexOrName];
|
|
}
|
|
return this._frameNames[indexOrName];
|
|
},
|
|
|
|
/**
|
|
* Get frame index from sprite.
|
|
* @param {Object} frameValue Index or name of the frame.
|
|
* @returns {Object} Sprite frame object.
|
|
*/
|
|
getFrameIndex: function(frameValue){
|
|
var frames = this._frames,
|
|
total = frames.length,
|
|
index = -1;
|
|
if(typeof frameValue === 'number'){
|
|
index = frameValue;
|
|
}else{
|
|
var frame = typeof frameValue === 'string' ? this._frameNames[frameValue] : frameValue;
|
|
if(frame){
|
|
for(var i = 0; i < total; i++){
|
|
if(frame === frames[i]){
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return index;
|
|
},
|
|
|
|
/**
|
|
* Play sprite.
|
|
* @returns {Sprite} The Sprite object.
|
|
*/
|
|
play: function(){
|
|
this.paused = false;
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Pause playing sprite.
|
|
* @returns {Sprite} The Sprite object.
|
|
*/
|
|
stop: function(){
|
|
this.paused = true;
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Jump to an assigned frame.
|
|
* @param {Object} indexOrName Index or name of an frame to jump to.
|
|
* @param {Boolean} pause Does pause after jumping to the new index.
|
|
* @returns {Sprite} The Sprite object.
|
|
*/
|
|
goto: function(indexOrName, pause){
|
|
var total = this._frames.length,
|
|
index = this.getFrameIndex(indexOrName);
|
|
|
|
this.currentFrame = index < 0 ? 0 : index >= total ? total - 1 : index;
|
|
this.paused = pause;
|
|
this._firstRender = true;
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Render function.
|
|
* @private
|
|
*/
|
|
_render: function(renderer, delta){
|
|
var lastFrameIndex = this.currentFrame, frameIndex;
|
|
|
|
if(this._firstRender){
|
|
frameIndex = lastFrameIndex;
|
|
this._firstRender = false;
|
|
}else{
|
|
frameIndex = this._nextFrame(delta);
|
|
}
|
|
|
|
if(frameIndex != lastFrameIndex){
|
|
this.currentFrame = frameIndex;
|
|
var callback = this._frames[frameIndex].callback;
|
|
callback && callback.call(this);
|
|
}
|
|
|
|
//NOTE: it will be deprecated, don't use it.
|
|
if(this.onEnterFrame) this.onEnterFrame(frameIndex);
|
|
|
|
this.drawable.init(this._frames[frameIndex]);
|
|
Sprite.superclass._render.call(this, renderer, delta);
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
_nextFrame: function(delta){
|
|
var frames = this._frames,
|
|
total = frames.length,
|
|
frameIndex = this.currentFrame,
|
|
frame = frames[frameIndex],
|
|
duration = frame.duration || this.interval,
|
|
elapsed = this._frameElapsed;
|
|
|
|
//calculate the current frame elapsed frames/time
|
|
var value = (frameIndex == 0 && !this.drawable) ? 0 : elapsed + (this.timeBased ? delta : 1);
|
|
elapsed = this._frameElapsed = value < duration ? value : 0;
|
|
|
|
if(frame.stop || !this.loop && frameIndex >= total - 1){
|
|
this.stop();
|
|
}
|
|
|
|
if(!this.paused && elapsed == 0){
|
|
if(frame.next != null){
|
|
//jump to the specified frame
|
|
frameIndex = this.getFrameIndex(frame.next);
|
|
}else if(frameIndex >= total - 1){
|
|
//at the end of the frames, go back to first frame
|
|
frameIndex = 0;
|
|
}else if(this.drawable){
|
|
//normal go forward to next frame
|
|
frameIndex++;
|
|
}
|
|
}
|
|
|
|
return frameIndex;
|
|
},
|
|
|
|
/**
|
|
* Set a callback on an assigned frame. Every time assigned frame is played, invoke the callback function. If callback is empty, callback function will be removed.
|
|
* @param {Int|String} frame Index or name of the assigned frame.
|
|
* @param {Function} callback Callback function.
|
|
* @returns {Sprite} The Sprite object.
|
|
*/
|
|
setFrameCallback: function(frame, callback){
|
|
frame = this.getFrame(frame);
|
|
if(frame) frame.callback = callback;
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Callback function on when sprite enter a new frame. default value is null. Note: this function is obsolete, use addFrameCallback funciton instead.
|
|
* @type Function
|
|
* @deprecated
|
|
*/
|
|
onEnterFrame: null
|
|
|
|
});
|