最近在玩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; } } }
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)); } } } }
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(); } } }
因为老的电脑太卡了,所以没有去跑起来,所以没办法出效果图,就这么留念一下吧。