package com.game.engine.map
{
import com.game.GlobalConst;
import com.game.engine.findpath.MapUtil;
import com.game.load.SourceCache;
import com.game.load.item.ImageLoader;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
/**卡马克地图**/
public class CamakeMap extends Shape{
//路径
private var _rootPath :String;
//地图标识
private var _mapID :int;
//加载类型(1==>普通加载 、2==>分块加载)
private var _loadType :int;
//可视化宽
private var _visualWidth :int;
//可视化高
private var _visualHeight :int;
//地图的宽
private var _mapWidth :int;
//地图的高
private var _mapHeight :int;
//分块宽
private var _tileWidth :int;
//分块高
private var _tileHeight :int;
//分块列数
private var _cols :int;
//分块行数
private var _rows :int;
//当前位图滚动X轴
private var _bx :int;
//当前位图滚动Y轴
private var _by :int;
//等于位图滚动位置(0,0)时,px值
private var _tx :int;
//等于位图滚动位置(0,0)时,py值
private var _ty :int;
//上一次移动到的x轴位置
private var _fx :int;
//上一次移动到的y轴位置
private var _fy :int;
//当前地图开始行
private var _sRow :int;
//当前地图开始列
private var _sCol :int;
//当前地图结束行
private var _eRow :int;
//当前地图结束列
private var _eCol :int;
//当前地图可视化行
private var _vRow :int;
//当前地图可视化列
private var _vCol :int;
//最小滚动宽
private var _sMinWidth :int;
//最小滚动高
private var _sMinHeight :int;
//最大滚动宽
private var _sMaxWidth :int;
//最大滚动高
private var _sMaxHeight :int;
//小地图
private var _smallBmpd :BitmapData;
//默认位图
private var _defaultBmpd :BitmapData;
//地图资源管理器
private var _sourceCach :SourceCache;
//位图存储字典
private var _bmpdDic :Dictionary;
//位图加载队列
private var _bmpdLoadDic :Dictionary;
public function CamakeMap(){
this._bmpdDic = new Dictionary();
//SoureCache 是一个加载管理器,因为代码比较多,暂时不公开,此处是创建一个场景地图加载的管理
//如需要使用此类,可以自行修改加载方式
this._sourceCach = SourceCache.createSourceCache(GlobalConst.SCENE_CACHE,1);
}
/**
* 初始化地图
* @param String rootPath 地图路径
* @param int mapID 地图标识
* @param int loadType 加载类型
* @param int visualWidth 可视化宽
* @param int visualHeight 可视化高
* @param int mapWidth 地图高
* @param int mapHeight 地图宽
* @param int tileWidth 分块宽
* @param int tileHeight 分块高
* **/
public function initMap(rootPath:String,mapID:int,loadType:int,visualWidth:int,visualHeight:int,
mapWidth:int,mapHeight:int,tileWidth:int =0 ,tileHeight:int =0):void{
this.dispose();
this._mapID = mapID;
this._rootPath = rootPath;
this._loadType = loadType;
this._mapWidth = mapWidth;
this._mapHeight = mapHeight;
this._tileWidth = tileWidth;
this._tileHeight = tileHeight;
if(loadType == MapUtil.TYPE_LOAD_NOCUT){
this.scrollRect = new Rectangle(0,0,mapWidth,mapHeight);
this._sMaxWidth = mapWidth - this._sMinWidth;
this._sMaxHeight = mapHeight - this._sMinHeight;
}else if(loadType == MapUtil.TYPE_LOAD_CUT){
//总tile行列大小
this._rows = Math.ceil(mapHeight/tileHeight);
this._cols = Math.ceil(mapWidth/tileWidth);
this._defaultBmpd = new BitmapData(tileWidth,tileHeight,false,1);
}
this.resetMap(visualWidth,visualHeight);
this.loadSmallMap();
}
//加载小地图
private function loadSmallMap():void{
var item:ImageLoader = this._sourceCach.addSource("smallMap"+_mapID,_rootPath+"/"+_mapID+"/small.jpg") as ImageLoader;
item.addEventListener(Event.COMPLETE,loadSmallComplete,false,0,true);
this._sourceCach.start();
}
/**
* 重置当前网页窗口的可视化大小
* @param int visualWidth 可视化宽
* @param int visualHeight 可视化高
* **/
public function resetMap(visualWidth:int,visualHeight:int):void{
if(this._visualWidth != visualWidth ||
this._visualHeight != visualHeight){ //宽高与前面不相同才进行重置
this._visualWidth = Math.min(visualWidth,_mapWidth);
this._visualHeight = Math.min(visualHeight,_mapHeight);
if(_loadType == MapUtil.TYPE_LOAD_CUT){
//可视部分tile大小
this._sMinWidth = this._visualWidth/2;
this._sMinHeight = this._visualHeight/2;
var vRow:int = Math.min(Math.ceil(this._visualHeight/this._tileHeight)+1,this._rows);
var vCol:int = Math.min(Math.ceil(this._visualWidth/this._tileWidth)+1,this._cols);
if(this._vRow != vRow ||
this._vCol != vCol){
this._vRow = vRow;
this._vCol = vCol;
this.scrollRect = new Rectangle(0,0,this._vCol*this._tileWidth,this._vRow*this._tileHeight);
}
this._tx = -1;
this._ty = -1;
this._fx = -1;
this._fy = -1;
}
}
}
/**获取当前地图相对顶点X轴(普通地图的真实顶点)**/
public function get px():int{
return this._bx + this._tx;
}
/**获取当前地图相对顶点Y轴(普通地图的真实顶点)**/
public function get py():int{
return this._by + this._ty;
}
/**获取可视区域的宽**/
public function get visualWidth():Number{
return this._visualWidth;
}
/**获取可视区域的高**/
public function get visualHeight():Number{
return this._visualHeight
}
/**
* 滚动位图
* @param Number fx 跟随者X轴坐标
* @param Number fy 跟随者Y轴坐标
* **/
public function onScroll(fx:Number,fy:Number):void{
if(_fx != fx || _fy != fy){
this.cacheAsBitmap = false;
this._fx = fx;
this._fy = fy;
if(this._loadType == MapUtil.TYPE_LOAD_CUT){
this.updateTXY(fx,fy);
fx -= this._tx;
fy -= this._ty;
}
this.centerMap(fx,fy);
this.checkLoad();
}else{
this.cacheAsBitmap = true;
}
}
//更新tile的顶点位置
private function updateTXY(x:Number,y:Number):void{
this._sRow = Math.floor((y - this._sMinHeight)/this._tileHeight);
this._sCol = Math.floor((x - this._sMinWidth)/this._tileWidth);
if(this._sRow <= 0){
this._sRow = 0;
}else if(this._sRow >= (this._rows - this._vRow)){
this._sRow = this._rows - this._vRow;
}
if(this._sCol <= 0){
this._sCol = 0;
}else if(this._sCol >= (this._cols -this. _vCol)){
this._sCol = this._cols - this._vCol;
}
this._eRow = this._sRow + this._vRow ;
this._eCol = this._sCol + this._vCol;
if(this._eRow >= this._rows){
this._sMaxHeight = this._mapHeight-this._sRow*this._tileHeight-this._sMinHeight;
}else{
this._sMaxHeight = this._vRow*this._tileHeight-this._sMinHeight;
}
if(this._eCol >= this._cols){
this._sMaxWidth = this._mapWidth - this._sCol*this._tileWidth-this._sMinWidth;
}else{
this._sMaxWidth = this._vCol*this._tileWidth -this._sMinWidth;
}
var tx:int = this._sCol*this._tileWidth;
var ty:int = this._sRow*this._tileHeight;
if(tx != this._tx || this._ty != ty){
this._tx = tx;
this._ty = ty;
this.updateAllBmpd();
}
}
//地图居中
private function centerMap(fx:Number,fy:Number):void{
var centerX:Number = 0;
var centerY:Number = 0;
if(fx <= this._sMinWidth){
centerX = 0;
}else if(fx >= this._sMaxWidth){
centerX = this._sMaxWidth - this._sMinWidth;
}else {
centerX = fx - this._sMinWidth;
}
if(fy <= this._sMinHeight){
centerY = 0;
}else if(fy >= this._sMaxHeight){
centerY = this._sMaxHeight - this._sMinHeight;
}else{
centerY = fy - this._sMinHeight;
}
var rect:Rectangle = this.scrollRect;
rect.x = centerX;
rect.y = centerY;
this.scrollRect = rect;
this._bx = centerX;
this._by = centerY;
}
//检查加载地图,判断地图是否在可视范围内,是的话加入加载队列中
private function checkLoad():void{
var item:ImageLoader;
if(this._loadType == MapUtil.TYPE_LOAD_NOCUT){
if(this._bmpdLoadDic[this._mapID+"_0_0"] == undefined){
item = this._sourceCach.addSource(this._mapID+"_0_0",this._rootPath+"/"+this._mapID+"/big.jpg") as ImageLoader;
item.addEventListener(Event.COMPLETE,loadComplete);
this._bmpdDic[item.key] = item;
this._bmpdLoadDic[this._mapID+"_0_0"] = true;
}
}else if(this._loadType == MapUtil.TYPE_LOAD_CUT){
for(var i:int=this._sRow;i<this._eRow;i++){
for(var j:int=_sCol;j<this._eCol;j++){
if(this._bmpdLoadDic[this._mapID+"_"+i+"_"+j] == undefined){
item = _sourceCach.addSource(this._mapID+"_"+i+"_"+j,this._rootPath+"/"+this._mapID+"/"+i+"_"+j+".jpg") as ImageLoader;
item.addEventListener(Event.COMPLETE,loadComplete);
this._bmpdLoadDic[item.key] = item;
this._bmpdLoadDic[this._mapID+"_"+i+"_"+j] = true
}
}
}
}
this._sourceCach.start();
}
//加载位图成功
private function loadComplete(event:Event):void{
var item:ImageLoader = event.target as ImageLoader
if(item != null){
if(this._bmpdDic[item.key] is BitmapData) {
this._bmpdDic[item.key].dispose();
}
var array:Array = item.key.split("_");
this._bmpdDic[item.key] = item.bmpd;
this.updateBmpd(int(array[1]),int(array[2]));
item.removeEventListener(Event.COMPLETE,loadComplete);
}
}
//加载小地图成功
private function loadSmallComplete(event:Event):void{
var item:ImageLoader = event.target as ImageLoader;
if(item != null){
var bmpd :BitmapData;
var matrix :Matrix = new Matrix();
if(this._loadType == MapUtil.TYPE_LOAD_NOCUT){
if(this._bmpdDic[this._mapID+"_0_0"] == null){
bmpd = new BitmapData(this._mapWidth,_mapHeight,false);
matrix.scale(this._mapWidth/item.bmpd.width,this._mapHeight/item.bmpd.height);
bmpd.draw(item.bmpd,matrix,null,null,null,false);
this._bmpdDic[this._mapID+"_0_0"] = bmpd;
updateBmpd(0,0);
}
}else if(_loadType == MapUtil.TYPE_LOAD_CUT){
this._smallBmpd = item.bmpd;
this.updateAllBmpd();
}
item.removeEventListener(Event.COMPLETE,loadSmallComplete);
}
}
//滚动到边缘时需要更新整张位图
private function updateAllBmpd():void{
this.graphics.clear();
for(var i:int=this._sRow;i<=this._eRow;i++){
for(var j:int=this._sCol;j<=this._eCol;j++){
var point :Point = new Point((j-this._sCol)*this._tileWidth,(i-this._sRow)*this._tileHeight);
var bmpd :BitmapData;
if(this._bmpdDic[this._mapID+"_"+i+"_"+j] is BitmapData){
bmpd = this._bmpdDic[this._mapID+"_"+i+"_"+j];
}else if(this._smallBmpd != null){
var matrix :Matrix = new Matrix();
var stw :int = Math.round(this._smallBmpd.width/this._cols);
var sth :int = Math.round(this._smallBmpd.height/this._rows);
var sbmpd:BitmapData = new BitmapData(stw,sth);
matrix.scale(this._tileWidth/stw,this._tileHeight/sth);
sbmpd.copyPixels(this._smallBmpd,new Rectangle(j*stw,i*sth,stw,sth),new Point());
bmpd = new BitmapData(this._tileWidth,this._tileHeight,false);
bmpd.draw(sbmpd,matrix,null,null,null,false);
sbmpd.dispose();
this._bmpdDic[this._mapID+"_"+i+"_"+j] = bmpd;
}else{
bmpd = this._defaultBmpd;
}
this.graphics.beginBitmapFill(bmpd);
this.graphics.drawRect(point.x,point.y,bmpd.width,bmpd.height);
}
}
this.graphics.endFill();
}
//更新缓冲位图
private function updateBmpd(row:int,col:int):void{
var bmpd:BitmapData;
if(this._loadType == MapUtil.TYPE_LOAD_NOCUT){
bmpd = this._bmpdDic[_mapID+"_0_0"];
this.graphics.beginBitmapFill(bmpd);
this.graphics.drawRect(0,0,bmpd.width,bmpd.height);
}else if(this._loadType == MapUtil.TYPE_LOAD_CUT){
bmpd = this._bmpdDic[this._mapID+"_"+row+"_"+col];
this.graphics.beginBitmapFill(bmpd);
this.graphics.drawRect((col-this._sCol)*this._tileWidth,(row-this._sRow)*this._tileHeight,bmpd.width,bmpd.height);
}
this.graphics.endFill();
}
/**销毁 一般会在切换场景时需要执行此方法,用于清除上一张地图的位图缓存, 回收内存**/
public function dispose():void{
//执行removeAllSource()将会删除当前加载管理中所有资源,并清除当前加载队列
this._sourceCach.removeAllSource();
for each(var temp:Object in _bmpdDic){
if(temp is ImageLoader) temp.removeEventListener(Event.COMPLETE,loadComplete);
else if(temp is BitmapData) temp.dispose();
}
if(this._defaultBmpd!= null){this._defaultBmpd.dispose();this._defaultBmpd = null;}
if(this._smallBmpd != null ){this._smallBmpd.dispose();this._smallBmpd = null;}
this._bmpdDic = new Dictionary();
this._bmpdLoadDic = new Dictionary();
this._tx = -1;
this._ty = -1;
this._fx = -1;
this._fy = -1;
}
}
}Flash网页游戏中实现的地图分块加载(卡马克地图)
最新推荐文章于 2019-04-16 17:07:11 发布
本文介绍了一个用于游戏地图管理的系统,包括地图加载、滚动、可视化和资源管理等功能。

202

被折叠的 条评论
为什么被折叠?



