zoukankan      html  css  js  c++  java
  • 给游戏中的模型”植入芯片“(在自定义类中加脚本扩展)

       文章若非特别注明转载,皆是原创,转载请注明出处。

      本文地址:http://www.cnblogs.com/bobolive/p/3538606.html

     在2d游戏中,模型动画一般是按帧播放的,通常我们希望我们的模型足够“智能”, 在一段动画过程里面可以精准地触发一系列事件,或做出一些调整。比如说一个模型的攻击动作是举起大刀往下砍,这里我们希望它把刀举过头顶往下砍的时候出现一刀光特效,在刀挥至胸前时砍中对方,配合特效在某处停留一两秒等等。这时就需要模型内部有“芯片”供我们预设或动态的输入指令。

      这可以做一个不依赖资源的,适用于任何有帧系列概念的自建类。这作用有点类似ActionScript 中 MovieClip的 addFrameScript, 但要它是独立的,更灵活、可扩展。

      这样,模型资源里面加上一些标签, 在Flash中是这样的:

      

      要植入的“芯片”: FrameScript

      它提供根据标签植入脚本接口 addLabelIndexScript

      

    addLabelIndexScript("attack", fillSkill, [hitId, ...]);
            /**
             * 如果FrameScript设置了labelIndex的标签映射字典, 则可以根据标签来执行script
             * @param label_ script执行的标签
             * @param callback_ 具体的script
             * @param param_ script 的参数
             * @param once_ 为true时,执行一次会清除,默认为true
             * 
             */        
            public function addLabelIndexScript(label_:String, callback_:Function,
                                                param_:Object=null, once_:Boolean=true):void
            {
                var frame_:int= _excuteIndex;
                if(!_hasSetLabel)
                {
                    _preLabelDic[label_] = {call:callback_, param:param_, once:once_};
                }
                else
                {
                    if(_labelIndexDic.hasOwnProperty(label_)) {
                        frame_ = int(_labelIndexDic[label_]);
                    }
                    addFrameScript(frame_, callback_, param_, once_);
                    _preLabelDic[frame_] = {call:callback_, param:param_, once:once_};
                }
            }
    
            /**
             * 增加一个script 
             * @param frame_ 执行的计数值
             * @param callback_ 
             * @param param_
             * @param once_ 为true时,执行一次会清除,默认为true
             */        
            public function addFrameScript(frame_:int, callback_:Function, param_:Object=null, once_:Boolean=true):void
            {
                var callbacks_:Array = [];
                var frameStr_:String = frame_.toString();
                if(_frameScriptDic.hasOwnProperty(frameStr_))
                {
                    callbacks_ = _frameScriptDic[frameStr_] as Array;
                }
                else
                {
                    callbacks_ = _frameScriptDic[frameStr_] = [];
                }
                callbacks_.push({call:callback_, param:param_, once:once_});
            }

       这里还应该可以接受即时插入的脚本。

            /**
             * 增加从当前计数往前的计数的script 
             * @param forwardFrame_ 从当前计数起多少个计数后执行
             * @param callback_ 具体的script
             * @param param_ script 的参数
             * @param once_ 为true时,执行一次会清除,默认为true
             */        
            public function addForwardFrameScript(forwardFrame_:int, callback_:Function,
                                                  param_:Object=null, once_:Boolean=true):void
            {
                var frame_:int = forwardFrame_ + _excuteIndex;
                addFrameScript(frame_, callback_, param_, once_);
            }

      插入的脚本由自定义的帧数来触发。

    frameScript.excuteIndex++;//帧计数完全自控制
            /**
             * 更新FrameScript的计数 
             * @param value_ value_为0时表示清除FrameScript
             * 当value_大于当前计数时,会从当前计数开始执行(value_ - excuteIndex)次
             * 并把excuteIndex 赋值为 value_
             */        
            public function set excuteIndex(value_:int):void
            {
                if(!value_) 
                {
                    clear();
                }
                else
                {
                    var dis:int = value_ - _excuteIndex;
                    while(dis)
                    {
                        step();
                        dis--;
                    }
                }
            }
            
            /**
             * 执行下一次计数的script 
             * 同时excuteIndex 加 1
             */        
            private function step():void
            {
                excuteFrameScript(_excuteIndex);
                _excuteIndex++;
            }

      这里如果要实现加速机制,改成:

    frameScript.excuteIndex += multiple;//multiple 是倍数

      完整代码:

    package utils.display
    {
        import events.CacheEvent;
        
        import flash.display.Bitmap;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.geom.Point;
        import flash.utils.Dictionary;
        import flash.utils.getTimer;
        
        import modules.scene.interfaces.IRender;
        
        import tools.time.CallBack;
        import tools.time.FrameScript;
        import tools.time.TimerManage;
        
        import utils.cache.SourceCacheManage;
        import utils.consts.MovieClipDataType;
        import utils.loader.LoadLevel;
        import utils.loader.LoadType;
        import utils.loader.LoadUrlUtils;
        import utils.loader.ResourceLoaderPool;
        import utils.loader.items.DgLoaderItem;
        import utils.loader.items.GifLoaderItem;
        import utils.loader.items.NdgLoaderItem;
        import utils.render.ModelRenderManager;
        
        public class MultiBodydisplayer extends Sprite implements IRender
        {
            public var resourceKey:String;
            public var centerPoint:Point;
            public var frameScript:FrameScript;
            public var stepFrame:int;
            private var _needLoadNum:int;
            private var _resourceDic:Dictionary;
            private var _bitmapDic:Array;
            private var _displayIndexs:Array;
            
            private var _currentLabel:String;
            private var _loopDic:Dictionary;
            private var _delay:int;
            private var _currentIndex:int;
            private var _scaleX:int;
            private var _mainHeight:int;
            private var _mainWidth:int;
            private var _everyStep:Boolean;
            private var _bitmapNum:int;
            public function MultiBodydisplayer()
            {
                frameScript = new FrameScript;
                _bitmapNum = 0;
            }
            
            public function set everyStep(value_:Boolean):void
            {
                _everyStep = value_;
                ModelRenderManager.getInstance().remove(this);
                
                ModelRenderManager.getInstance().add(this, _everyStep);
            }
            
            public function getPostion(centerPoint_:Point):Point
            {
                if(!centerPoint)
                {
                    centerPoint = centerPoint_;
                    this.x = (scaleX == 1) ? -centerPoint.x : centerPoint.x;// - (-1*scaleX)*
                    this.y = -centerPoint.y;
                }
                
                return new Point(centerPoint.x - centerPoint_.x, centerPoint.y - centerPoint_.y);
            }
            
            private function setBodyXY(x_:Number, y_:Number):void
            {
                if(!centerPoint)
                {
                    this.x = (scaleX == 1) ? -x_ : x_;// - (-1*scaleX)*
                    this.y = -y_;
                    centerPoint = new Point(x_, y_);
                }
            }
            
            private function clearResourceDic():void
            {
                for (var url_:String in _resourceDic)
                {
                    SourceCacheManage.getInstance().resBack(url_);
                }
                _resourceDic = new Dictionary;
                ModelRenderManager.getInstance().remove(this);
            }
            
            public function setResourceUrls(urls_:Array, LoadLevel_:int=LoadLevel.LOW):Boolean
            {
                var hasResource:Boolean = false;
                
                _needLoadNum = 0;//urls_.length;
                clearResourceDic();
                var loaderItem:NdgLoaderItem;
                for each(var url:String in urls_)
                {
                    _needLoadNum++;
                    _resourceDic[url] = null;
                    if(LoadUrlUtils.getType(url) == LoadType.NDG_TYPE)
                    {
                        loaderItem = new NdgLoaderItem(url, LoadLevel_, true, loadCompletedHandler, url);
                        hasResource = ResourceLoaderPool.getInstance().loadResourceByItem(loaderItem, true) || hasResource;
                    }
                    else if(LoadUrlUtils.getType(url) == LoadType.GIF_TYPE)
                    {
                        var gifItem:GifLoaderItem = new GifLoaderItem(url, LoadLevel_, true, loadCompletedHandler, url);
                        hasResource = ResourceLoaderPool.getInstance().loadResourceByItem(gifItem, true) || hasResource;
                    }
                    else if(LoadUrlUtils.getType(url) == LoadType.DG_TYPE)
                    {
                        var dgLoaderItem:DgLoaderItem = new DgLoaderItem(url, LoadLevel_, true, loadCompletedHandler, url);
                        hasResource = ResourceLoaderPool.getInstance().loadResourceByItem(dgLoaderItem, true) || hasResource;
                        dgLoaderItem = null;
                    }
                }
                loaderItem = null;
                
                return hasResource;
            }
            
            private function loadCompletedHandler(content_:MovieClipData, url:String):void
            {
                if(!_resourceDic.hasOwnProperty(url)) return;
                
                _resourceDic[url] = content_;
                _needLoadNum--;
            }
            
            public function set delay(value_:int):void
            {
                _delay = value_;
            }
            
            /**
             * 得到一张已经摆放好层次的位图
             */        
            public function getBitmapByIndex(type_:Object, index_:Object):Bitmap
            {
                var index:int = int(index_);
                
                var bitmap:Bitmap;
                if(!_bitmapDic) _bitmapDic = [];
                if(null != _bitmapDic[type_]) bitmap = _bitmapDic[type_] as Bitmap;
                else bitmap = _bitmapDic[type_] = new Bitmap;
                
                appendNewBitmap(index, bitmap);
                
                return bitmap;
            }
            
            public function appendNewBitmap(index_:int, bitmap_:Bitmap):void
            {
                if(!_displayIndexs) _displayIndexs = [];
                if(_displayIndexs.indexOf(index_) == -1) 
                {
                    var hasAdd_:Boolean = contains(bitmap_);
                    if(hasAdd_)
                    {
                        var oIndex_:int = getChildIndex(bitmap_);
                        if(_displayIndexs.length > oIndex_ && _displayIndexs.length == _bitmapNum) _displayIndexs.splice(oIndex_, 1);
                    }
                    
                    _displayIndexs.push(index_);
                    _displayIndexs.sort(Array.NUMERIC);
                    var index:int = _displayIndexs.indexOf(index_);
                    
                    if(!hasAdd_)
                    {
                        _bitmapNum ++;
                        addChildAt(bitmap_, index);
                    }
                    else if(oIndex_ != index)
                    {
                        setChildIndex(bitmap_, index);
                    }
                }
            }
            
            public function isCopy():Boolean
            {
                for each(var data:MovieClipData in _resourceDic)
                {
                    if(!data) continue;
                    if(null == data.labelDic[_currentLabel])
                    {
                        var reLabel:String = _currentLabel.substr(0,2) + "6";
                        if(null != data.labelDic[reLabel]) _currentLabel = reLabel;
                    }
                    var frame:BitmapFrame = data.getFrame(_currentLabel, frameScript.excuteIndex);
                    if(frame)
                    {
                        return frame.isCopy;
                    }
                }
                return true;
            }
            
            public function step():void
            {
    //            if(resourceKey == "10148")
    //                trace("catch");
    //            trace(TimerManage.currentFrame + " enter multiBody time dis is " + (getTimer() - TimerManage.frameStartTime));
                var isRender:Boolean = false;
                var needStop:Boolean = false;
                for each(var data:MovieClipData in _resourceDic)
                {
                    if(!data) continue;
                    if(null == data.labelDic[_currentLabel])
                    {
                        var reLabel:String = _currentLabel.substr(0,2) + "6";
                        if(null != data.labelDic[reLabel]) _currentLabel = reLabel;
                    }
                    var frame:BitmapFrame = data.getFrame(_currentLabel, frameScript.excuteIndex);
                    if(frame)
                    {
                        var bitmap:Bitmap = getBitmapByIndex(data.type, frame.index);
                        if(scaleX != _scaleX) scaleX = _scaleX;
                        
                        if(!frame.isCopy)
                        {
                            setBodyXY(frame.rx, frame.ry);
                            bitmap.x = centerPoint.x - frame.rx;
                            bitmap.y = centerPoint.y - frame.ry;
                            
                            bitmap.bitmapData = frame.bitmapData;
                        }
                        
                        isRender = true;
                        
                        if(data.type == MovieClipDataType.BODY)
                        {
                            _mainHeight = bitmap.height;
                            _mainWidth  = bitmap.width;
                            if(frameScript.excuteIndex == 0) frameScript.setLabelIndexDic(data.labelDic);
                            if(frame.isLastFrame) needStop = checkLoopEnd();
                        }
                    }
                }
                _currentIndex++;
                if(isRender) {frameScript.excuteIndex++;}
                if(needStop) {stop();}
    //            trace(TimerManage.currentFrame + " end multiBody time dis is " + (getTimer() - TimerManage.frameStartTime));
            }
            
            public function imitateStep(isCopy_:Boolean):void
            {
                _currentIndex++;
                if(isCopy_) {frameScript.excuteIndex++;}
            }
            
            private var _startT:Number;
            public function play(label_:String, scale_:Number, delay_:int):void
            {
                _startT = getTimer();
                clearBitmapData();
                frameScript.excuteIndex = _currentIndex = 0;
                _currentLabel = label_;//ModelConst.formatFrame(label_);
                delay = delay_;
                _scaleX = scale_;
                playBack();
            }
            
            public function playBack():void
            {
                ModelRenderManager.getInstance().add(this, _everyStep);
            }
            
            public function stop():void
            {
                ModelRenderManager.getInstance().remove(this);
            }
            
            public function setLoopInfo(label_:String, loopEndFunc_:Function, loopTime_:int=1, param:Array = null):void
            {
                if(!_loopDic) _loopDic = new Dictionary;
                _loopDic[label_] =  
                    {endFunc: new CallBack(loopEndFunc_, param, true), loopTime:loopTime_};
            }
            
            private function checkLoopEnd():Boolean
            {
                if(_loopDic && _loopDic.hasOwnProperty(_currentLabel))
                {
                    var obj:Object = _loopDic[_currentLabel];
                    obj.loopTime --;
                    if(obj.loopTime <= 0) 
                    {
                        var callBack:CallBack = obj.endFunc as CallBack;
                        if(callBack) callBack.execute();
                        delete _loopDic[_currentLabel];
                        return true;
                    }
                }
                return false;
            }
            
            public function get isHit():Boolean
            {
                var pixel:Number;
                var result:Boolean = false;
                for each(var bitmap:Bitmap in _bitmapDic)
                {
                    if(contains(bitmap) && bitmap.bitmapData)
                    {
                        pixel = bitmap.bitmapData.getPixel32(bitmap.mouseX, bitmap.mouseY);
                        result = result || pixel > 0;
                    }
                }
                return result;
            }
            
            public function get mainHeight():int
            {
                return _mainHeight;
            }
            
            public function get mainWidth():int
            {
                return _mainWidth;
            }
            
            public function clearBitmapData():void
            {
                for each(var bitmap:Bitmap in _bitmapDic)
                {
                    bitmap.bitmapData = null;
                }
                _displayIndexs = [];
                centerPoint = null;
            }
            
            public function clear():void
            {
                stop();
                
                for each(var bitmap:Bitmap in _bitmapDic)
                {
                    if(contains(bitmap)) removeChild(bitmap);
                }
                
                _displayIndexs = [];
                
                centerPoint = null;
                
                _bitmapNum = 0;
            }
            
            public function dispose():void
            {
                clear();
                clearResourceDic();
                ModelRenderManager.getInstance().remove(this);
            }
        }
    }
    FrameScript
  • 相关阅读:
    jQuery 参考手册
    jQuery 参考手册
    ASP.NET框架例举
    判断checkbox是否选中
    ajax动态添加的li不能绑定click事件
    缓存代码备用
    关于ajax伪实时动态下拉显示最新数据
    JavaScript中,格式化DateTime
    jquery判断id是否存在
    SSI-Server Side Inclued
  • 原文地址:https://www.cnblogs.com/bobolive/p/3538606.html
Copyright © 2011-2022 走看看