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

 

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

你可能感兴趣的:(COC建筑拖动的实现)