最近在玩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建筑拖动的实现的更多相关文章

  1. COC+RTS+MOR游戏开发 一(游戏特色分析,和实践)

    本场比赛的临时名称 游戏特色(-):COC风格 ,塔防养成类游戏.          一款史诗般的战斗策略游戏.玩家须要建立村庄,成千上万的网友训练玩家的军队和战斗. 游戏中玩家须要不断的提高军队的作 ...

  2. CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果

    CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...

  3. Android开发学习之路-RecyclerView滑动删除和拖动排序

    Android开发学习之路-RecyclerView使用初探 Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析 Android开 ...

  4. 【Android】 修复ijkPlayer进行m3u8 hls流播放时seek进度条拖动不准确的问题

    项目中使用的播放器是ijkPlayer,发现播放切片特点的hls流(m3u8格式的视频)拖动seekBar的时候会莫名的跳转或者seek不到准确的位置,发现网友也遇到了同样的问题,ijk的开发者也说明 ...

  5. 自己封装的一个原生JS拖动方法。

    代码: function drag(t,p){ var point = p || null, target = t || null, resultX = 0, resultY = 0; (!point ...

  6. 基于Metronic的Bootstrap开发框架经验总结(13)--页面链接收藏夹功能的实现2(利用Sortable进行拖动排序)

    在上篇随笔<基于Metronic的Bootstrap开发框架经验总结(12)--页面链接收藏夹功能的实现>上,我介绍了链接收藏夹功能的实现,以及对收藏记录的排序处理.该篇随笔主要使用功能按 ...

  7. jQuery拖动剪裁图片作为头像

    图片上传是许多网站的一个常用的功能,有时需要对上传的图片做初步的选择裁剪,比如上传头像.下面就是一个使用HTML5+jQuery实现的图片上传裁剪特效,可以对选择要上传的图片做缩小.放大.拖动和裁剪, ...

  8. SharePoint 2013 通过JavaScript实现列表标题列宽度可拖动

    前言 最近有个新需求,用户希望标题栏可以拖动宽度,其实觉得没什么用,既然用户要了又推不掉,就勉为其难实现一下吧. 其实原理比较简单,就是利用JavaScript对标题栏进行宽度控制,然后从网上搜了一下 ...

  9. 基于jquery实现图片拖动和曲线拖放

    功能:图片的拖动.曲线的拖放和绘制 一. 准备工作 1. 点击此下载相关的文档 二. 在浏览器中运行 dragDrop.html 文件,即可看到效果 三. 效果图

随机推荐

  1. 【单源最短路模板】 poj 2387

    #include <cstdio> #include <iostream> #include <stdlib.h> #include <memory.h> ...

  2. 做.net的早晚会用到,并且网上还没有这方面的正确资料或几乎很少

    原文网址:http://www.cnblogs.com/langu/archive/2012/03/23/2413990.html 一直以来,找安装程序的msi源文件路径得到的都是“system32” ...

  3. 对于IE6版本图片透明。

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. CodeForces 689C Mike and Chocolate Thieves (二分最大化最小值)

    题目并不难,就是比赛的时候没敢去二分,也算是一个告诫,应该敢于思考…… #include<stdio.h> #include<iostream> using namespace ...

  5. Java程序员的10道XML面试题 (转)

    包括web开发人员的Java面试在内的各种面试中,XML面试题在各种编程工作的面试中很常见.XML是一种成熟的技术,经常作为从一个平台到其他平台传输数据的标准.XML面试问题包括用于转换XML文件的X ...

  6. HDU 2675 Equation Again

    公式转化+二分答案 首先,把题目中给的等式转化一下,变成了这个样子. 等式右边的值是可以求出来的. ln(x)/x的大致图像是这样的 那么只要对[0,e]和[e,+∞]分别进行二分答案即可. #inc ...

  7. 错误: error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. 的处理方法

  8. Ubuntu 12.04和Windows 7双系统安装图解

    http://wenku.baidu.com/link?url=PZlnNOhY0SjHDW-teFFnCMzPYJVjx7vj6yWY-o5HHFLuFqhLI4uFcQVu_y0_6i7vpSnz ...

  9. 使用nodejs的http模块创建web服务器

    使用nodejs的http模块创建web服务器 laiqun@msn.cn Contents 1. web服务器基础知识 2. Node.js的Web 服务器 3. 代码实现 1. web服务器基础知 ...

  10. Struts2 设置--Myelipse

    1. Windows---preferrence---Myeclipse---Server----Tomcat 2. Windows---preferrence---Java---Installed ...