ActionScript 开发之自定义 EnterFrame 事件

时间:2022-02-28 03:27:57
/*
FrameUtils 类说明:

使用:
1、避免 Flash 最小化机制带来帧频降低的影响。更准确的控制帧的运行,方便为不同影片剪辑设置不同的帧频,更方便在帧标签中添加动作(注册回调函数)。
优点:
1、与 EnterFrame 相比,不受最小化降帧影响。
2、方便为不同的影片剪辑设置不同的帧频。
3、方便在帧标签中添加动作。
缺点:
创建FrameUtils会带来内存的开销,由于采用 MovieClip的EnterFrame在内部运行,创建对象等于创建MovieClip,建议整个游戏中只创建一个或者几个FrameUtils,经测试,创建一个,已足够使用。

例子:

var frameUtils:FrameUtils = new FrameUtils();
frameUtils.registerCallback("1", function():void{
trace(new Date());
}, 1000);
frameUtils.play();
*/

package utils
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Dictionary;
import flash.utils.getTimer;

/**
* 模拟计时器
*/
public class FrameUtils
{
/**
* 暂停状态
*/
public static var pause:Boolean = false;

/**
* 计时器
*/
private var _movieClip:MovieClip;

/**
* 当前时间 getTimer();
*/
private var _currentTime:int;

/**
* 回调函数列表
*/
private var _dictionary:Dictionary;

/**
* 不支持 addEventListener 任何事件,请通过 registerCallback 添加回调函数。
*
*/
public function FrameUtils() {}

/**
* 播放,暂停请直接设置 FrameUtils.pause = false;
*
*/
public function play():void
{
this._currentTime = getTimer();

if(this._movieClip == null) this._movieClip = new MovieClip();

if(!this._movieClip.hasEventListener(Event.ENTER_FRAME)){
this._movieClip.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
this._movieClip.play();
}

/**
* 停止 ,暂停请直接设置 FrameUtils.pause = false;
*
*/
public function stop():void
{
if(this._movieClip == null) return;

if(this._movieClip.hasEventListener(Event.ENTER_FRAME))
{
this._movieClip.removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
this._movieClip.stop();
}

/**
* 销毁
*
*/
public function destory():void
{
this.stop();

this._movieClip = null;

for each(var key:String in this._dictionary)
{
this._dictionary[key] = null;
delete this._dictionary[key];
}

this._dictionary = null;
}

/**
* 注册侦函数
* @param type 消息类别
* @param callback 回调函数
* @param delay 延迟时间,单位:毫秒
*
*/
public function registerCallback(type:String, callback:Function, delay:int = 1000):void
{
if(this._dictionary == null) this._dictionary = new Dictionary();

var frameCallback:FrameCallback = new FrameCallback(callback, delay);

if(this._dictionary[type] != null){

var index:int = this.getCallback(callback, this._dictionary[type]);

if(index == -1){

this._dictionary[type].push(frameCallback);

}
}else{

this._dictionary[type] = [frameCallback];

}
}

/**
* 移除侦函数
* @param type 消息类别
* @param callback 回调函数
*
*/
public function unRegisterCallback(type:String, callback:Function):void
{
if(this._dictionary == null) return;

if(this._dictionary[type] != null){

var index:int = this.getCallback(callback, this._dictionary[type]);

if(index != -1){

this._dictionary[type].splice(index, 1);

}
}
}

/**
* Event.ENTER_FRAME
* @param eventHandler
*
*/
private function onEnterFrameHandler(eventHandler:Event):void
{
// 如果是非暂停状态
if(!pause)
{
this.enterFrameCallback();
}
}

/**
* Event.ENTER_FRAME 处理
*
*/
private function enterFrameCallback():void
{
var subTime:int = getTimer() - this._currentTime;

if(this._dictionary != null)
{
for(var key:String in this._dictionary){

for each(var frameCallback:FrameCallback in this._dictionary[key] as Array){

var currentTime:int = subTime + frameCallback.currentDelay;

if(currentTime >= frameCallback.delay){

var tickNum:int = int(currentTime / frameCallback.delay);

var modNum:int = currentTime % frameCallback.delay;

while(tickNum > 0){

frameCallback.callback();

tickNum --;
}

frameCallback.currentDelay = modNum;

}else{

frameCallback.currentDelay += subTime;

}

}
}
}

this._currentTime = getTimer();
}

/**
* 获取侦函数,采用遍历获取索引
* @param callback
* @param list
* @return
*
*/
private function getCallback(callback:Function, list:Array):int
{
var index:int = 0;
for each(var frameCallback:FrameCallback in list){
if(frameCallback.callback == callback) return index;
index ++;
}
return -1;
}
}
}
/**
* 内部类,回调使用
*
*/
class FrameCallback
{
public var callback:Function;
public var delay:int;
public var currentDelay:int;

public function FrameCallback(callback:Function, delay:int){
this.callback = callback;
this.delay = delay;
}
}