読者です 読者をやめる 読者になる 読者になる

TimeWalkerクラスというのを作ってみた

何秒後にこれやって何秒後にこれやって何秒後にこれやって…みたいな処理を書くのが面倒なのでそれを楽にするクラスを書いてみた。
機能を最小限でエラー処理していない完成度40%ぐらいのものだけどとりあえず公開。

それを使うとこういう風に書ける

package
{
    import flash.display.*;
    
    public class Etude extends Sprite
    {
        public var tw:TimeWalker;
        public function Etude()
        {
            tw = TimeWalker.create(this);
            tw.start();
        }
        public function timeline_0_0():void
        {
            trace('start');
        }
        public function timeline_0_5():void
        {
            trace('0.5秒経過');
        }
        public function timeline_2_0():void
        {
            trace('2.0秒経過');
        }
        public function timeline_2_5():void
        {
            trace('2.5秒経過');
        }
        public function timeline_6_0():void
        {
            trace('end');
        }
    }
}

指定したオブジェクトからタイムラインをあらわすメソッド名を抜き出して、時系列でメソッドを呼び出しています。
デフォルトではtimeline_[0-9]+_?[0-9]{0,3}のメソッドを抜き出します。

こういう風にも書ける

package
{
    import flash.display.*;
    
    public class Etude extends Sprite
    {
        public var tw:TimeWalker;
        public function Etude()
        {
            tw = TimeWalker.create(this,'t');  // t_[0-9]+_?[0-9]{0,3}のメソッドを抜き出す
            tw.start();
        }
        public function t_0():void
        {
            trace('start');
        }
        public function t_4():void
        {
            trace('4秒経過');
        }
        public function t_6_00():void
        {
            trace('end');
            tw.rewind();  // 繰り返し
        }
    }
}

TimeWalker.createの第二引数で抜き出すメソッドの条件を一部指定しています。

ソース

// TimeWalker.as

package
{
    import flash.utils.*;
    import flash.events.TimerEvent;
    public class TimeWalker
    {
        private var timeKey:uint;
        private var timer:Timer;
        private var timeline:TimeLine;
        
        public function TimeWalker(timeline:TimeLine)
        {
            this.timeKey = 0;
            this.timeline = timeline;
            
            this.timer = new Timer(1,0);
            this.timer.addEventListener(TimerEvent.TIMER,execute);
            
        }
        public function start():void
        {
            if(timeKey == 0) timer.delay = 1;
            
            timer.start();
        }
        public function stop():void
        {
            timer.stop();
        }
        public function getNextTime():Number
        {
            return timeline.getNextTime(timeKey) / 1000;
        }
        private function execute(e:TimerEvent = null):void
        {
            timeline.execute(timeKey);
            
            if(timeline.hasNext(timeKey)){
                timer.delay = timeline.getNextTime(timeKey);
                timeKey++;
            }else{
                timer.stop();
            }
        }
        public function rewind():void
        {
            timeKey = 0;
            if(timer.running) timeline.execute(0);
        }
        public static function create(source:Object,identifier:String = 'timeline'):TimeWalker
        {
            return new TimeWalker(TimeLine.create(source,identifier));
        }
    }
}

import flash.utils.*;
import flash.events.TimerEvent;
class TimeLine
{
    public var methodOnTimeArray:Array = [];
    public var timeArray:Array = [];
    public var thisObject:Object;
    
    public function TimeLine(methodOnTimeArray:Array,thisObject:Object=null)
    {
        if(methodOnTimeArray[0] == undefined){
            methodOnTimeArray[0] = function():void{};
        }
        
        this.methodOnTimeArray = methodOnTimeArray;
        this.thisObject = thisObject;
        
        for(var time:* in methodOnTimeArray){
            timeArray.push(parseFloat(time));
        }
        
        timeArray.sort(Array.NUMERIC);
    }
    public function execute(timeKey:uint):void
    {
        methodOnTimeArray[timeArray[timeKey]].call(thisObject);
    }
    public function getNextTime(timeKey:uint):Number
    {
        return 1000 * (timeArray[timeKey + 1] - timeArray[timeKey]);
    }
    public function hasNext(timeKey:uint):Boolean
    {
        if(timeKey >= timeArray.length -1) return false;
        return true;
    }
    public static function create(source:Object,identifier:String):TimeLine
    {
        var list:XMLList = describeType(source).elements('method').attribute('name');
        
        var r:RegExp = new RegExp('^' + identifier + '_([0-9]+_?[0-9]{0,3})$');
        
        var mota:Array = [];
        var xml:XML;
        var result:Array;
        for each(xml in list){
            result = r.exec(xml.toString());
            
            if(result != null){
                mota[parseFloat(result[1].replace(/_/,'.'))] = source[xml.toString()];
            }
        }
        
        var tl:TimeLine = new TimeLine(mota,source);
        return tl;
    }
}