zoukankan      html  css  js  c++  java
  • COC建筑拖动的实现

    最近在玩COC,多体验一下手游的体验,因为自己毕竟一直是做页游的,有些观念需要转变一下。

    好像偏了,玩了几次之后突然想起COC那个地图拖动的自己之前实现过,那是2010年左右的时候,模拟经营类页游大行其道的时候,我做了个类似的功能。

    核心内容应该是通过直线方程确定建筑的位置,想想那时候的自己还是干劲十足的,哪像现在,犹豫踟蹰,徘徊不前,对未来充满迷茫。

    特从旧电脑上把相关的几个类拷下来,公布于此,虽然今时今日去看,粗糙得很,有很多需要改进的地方,但是还是觉得有一些学习的意义的。

    为了填满全页,主要的类不折叠了,如下:

    package com.app.map.smallMap
    {    
        import com.app.facilities.model.FacilityModel;
        import com.app.facilities.model.vo.FacilityVO;
        import com.core.ServiceID;
        import com.core.manage.MainManager;
        import com.core.manage.MaterialUIManager;
        import com.core.manage.UIManager;
        import com.core.ui.loader.MaterialLoader;
        import com.core.utils.Tool;
        
        import flash.display.DisplayObject;
        import flash.display.Loader;
        import flash.display.MovieClip;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.filters.GlowFilter;
        import flash.geom.Point;
        import flash.geom.Rectangle;
        
        import org.ds.HashMap;
        import org.manager.RootManager;
    
        /**
         * 
         * 用来摆放建筑和设施的小地图</BR>
         * 为方便管理,请勿直接new构造器,请使用<code>getMap(key:String):SmallMap</code>方法取实例 
         * @author Ado
         * 
         */    
        public class SmallMap extends Sprite
        {
            /**
             * 安置事件类型 
             */        
            public static const SETTLE_EVENT:String = "settle_event";
            /**
             * 皮肤加载完成 
             */        
            public static const SKIN_LOADED:String = "skin_loaded";
            
            private var mc:MovieClip;
            private var _row:int = 1;
            private var _column:int = 1;
        
            private static var maps:HashMap = new HashMap();
            
            private var _building:BuildingTile;//拖动的建筑
            public var tempSkin:Skin;//拖动建筑的皮肤
            private var tempSkinIsShowed:Boolean;//临时皮肤是否已经显示
            private var loadedOver:Boolean;
            private var _mapData:Object;
            private var _buidlingData:Array = [];
            /**
             * 是否支持连续建筑
             */        
            public var isMultiSettlable:Boolean;
            //已安放的建筑列表信息
            private var _settledBuildings:Array = [];
            //已安放的建筑信息
            private var settledBuilding:Object;
            /**
             *是否是在进行固有建筑移除操作 
             */        
            public var isRemove:Boolean;
            /**
             *建筑安放的回调函数 
             */        
            public var callBack:Function;
            /**
             * 拖动参照物
             */        
            public var moveRefer:Sprite;
            
            //本地图上的皮肤数据
            public var skins:Array = [];
            private var skinLoader:MaterialLoader;
            private var needSkins:Array = [];//皮肤加载队列
            
            private var _availiableSize:Array;//可以放置的尺寸
            private var _derectorAvailiable:Boolean;//是否可以安置设施
            /**
             * 摆放建筑的小地图 
             * 
             */        
            public function SmallMap()
            {
                mc = UIManager.getMovieClip("small_map");
                mc.name="_smallMap";
                skinLoader = new MaterialLoader();
                this.addChild(mc);
            }
            /**
             * 根据传入的key值取得或者新建小地图 
             * @param key key值通常是面板的完整路径名
             * @return 
             * 
             */        
            public static function getMap(key:String):SmallMap
            {
                if(maps.containsKey(key))
                {
                    return maps.getValue(key);
                }else
                {
                    var map:SmallMap = new SmallMap();
                    maps.add(key, map);
                    return map;
                }
            }
            /**
             * 
             * @param _mapData            地图数据
             * @param buildingTile        建筑底座
             * @param _callBack            回调函数
             * @param isMultiSettlable    是否可以重复放置
             * 
             */                
            public function initMap(_mapData:Object, buildingTile:BuildingTile = null, _callBack:Function=null, isMultiSettlable:Boolean=false):void
            {
                mapData = _mapData;
                this.isMultiSettlable = isMultiSettlable;
                if(buildingTile!=null)
                {
                    building = buildingTile;
                }            
                callBack = _callBack;            
            }
            /**
             * 在小地图上拖动的事件监听器 
             * @param e
             * 
             */        
            private function startMoveHandler(e:MouseEvent = null):void
            {
                if(e!=null)
                {
                    e.stopImmediatePropagation();
                }
                _building.removeEventListener(MouseEvent.CLICK, startMoveHandler);
                moveRefer.addEventListener(MouseEvent.ROLL_OVER, bgOverHandler);
                
                moveRefer.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER));
            }
            /**
             * 背景滑过事件监听:当前建筑的事件监听,开始移动 
             * @param e
             * 
             */        
            private function bgOverHandler(e:MouseEvent):void
            {
                moveRefer.addEventListener(MouseEvent.ROLL_OUT, bgOutHandler);
                moveRefer.removeEventListener(MouseEvent.ROLL_OVER, bgOverHandler);
                
                tempSkin.startDrag(true, new Rectangle(moveRefer.x-x,  
                    moveRefer.y - y, 
                    moveRefer.width - _building.width, 
                    moveRefer.height - _building.height/2));
                RootManager.stage.addEventListener(MouseEvent.MOUSE_MOVE, checkHandler);
                moveRefer.addEventListener(MouseEvent.CLICK, positionHandler);    
            }
            /**
             * 背景滑出事件监听:移除当前建筑的所有事件,且停止移动 
             * @param e
             * 
             */        
            private function bgOutHandler(e:MouseEvent):void
            {
                moveRefer.removeEventListener(MouseEvent.ROLL_OUT, bgOutHandler);
                moveRefer.addEventListener(MouseEvent.ROLL_OVER, bgOverHandler);
                
                if(_building)
                {
                    _building.stopDrag();
                    _building.x=mc["bg"].width;
                    _building.y=mc["bg"].height;
                    tempSkin.x=mc["bg"].width;
                    tempSkin.y=mc["bg"].height;
                }
                RootManager.stage.removeEventListener(MouseEvent.MOUSE_MOVE, checkHandler);
                _building.settlable = false;
                moveRefer.stage.removeEventListener(MouseEvent.CLICK, positionHandler);
            }
            
            /**
             * 根据是否可以放置建筑而更换底座颜色<br>
             * 所有的小块坐标都是以下两个系列的线条的交点<br>
             * <li>0.5 * x + y - 87.5 = k1 * 25;</li>
             * <li>0.5 * x - y + 87.5 = k2 * 25;</li><br/>
             * 由于长宽变化公式已变化
             * k1,k2均为整数,四舍五入取值
             * k1 取值范围: 0 ~  (建筑行 - 1)
             * k2 取值范围: 0 ~  (建筑列 - 1)
             * 以下以2*2的建筑为例 取值范围0 ~ (7-2)
             * 7为小地图横竖的单元格个数
             * **/
            private function checkHandler(e:MouseEvent):void
            {
                var refX:int = 7 - building.col;
                var refY:int = 7 - building.row;
                var ny:Number = Math.round((tempSkin.x * 5 / 9 + tempSkin.y - 70) / 20);
                var nx:Number = Math.round((tempSkin.x * 5 / 9 - tempSkin.y + 70) / 20);
                
                if(nx < 0 || nx > refX || ny < 0 || ny > refY)
                {
                    _building.settlable = false;
                    _building.visible = false;
                }else if(!checkSettlable(nx+1,ny+1,_building))
                {
                    _building.settlable = false;
                    _building.visible = true;
                    tempSkin.alpha = 0.7;
                }else
                {
                    _building.settlable = true;
                    _building.visible = true;
                    tempSkin.alpha = 0.7;
                }
                //设置位置
                _building.x = (ny + nx) * 18;
                _building.y = 10 * (ny - nx  + 7);
                
                //只有建筑才需要
                if(_building.row > 1)
                {
                    _building.settleFactor = checkPoints(nx+1,ny+1);
                }            
            }
            /**
             * 检测建筑的每个点 
             * @param checkCol
             * @param checkRow
             * 
             */        
            private function checkPoints(checkCol:int, checkRow:int):Array
            {
                var a:Array = [];
                for(var i:int = 0; i < _building.row; i++)
                {
                    for(var j:int = 0; j < _building.col; j++)
                    {
                        if(checkCol + j <= 0 || checkCol + j > 7 || checkRow + i <= 0 || checkRow + i > 7 || !pointCheck(checkRow+i,checkCol+j))
                        {
                            a.push(i+"_"+j);
                        }
                    }
                }
                return a;
            }
            /**
             * 检测某点是否可以安置,你妹的,我要崩溃了 
             * @param checkCol
             * @param checkRow
             * @param point
             * @return 
             * 
             */        
            private function pointCheck(checkRow:int, checkCol:int):Boolean
            {
                var result:Boolean = true;
                var referCheck:Array = _buidlingData.concat(_settledBuildings);
                if(referCheck.length)
                {
                    for each(var i:BuildingTile in referCheck)
                    {
                        if(i.row == 1)
                        {
                            if(i.buildingData.unit_col0 == checkCol && i.buildingData.unit_row0 == checkRow)
                            {
                                result = false;
                                break;
                            }
                        }else
                        {
                            if(i.buildingData.unit_col1+1 > checkCol && checkCol >= i.buildingData.unit_col0 - 1 &&
                                i.buildingData.unit_row1+1 > checkRow && checkRow >= i.buildingData.unit_row0 - 1)
                            {
                                result = false;
                                break;
                            }
                        }
                    }
                }else
                {
                    result = true;
                }
                return result;
            }
            /**
             * 检测是否可以安放 
             * @param checkCol     接受检测的行
             * @param checkRow     接受检测的列
             * @param bld         接受检测的BuildingTile
             * @return 
             * 
             */        
            private function checkSettlable(checkCol:int, checkRow:int, bld:BuildingTile):Boolean
            {
                var result:Boolean = true;
                var referCheck:Array = _buidlingData.concat(_settledBuildings);
                if(referCheck.length)
                {
                    for each(var i:BuildingTile in referCheck)
                    {    
                        if(bld.buildingData.referCol == 1)//设施摆放
                        {
                            if(!(i.buildingData.unit_col1 <= checkCol || i.buildingData.unit_row1 <= checkRow || 
                                i.buildingData.unit_col0 >= checkCol+bld.buildingData.referCol || 
                                i.buildingData.unit_row0 >= checkRow+bld.buildingData.referRow))
                            {
                                result = false;
                                break;
                            }
                        }else
                        {
                            if(i.row == 1)
                            {
                                if(!(i.buildingData.unit_col1 <= checkCol || i.buildingData.unit_row1 <= checkRow || 
                                    i.buildingData.unit_col0 >= checkCol+bld.buildingData.referCol || 
                                    i.buildingData.unit_row0 >= checkRow+bld.buildingData.referRow))
                                {
                                    result = false;
                                    break;
                                }
                            }else
                            {
                                if(!(i.buildingData.unit_col1+1 <= checkCol || i.buildingData.unit_row1+1 <= checkRow || 
                                    i.buildingData.unit_col0 >= checkCol+bld.buildingData.referCol+1 || 
                                    i.buildingData.unit_row0 >= checkRow+bld.buildingData.referRow+1))
                                {
                                    result = false;
                                    break;
                                }
                            }
                        }
                    }
                }else
                {
                    result = true;
                }
                return result;
            }
            /**
             * 安放建筑或者设施 
             * @param e
             * 
             */        
            private function positionHandler(e:MouseEvent):void
            {
    //            e.stopImmediatePropagation();
                if(_building.settlable)
                {
                    var ny:Number = Math.round((building.x * 5 / 9 + building.y - 70) / 20);
                    var nx:Number = Math.round((building.x * 5 / 9 - building.y + 70) / 20);
    
                    var tempX:Number = (ny + nx) * 18;
                    var tempY:Number = 10 * (ny - nx  + 7);
                    tempSkin.stopDrag();
                    moveRefer.removeEventListener(MouseEvent.CLICK, positionHandler);
                    RootManager.stage.removeEventListener(MouseEvent.MOUSE_MOVE, checkHandler);
                    moveRefer.removeEventListener(MouseEvent.ROLL_OVER, bgOverHandler);
                    moveRefer.removeEventListener(MouseEvent.ROLL_OUT, bgOutHandler);
                    _building.y = tempY;
                    _building.x = tempX;
    //                _building.alpha = 0.2;    
                    
                    building.buildingData.unit_col0 = nx + 1;
                    building.buildingData.unit_row0 = ny + 1;
                    building.buildingData.unit_col1 = building.buildingData.unit_col0 + building.col;
                    building.buildingData.unit_row1 = building.buildingData.unit_row0 + building.row;
                    
                    //安置皮肤数据
                    tempSkin.alpha = 1;
                    tempSkin.x = tempX;
                    tempSkin.y = tempY;
                    tempSkin.depth = _building.n;
                    
                    editModel = true;
                    
                    if(isMultiSettlable)
                    {
                        _settledBuildings.push(building);
                        tempSkin.addEventListener(MouseEvent.ROLL_OVER, skinOverHandler);
                        this._building = null;
                    }else if(callBack != null)
                    {
                        callBack();
                    }
                    //更新皮肤,重新排列皮肤
                    skins.push(tempSkin);
                    skins.sortOn("depth");
                    
                    for(var i:int = 0; i < skins.length; i++)
                    {
                        mc.addChild(skins[i]);
                    }
                    this.dispatchEvent(new Event(SETTLE_EVENT));
                }else
                {
                    tempSkin.startDrag(true, new Rectangle(moveRefer.x-x,  
                        moveRefer.y - y, 
                        moveRefer.width - _building.width,  
                        moveRefer.height - _building.height/2));
                }
            }
            /**
             * 皮肤鼠标滑过事件处理 
             * @param e
             * 
             */        
            private function skinOverHandler(e:MouseEvent):void
            {
                e.target.filters = [new GlowFilter(0xff0000,0.8)];
                e.target.addEventListener(MouseEvent.ROLL_OUT, skinOutHandler);
                e.target.removeEventListener(MouseEvent.ROLL_OVER, skinOverHandler);
            }
            /**
             * 皮肤鼠标滑出事件处理 
             * @param e
             * 
             */        
            private function skinOutHandler(e:MouseEvent):void
            {
                e.target.filters = [];
                e.target.removeEventListener(MouseEvent.ROLL_OUT, skinOutHandler);
                e.target.addEventListener(MouseEvent.ROLL_OVER, skinOverHandler);
            }
            
            
            //取得皮肤:队列形式
            private function getSkins():void
            {
                if(needSkins.length)
                {
                    skinLoader.getSwf(needSkins[0],needSkins[0]);
                    needSkins.shift();
                    if(skinLoader)
                    {
                        skinLoader.setCompleteFunc = function(e:Event):void
                        {
                            getSkins();
                        }
                    }                
                }else
                {
                    loadedOver = true;
                    skinLoader.setCompleteFunc = null;
                    displaySkins();
                }
            }
            /**
             * 显示皮肤数据 
             */        
            private function displaySkins():void
            {
                for each(var i:BuildingTile in _buidlingData)
                {
                    var skin:Skin;//此处要实现对缓存数据的重用
                    if(i.iconSource)
                    {
                        skin = new Skin(i.iconSource);
                        skin.depth = i.depth;
                        skin.firstSort = i.buildingData.firstSort;
                        skin.id = i.buildingData.id;
                        skin.x = i.x;
                        skin.y = i.y;
                        skins.push(skin);
                        i.visible = false;
                    }
                }
                skins.sortOn(["firstSort", "depth"], Array.NUMERIC);
                if(_building && tempSkin && !tempSkinIsShowed)
                {
                    tempSkin.srcUrl = _building.iconSource;
                    tempSkinIsShowed = true;
                }
                
                for each(var j:Skin in skins)
                {
                    mc.addChild(j);
                    j.visible = true;
                }
                dispatchEvent(new Event(SKIN_LOADED));
            }
            /**
             * 根据皮肤取建筑块 ,由于临时建筑无id
             * @param s Skin
             * @return 
             * 
             */        
            public function getTileBySkin(s:Skin):BuildingTile
            {
                var tile:BuildingTile;
                for each(var i:BuildingTile in _settledBuildings)
                {
                    if(i.x == s.x && i.y == s.y)
                    {
                        tile = i;
                        break;
                    }
                }
                return tile;
            }
            /**
             * 移除设施 
             * @param buildingData
             * 
             */        
            public function removeBuildingTile(buildingData:Object):void
            {
                for each(var i:BuildingTile in _settledBuildings)
                {
                    if(i.buildingData.unit_col0 == buildingData.unit_col0 && i.buildingData.unit_row0 == buildingData.unit_row0)
                    {
                        mc.removeChild(i);
                        _settledBuildings.splice(_settledBuildings.indexOf(i),1);
                        for each(var j:Skin in skins)
                        {
                            if(j.x == i.x && j.y == i.y)
                            {
                                mc.removeChild(j); 
                                i.graphics.clear();
                                j.removeEventListener(MouseEvent.ROLL_OUT, skinOutHandler);
                                j.removeEventListener(MouseEvent.ROLL_OVER, skinOverHandler);
                                skins.splice(skins.indexOf(j),1);
                                break;
                            }
                        }
                        i.graphics.clear();
                        this.dispatchEvent(new Event(SETTLE_EVENT));
                        return;
                    }
                }
            }
            /**
             * 计算可容纳的尺寸 
             * 
             */        
            private function cauculateMaxSize():void
            {
                var reference:Array = [
                    "2*2","2*3","3*2","3*3",
                    "3*4","4*3","3*5","5*3",
                    "4*4","4*5","5*4","4*6",
                    "4*7","7*4","5*7","7*5",
                    "6*4","5*5","5*6","6*5",
                    "6*6","6*7","7*6","7*7",];
                _availiableSize = [];
                
                if(_buidlingData.length==0)
                {
                    _availiableSize = reference;
                    _derectorAvailiable = true;
                    return;
                }
                
                var referTile:BuildingTile = new BuildingTile(null,true);
                for(var i:int=0; i < reference.length; i++)
                {                        
                    var temp:Array = reference[i].split("*");
                    referTile.buildingData = {referRow:int(temp[0]), referCol:int(temp[1]), type:1, layer:1};
                    var limit:int = (7 - referTile.buildingData.referRow) * 7 + (7 - referTile.buildingData.referCol) + 1;
                    for(var n1:int =1; n1 <= limit; n1++)
                    {
                        var referC:int = (n1%7 == 0 ? 7 : n1%7);
                        var referR:int = Math.ceil(n1/7);
                        if(referC + referTile.col <= 8 && referR + referTile.row <= 8 && checkSettlable(referC,referR,referTile))
                        {
                            _availiableSize.push(reference[i]);
                            break;
                        }
                    }    
                }
                
                var num:int = 0;
                for each(var j:BuildingTile in _buidlingData)
                {
                    num += j.row * j.col;
                }
                if(num >= 49)
                {
                    _derectorAvailiable = false;
                }else
                {
                    _derectorAvailiable = true;
                }
            }
            /**
             * 根据id取建筑块 
             * @param id
             * @return 
             * 
             */        
            public function getTileByDepth(d:int):BuildingTile
            {
                var tile:BuildingTile;
                for each(var i:BuildingTile in _buidlingData)
                {
                    if(i.depth == d)
                    {
                        tile = i;
                        break;
                    }
                }
                return tile;
            }
            /**
             * 根据id取皮肤 
             * @param s
             * 
             */        
            public function getSkinByDepth(d:int):Skin
            {
                var s:Skin;
                for each(var i:Skin in skins)
                {
                    if(i.depth == d)
                    {
                        s = i;
                        break;
                    }
                }
                return s;
            }
            /**
             * 显示指定类型的皮肤 
             * @param type
             * 
             */        
            public function showSpecifiedSkin(type:int):void
            {
                for each(var i:BuildingTile in _buidlingData)
                {
                    if(i.buildingData is FacilityVO)
                    {
                        if(i.buildingData.type == type)
                        {
                            getSkinByDepth(i.depth).visible = true;
                            getTileByDepth(i.depth).visible = false;
                        }else
                        {
                            getSkinByDepth(i.depth).visible = false;
                            getTileByDepth(i.depth).visible = true;
                            getTileByDepth(i.depth).alpha = 0.2;
                        }                    
                    }
                }
            }
            /**
             * 更新需要安置的建筑的数据 
             * @param data
             * 
             */        
            public function updateBuildingData(data:Object):void
            {
                var needSkinUpdated:Boolean = false;
                editModel = false;
                
                if(_building.buildingData.referRow > 1)
                {
                    needSkinUpdated = data.layer != _building.buildingData.layer || data.referRow != _building.buildingData.referRow || data.referCol != _building.buildingData.referCol;
                }
                
                if(_building.buildingData.type != data.type || needSkinUpdated)
                {
                    _building.buildingData = data;
                    if(tempSkin && _building.iconSource != tempSkin.srcUrl)
                    {
                        if(MaterialUIManager.contains(_building.iconSource))
                        {
                            tempSkin.srcUrl = _building.iconSource;
                        }else
                        {
                            skinLoader.getSwf(_building.iconSource,_building.iconSource);
                            skinLoader.setCompleteFunc = loadComplete;
    //                            function(e:Event):void
    //                        {
    //                            tempSkin.srcUrl = _building.iconSource;
    //                        }
                        }    
                    }
                }
                if(skins.indexOf(tempSkin) >= 0)
                {
                    skins.splice(tempSkin);
                }
                startMoveHandler();
    //            tempSkin.alpha = 0.7;
    //            _building.alpha = 1;
            }
            /**
             * 取得当前地图可安放的最大尺寸 
             * @return 
             * 
             */        
            public function get availiableSize():Array
            {
                return _availiableSize;
            }
            /**
             * 设置地图上店铺皮肤显示与否
             * @param flag
             * 
             */        
            public function setShopSkinVisible(flag:Boolean):void
            {
                for each(var i:BuildingTile in _buidlingData)
                {
                    if(i.row > 1)
                    {
                        getSkinByDepth(i.depth).visible = flag;
                        i.visible = !flag;
                        i.alpha = 0.7;
                    }
                }
            }
            /**
             * 设置地图上所有皮肤的可显示与否 
             * @param vis
             * 
             */        
            public function setSkinVisible(vis:Boolean,_id:int=0):void
            {
                for each(var i:BuildingTile in _buidlingData)
                {
                    if(i.buildingData.id!=_id || i.buildingData is FacilityVO)
                    {
                        getSkinByDepth(i.depth).visible = vis;
                        i.visible = !vis;
                        i.alpha = 0.7;
                    }
                        
                }
            }
            /**
             * 清空地图上的信息 
             * 循环方法待修改,修改依据:旧数据的重用
             */        
            public function cleanMap():void
            {
                //清理皮肤数据
                for each(var j:Skin in skins)
                {
                    if(mc.contains(j))
                    {
                        j.recycle();
                        mc.removeChild(j);
                    }
                    j.removeEventListener(MouseEvent.ROLL_OUT, skinOutHandler);
                    j.removeEventListener(MouseEvent.ROLL_OVER, skinOverHandler);
                }
                skins = [];
                
                //清理已有店铺设施
                for each(var i:BuildingTile in _buidlingData)
                {
                    i.recycle();
                    if(mc.contains(i))
                    {
                        mc.removeChild(i);
                    }        
                }
                _buidlingData = [];
                //清理展示摆放的店铺设施
                for each(i in _settledBuildings)
                {
                    if(mc.contains(i))
                    {
                        mc.removeChild(i);
                    }    
                }
                _settledBuildings = [];
                    
                //清理临时建筑
                if(_building != null && mc.contains(_building))
                {
                    if(mc.contains(_building))    mc.removeChild(_building);
                    if(mc.contains(tempSkin))
                    {
                        mc.removeChild(tempSkin);
                        tempSkin.recycle();
                    }
                    tempSkin.stopDrag();
                    _building = null;
                    tempSkin = null;
                }
                RootManager.stage.removeEventListener(MouseEvent.MOUSE_MOVE, checkHandler);
                
                if(moveRefer)
                {
                    moveRefer.removeEventListener(MouseEvent.CLICK, positionHandler);
                    moveRefer.removeEventListener(MouseEvent.ROLL_OUT, bgOutHandler);
                    moveRefer.removeEventListener(MouseEvent.ROLL_OVER, bgOverHandler);
                }            
            }        
            /**
             * 将待建设施转换成已建设施
             * */
            public function doTransform(id:int):void
            {
                for each(var i:BuildingTile in settledBuildings)
                {
                    if(i.buildingData.id == id)
                    {
                        settledBuildings.splice(settledBuildings.indexOf(i),1);
                        buidlingData.push(i);
                    }
                }
            }
            /**
             * 获取建筑花费 
             * @return 
             */        
            public function getCost():Number
            {
                var cost:Number = 0;
                for each(var i:BuildingTile in settledBuildings)
                {
                    cost += int(i.buildingData.price);
                }
                return cost;
            }
            /**
             * 获取设施加成 
             * @return 
             * 
             */        
            public function getBouns():Number
            {
                var bouns:Number = 0;
                for each(var i:BuildingTile in settledBuildings)
                {
                    bouns += int(i.buildingData.value);
                }
                return bouns;
            }
            /**
             * @param child 外部向小地图上添加子显示对象 
             * @param child
             */            
            public function addChildToMap(child:DisplayObject):void
            {
                mc.addChild(child);
                child.x = mc.mouseX;
                child.y = mc.mouseY;
            }
            /**
             * 从小地图上移除子显示对象 
             * @param child
             */        
            public function removeChildFromMap(child:DisplayObject):void
            {
                if(mc.contains(child))
                {
                    mc.removeChild(child);
                    if(child is Skin && skins.indexOf(child) > -1)
                    {
                        skins.splice(skins.indexOf(child),1);
                    }else if(child is BuildingTile && _buidlingData.indexOf(child) > -1)
                    {
                        _buidlingData.splice(_buidlingData.indexOf(child),1);
                    }
                }
            }
            /**
             * 地图固有的建筑信息
             * */
            public function set buidlingData(value:Array):void
            {
                cleanMap();
                _buidlingData = value;
                
                for each(var i:BuildingTile in value)
                {
                    i.x = (i.buildingData.unit_col0 + i.buildingData.unit_row0 - 2) * BuildingTile.unitWidth / 2;
                    i.y = (i.buildingData.unit_row0 - i.buildingData.unit_col0 + 7 ) * BuildingTile.unitHeight / 2;
                    mc.addChild(i);
                    i.visible = false;
                    i.settlable = true;
                    if(i.iconSource && needSkins.indexOf(i.iconSource) == -1 && !MaterialUIManager.contains(i.iconSource))
                    {
                        needSkins.push(i.iconSource);
                    }
                }
                
                cauculateMaxSize();
                
                if(needSkins.length)
                {
                    getSkins();
                }else
                {
                    displaySkins();
                    loadedOver = true;
                }
            }
            /**
             * 地图建筑数据
             * */
            public function get buidlingData():Array
            {
                return _buidlingData;
            }
            
            /**
             * 地图上安置的建筑或者设施 
             * @return 
             * 
             */        
            public function get settledBuildings():Array
            {
                return _settledBuildings;
            }
            /**
             * 
             * @param value 建筑数据,待建造的建筑,其中必须包含建筑素材地址和建筑尺寸例如(2*2,1*1)
             * 
             */        
            public function set building(value:BuildingTile):void
            {
                if(value)
                {
                    editModel = false;
                    _building = value;
                    _row = value.buildingData.row;
                    _column = value.buildingData.col;
                    
                    _building.x = mc["bg"].x + (mc["bg"].width - _building.width);
                    _building.y = mc["bg"].y + (mc["bg"].height - _building.height);
                    mc.addChild(building);
                    tempSkin = new Skin();
                    
                    
                    if(MaterialUIManager.contains(_building.iconSource))
                    {
                        tempSkin.srcUrl = _building.iconSource;
                    }else
                    {
                        if(!loadedOver && needSkins.indexOf(_building.iconSource) == -1)
                        {
                            needSkins.push(_building.iconSource);
                            tempSkinIsShowed = false;
                        }else
                        {
                            skinLoader.getSwf(_building.iconSource,_building.iconSource);
                            skinLoader.setCompleteFunc = loadComplete;
                        }                    
                    }        
                    mc.addChild(tempSkin);
                    startMoveHandler();
                    tempSkin.x = _building.x;
                    tempSkin.y = _building.y;
                }else
                {
                    editModel = true;
                    if(_building != null && mc.contains(_building))
                    {
                        mc.removeChild(_building);
                        _building.stopDrag();
                        _building.removeEventListener(MouseEvent.CLICK, startMoveHandler);
                        moveRefer.removeEventListener(MouseEvent.ROLL_OUT, bgOutHandler);
                        moveRefer.removeEventListener(MouseEvent.ROLL_OVER, bgOverHandler);
                    }
                    
                    if(tempSkin && mc.contains(tempSkin))
                    {
                        mc.removeChild(tempSkin);
                    }
                    RootManager.stage.removeEventListener(MouseEvent.MOUSE_MOVE, checkHandler);
                    moveRefer.removeEventListener(MouseEvent.CLICK, positionHandler);
                    _building = null;
                }
            }
            private function loadComplete(e:Event):void
            {
                try
                {
                    tempSkin.srcUrl = _building.iconSource;
                }catch(e:Error)
                {
                    trace("加载出错");
                }finally
                {
                    
                }
            }
            /**
             * 设置是否是编辑模式 :
             * true 编辑模式下地图接收鼠标事件
             * false 非编辑模式下不接收鼠标事件
             * @param value
             * 
             */        
            public function set editModel(value:Boolean):void
            {
                this.mouseEnabled = value;
                this.mouseChildren = value;
            }
            /**
             * 选中的建筑 
             * @return 
             * 
             */        
            public function get building():BuildingTile
            {
                return _building;
            }
            /**
             * 地图数据 
             * @return 
             * 
             */        
            public function get mapData():Object
            {
                return _mapData;
            }
            /**
             * 
             * @param value 地图数据,包括地图上已经建造好了的建筑数据
             * 
             */        
            public function set mapData(value:Object):void
            {
                _mapData = value;
            }
    
            public function get derectorAvailiable():Boolean
            {
                return _derectorAvailiable;
            }
    
        }
    }

    其他几个相关的类:

    package com.app.map.smallMap
    {
        import com.app.facilities.controller.FacilityController;
        import com.app.facilities.model.pool.FacilityPool;
        import com.app.facilities.model.vo.FacilityVO;
        import com.app.shop.model.vo.ShopVO;
        import com.core.info.DoMainInfo;
        
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.geom.Matrix;
        import flash.text.TextField;
        import flash.text.TextFormat;
        import flash.text.TextFormatAlign;
        
        import org.ds.HashMap;
    
        /**
         * 在小地图上摆放的菱形小方块
         * @author Ado
         * 
         */    
        public class BuildingTile extends Sprite
        {
            /**
             * 建筑皮肤所存位置前缀 
             */        
            public static const BUILD_URL:String = "swf/build/";
            /**
             * 设施皮肤所存位置前缀 
             */        
            public static const FACIL_URL:String = "swf/decorator/";
            /**
             * 店铺皮肤所存位置前缀 
             */        
            public static const SHOP_URL:String = "swf/shop/";
            /**
             * 是否是模拟的:<br/>
             * 是模拟的的话不用进行绘制<br/>
             * 是真实的的话要进行绘制 
             */        
            private var isSimulate:Boolean = false;;
            public static const unitWidth:Number = 36;//单位长度
            public static const unitHeight:Number = 20;//单位高度
            
            private var _settlable:Boolean;
            private var _buildingData:Object;
            public var row:int;
            public var col:int;
            
            private var _n:int = 1;
            
            public var iconSource:String;
            
            private var tiles:HashMap = new HashMap();
            /**
             *  
             * @param data 建筑数据
             * @param isSimulate 是否是模拟的建筑
             * 
             */        
            public function BuildingTile(data:Object=null,_isSimulate:Boolean=false)
            {
                isSimulate = _isSimulate;
                buttonMode = true;
                if(data == null) return;
                buildingData = data;
            }
            
            private function initTiles():void
            {
                graphics.clear();
                var t:int = col > 1 ? 2 : 1;
                
                tiles.eachKey(function(s:String):void{
                    trace(s);
                    removeChild(tiles.getValue(s));
                    tiles.remove(s);
                });
                for(var i:int = 0; i < row; i++)
                {
                    for(var j:int = 0; j < col; j++)
                    {
                        var tile:Unit;
                        if(tiles.containsKey(i+"_"+j))
                        {
                            tile = tiles.getValue(i+"_"+j);
                        }else
                        {
                            tile = new Unit(t);
                        }                     
                        tile.x = (j + i) * unitWidth /2;
                        tile.y = (i - j) * unitHeight/2;
                        tile.setteld = buildingData is ShopVO || buildingData is FacilityVO;
                        addChild(tile);
                        tiles.add(i+"_"+j,tile);
                    }
                }
            }
            
            private function updateBase():void
            {
                tiles.eachKey(function(s:String):void{
                    (tiles.getValue(s) as Unit).settlable = _settlable;
                });
            }
            /**
             * 是否可以安置,鼠标拖动的时候为true 
             * @return 
             * 
             */        
            public function get settlable():Boolean
            {
                return _settlable;
            }
    
            public function set settlable(value:Boolean):void
            {
                _settlable = value;
                if(row == 1)//店铺和建筑不一样
                {
                    updateBase();
                }            
            }
            /**
             * 不合适的点Array 
             * @param factor
             * 
             */        
            public function set settleFactor(factor:Array):void
            {
                tiles.eachKey(function(k:String):void
                {
                    if(factor.indexOf(k) > -1)
                    {
                        (tiles.getValue(k) as Unit).settlable = false;
                    }else
                    {
                        (tiles.getValue(k) as Unit).settlable = true;
                    }
                });
            }
    
            public function get buildingData():Object
            {
                return _buildingData;
            }
    
            /**
             * 回收 
             * 
             */        
            public function recycle():void
            {
                tiles.eachKey(function(k:String):void
                {
                    removeChild(tiles.getValue(k) as Unit);
                    tiles.remove(k);
                });
            }
            /**
             * 摄入建筑(包括店铺和设施)信息 
             * @param value
             * 
             */        
            public function set buildingData(value:Object):void
            {
                _buildingData = value;
                if(value.hasOwnProperty("referRow"))
                {
                    row = value["referRow"];
                    col = value["referCol"];
                }else
                {
                    n = _buildingData.n;
                }
                if((_buildingData is FacilityVO) || (row == 1 && col == 1))
                {
                    iconSource = DoMainInfo.assetsUrl + FACIL_URL + FacilityPool.SystemFacility[_buildingData.type-1]["icon"];
                }else if(_buildingData)
                {
                    iconSource = DoMainInfo.assetsUrl + SHOP_URL + ShopVO.getFolder(_buildingData.type) + row + "_" + col + "_" + _buildingData.layer +".swf";
                }
                if(!isSimulate) initTiles();
    //            settlable = false;
            }
            /**
             * 获取深度 
             * @return 
             * 计算方式 行*10 + (7 - 列)
             * 原理,行大者排前,列小者排前
             */        
            public function get depth():Number
            {
                return (_buildingData.unit_row0 * 10 + (7 - _buildingData.unit_col0));
            }
            
            public function get n():int
            {
                return (_buildingData.unit_row0 - 1) * 7 + _buildingData.unit_col0;
            }
            
            public function set n(value:int):void
            {
                _n = value;
                
                if(_n%7 == 0)
                {
                    _buildingData.unit_col0 = 7;
                }else
                {
                    _buildingData.unit_col0 = _n%7;
                }
                _buildingData.unit_row0 = Math.ceil(_n/7);
                        
                if(_buildingData is FacilityVO)
                {
                    row = 1;
                    col = 1;
                }else
                {
                    row = _buildingData.length;
                    col = _buildingData.width;
                }
                _buildingData.unit_row1 = _buildingData.unit_row0 + row;
                _buildingData.unit_col1 = _buildingData.unit_col0 + col;
            }
        }
    }
    BuildingTile.as
    package com.app.map.smallMap
    {
        import com.core.manage.MaterialUIManager;
        import com.core.utils.Tool;
        
        import flash.display.Loader;
        import flash.display.MovieClip;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.ProgressEvent;
    
        /**
         * 由于加载属于异步,所以用显示对象将其包装起来,直接使用此类即可,<br/>加载完后显示对象会自动添加到本类实例当中;<br/>
         * 此皮肤需要在添加到舞台之前设入深度depth与对应店铺设施之id,此二字段的默认值皆为0
         * @author Ado
         * 
         */    
        public class Skin extends Sprite
        {
            /**
             * 对应之建筑,设施或者店铺之id 
             */        
            public var id:int = 0;
            /**
             * 此皮肤对应之BuildingTile之深度,显示排序用 
             */        
            public var depth:Number = 0;
            private var mc:MovieClip;
            private var _srcUrl:String;
            private var loader:Loader;
    //        private var _referWidth:Number;
            public var firstSort:int = 0;
            /**
             * 是否需要告知转换完毕 
             */        
            public var needNotice:Boolean;
            /**
             * 转换完毕的事件监听器 
             */        
            public static const CONVERT_COMPLETE:String = "CONVERT_COMPLETE";
            public function Skin(url:String = null)
            {
                loader = new Loader();
                
                if(url != "" && url != null)
                {
                    srcUrl = url;
                }
                this.buttonMode = true;
            }
            /**
             * 回收资源
             * */
            public function recycle():void
            {
                loader.unloadAndStop();
                _srcUrl = "";
            }
    
            public function get srcUrl():String
            {
                return _srcUrl;
            }
    
            public function set srcUrl(value:String):void
            {
                _srcUrl = value;
                loader.contentLoaderInfo.addEventListener(Event.COMPLETE, convertComHandler);
                loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
                if(MaterialUIManager.contains(_srcUrl))
                {
                    loader.loadBytes(Tool.clone(MaterialUIManager.getLoader(_srcUrl)));
                }
            }
            private function progressHandler(e:ProgressEvent):void
            {
                trace(e.bytesLoaded+":"+e.bytesTotal);
            }
            private function convertComHandler(e:Event):void
            {
                if(mc != null)
                {
                    mc.stop();
                    this.removeChild(mc);
                    mc = null;
                }
                
                mc = e.target.loader.content;
                mc.cacheAsBitmap = true;
                addChild(mc);
                
                loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, convertComHandler);
                
                if(needNotice)
                {
                    dispatchEvent(new Event(CONVERT_COMPLETE));
                }
            }
        }
    }
    Skin.as
    package com.app.map.smallMap
    {
        import flash.display.Sprite;
        
        public class Unit extends Sprite
        {
            private var color:uint;
            private var _settlable:Boolean = true;
            private var _setteld:Boolean = true;
            /**
             *  
             * @param t 1代表设施底座 2代表店铺底座
             * @author Ado
             */        
            public function Unit(t:int)
            {
                color = t == 1 ? 0xe0ec22 : 0xc02f0d;
                super();
            }
    
            private function updateBase():void
            {
                graphics.clear();
                var targetColor:uint = _setteld ? color : (_settlable ? 0x00ff00 : 0xff0000);
                graphics.beginFill(targetColor);
                
                graphics.moveTo(0.5,0);
                graphics.lineTo((BuildingTile.unitWidth - 1) /2, -(BuildingTile.unitHeight - 1)/2);
                graphics.lineTo((BuildingTile.unitWidth -1), 0);
                graphics.lineTo((BuildingTile.unitWidth - 1)/2, (BuildingTile.unitHeight - 1)/2)
                graphics.lineTo(0.5,0);
                graphics.endFill();
            }
            public function get settlable():Boolean
            {
                return _settlable;
            }
    
            public function set settlable(value:Boolean):void
            {
                _settlable = value;
                updateBase();
            }
    
            public function get setteld():Boolean
            {
                return _setteld;
            }
            
            public function set setteld(value:Boolean):void
            {
                _setteld = value;
                updateBase();
            }
        }
    }
    Unit.as

    因为老的电脑太卡了,所以没有去跑起来,所以没办法出效果图,就这么留念一下吧。

  • 相关阅读:
    error C4430: 缺少类型说明符
    Fiddler 教程
    make: Nothing to be done for 'first'
    Qt Creator + MinGW 在windows 下的调试GDB停止工作解决
    WIN7成功安装Qt4.8方法,无需VS支持
    深入研究 UCenter API For .NET
    C#在Winform程序中显示QQ在线状态
    VS2010 需要缺少的web组件才能加载该项目
    System.Runtime.InteropServices.COMException: 检索 COM 类工厂中 CLSID 为 {0002E510-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80040154
    c#while循环注意continue的地方
  • 原文地址:https://www.cnblogs.com/adoontheway/p/4383134.html
Copyright © 2011-2022 走看看