Flex地圖分塊加載的實現

在家上網賺錢更容易

首先我們確定幾個關鍵點:
窗口大小:windowW:Number,windowH:Number; 指的是可視區域的大小 我們可以把他想成客戶端的分別率
單位地圖大小: uintPicW:Number,uintPicH:Number; 指的是你切割的地圖圖片的單元大小。
當前地圖座標:position:point;這裏大家就可以想成是你人物的當前所處座標

清楚了上面的幾個關鍵點,我們再來看下面的這個圖:



陰影區域就是可視區域 A、B、C、D就是切割的單元地圖

我們可以很容易的求出窗口的4個點,所佔的地圖的索引:
x0 = position.x - windowW/2;
x1 = position.x + windowW/2;
y0 = position.y - windowH/2;
y1 = position.y + windowH/2;

mapIndexX0 = uint(x0/256);
mapIndexX1 = uint(x1/256);
mapIndexY0 = uint(y0/256);
mapIndexY1 = uint(y1/256);

明白了上面的這些 下面這個類 相信大家都能看明白

  1. package com.heptaFish.common.game.map.layers
  2. {
  3. import com.heptaFish.common.config.Config;
  4. import com.heptaFish.common.core.BaseDisplayObject;
  5. import com.heptaFish.common.game.map.impl.GameMap;
  6. import com.heptaFish.common.hack.HeptaFishGC;
  7. import com.heptaFish.common.loader.impl.ImageLoader;
  8. import com.heptaFish.common.map.impl.HashMap;
  9. import flash.display.Bitmap;
  10. import flash.events.Event;
  11. import flash.events.IOErrorEvent;
  12. import flash.events.ProgressEvent;
  13. import flash.geom.Point;
  14. //地圖層 圖片
  15. public class MapLayer extends BaseDisplayObject
  16. {
  17.   //圖片讀取器
  18.   private var _imageLoader:ImageLoader;
  19.   //地圖圖片 用於整塊加載模式
  20.   private var _image:Bitmap;
  21.   //地圖圖片數組 用於柵格式加載地圖模式
  22.   private var _imageMap:HashMap;
  23.   //小地圖圖片
  24.   private var _simage:Bitmap;
  25.   //
  26.   private var _map:GameMap;
  27.   private var _loadType:int;//加載類型 0:整塊加載 1:柵格加載
  28.   private var _visualWidth:Number;//地圖可視寬度
  29.   private var _visualHeight:Number;//地圖可視高度
  30.   private var _sliceWidth:Number;//地圖切割單元寬度
  31.   private var _sliceHeight:Number;//地圖切割單元高度
  32.   private var _preloadX:Number;//橫向預加載屏數
  33.   private var _preloadY:Number;//縱向預加載屏數
  34.   private var _loadingMap:HashMap;//正在加載的屏map
  35.   private var _waitLoadingArr:Array;//等待加載的loadermap
  36.   
  37.   private var _loadingNo:int = Config.getInt("concurrencyImageLoader");
  38.   
  39.   private var _screenImageRow:int;//一屏需要加載的橫向圖片數
  40.   private var _screenImageCol:int;//一屏需要加載的縱向圖片數
  41.   private var _row:int;//總橫向節點數
  42.   private var _col:int;//總縱向節點數
  43.   
  44.   private var _nowPlayerPointoint;//當前人物所處的屏
  45.   
  46.   public function MapLayer(map:GameMap)
  47.   {
  48.    _map = map;
  49.    _loadType = parseInt([email protected]);
  50.   }
  51.   //讀取地圖圖片
  52.   public function load():void{
  53.    //加載小地圖
  54.    var imageLoader:ImageLoader = new ImageLoader();
  55.    var fileName:String =Config.getValue("mapLib") + _map.name + "/map_s.jpg";
  56.    imageLoader.load(fileName);
  57.    imageLoader.addEventListener(Event.COMPLETE,loadSmallSuccess);
  58.    imageLoader.addEventListener(ProgressEvent.PROGRESS,loadingHandler);
  59.    imageLoader.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
  60.    
  61.   }
  62.   //讀取大地圖成功
  63.   private function loadBigSuccess(evet:Event):void{
  64.    var imageLoader:ImageLoader = ImageLoader(evet.target);
  65.    var image:Bitmap = new Bitmap(imageLoader._data);
  66.    addChild(image);
  67.    if(_simage != null && _simage.parent == this){
  68.     removeChild(_simage);
  69.     _simage = null;
  70.    }
  71.    this.width = image.width;
  72.    this.height = image.height;
  73.    imageLoader.removeEventListener(Event.COMPLETE,loadBigSuccess);
  74.    imageLoader.removeEventListener(ProgressEvent.PROGRESS,loadingHandler);
  75.    imageLoader.removeEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
  76.    imageLoader = null;
  77.    dispatchEvent(evet);
  78.    HeptaFishGC.gc();
  79.   }
  80.   //讀取小地圖成功
  81.   private function loadSmallSuccess(evet:Event):void{
  82.    var imageLoader:ImageLoader = ImageLoader(evet.target);
  83.    var image:Bitmap = new Bitmap(imageLoader._data);
  84.    image.width = _map.mapWidth;
  85.    image.height = _map.mapHeight;
  86.    addChild(image);
  87.    this.width = image.width;
  88.    this.height = image.height;
  89.    imageLoader.removeEventListener(Event.COMPLETE,loadSmallSuccess);
  90.    imageLoader.removeEventListener(ProgressEvent.PROGRESS,loadingHandler);
  91.    imageLoader.removeEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
  92.    imageLoader = null;
  93.    dispatchEvent(evet);
  94.    HeptaFishGC.gc();   
  95.    switch(_loadType){
  96.     case 0://整塊加載   
  97.      //加載大地圖
  98.      var bfileName:String =Config.getValue("mapLib") + _map.name + "/map.jpg";
  99.      var bLoader:ImageLoader = new ImageLoader();
  100.      bLoader.load(bfileName);
  101.      bLoader.addEventListener(Event.COMPLETE,loadBigSuccess);
  102.      bLoader.addEventListener(ProgressEvent.PROGRESS,loadingHandler);
  103.      bLoader.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
  104.      break;
  105.     case 1:
  106.      _loadingMap = new HashMap();
  107.      _imageMap = new HashMap();
  108.      _waitLoadingArr = new Array();
  109.      _visualWidth = _map.app.screen.size.x;
  110.      _visualHeight = _map.app.screen.size.y;
  111.      _sliceWidth = parseFloat([email protected]);
  112.      _sliceHeight = parseFloat([email protected]);
  113.      _preloadX = parseFloat([email protected]);
  114.      _preloadY = parseFloat([email protected]);
  115.      _screenImageRow = Math.round(_visualWidth/_sliceWidth);
  116.      _screenImageCol = Math.round(_visualHeight/_sliceHeight);
  117.      _row = Math.ceil(_map.mapWidth/_sliceWidth);
  118.      _col = Math.ceil(_map.mapHeight/_sliceHeight);
  119.      loadSliceImage(_map.initPlayerPoint);
  120.      break;
  121.     default:
  122.      break;
  123.      
  124.    }
  125.   }
  126.   
  127.   //根據player座標讀取周邊指定屏數地圖
  128.   private function loadSliceImage(playerPointoint):void{
  129.    var nowX:int = Math.floor(playerPoint.x/_sliceWidth);//現在所處的索引X
  130.    var nowY:int = Math.floor(playerPoint.y/_sliceHeight);//現在所處的索引Y
  131.    var nowScreenX:int = Math.floor(nowX/_screenImageRow);//現在所處的屏索引X
  132.    var nowScreenY:int = Math.floor(nowY/_screenImageCol);//現在所處的屏索引Y
  133. //   trace("nowScreenX:" + nowScreenX);
  134. //   trace("nowScreenY:" + nowScreenY);
  135.    _nowPlayerPoint = new Point(nowScreenX,nowScreenY);
  136.    loadScreenImage(nowScreenX,nowScreenY);
  137. //   removeScreenImage(nowScreenX,nowScreenY);
  138.    var startX:int = (nowScreenX - _preloadX < 0 ? 0 : nowScreenX - _preloadX);
  139.    var startY:int = (nowScreenY - _preloadY < 0 ? 0 : nowScreenY - _preloadY);
  140.    
  141.    var endX:int = (nowScreenX + _preloadX > _row ? _row : nowScreenX + _preloadX);
  142.    var endY:int = (nowScreenY + _preloadY > _col ? _col : nowScreenY + _preloadY);
  143.    
  144.    for(var xx:int = startX; xx < endX;xx++){
  145.     for(var yy:int = startY; yy < endY;yy++){
  146.      if(xx == nowScreenX && yy == nowScreenY){
  147.       continue;
  148.      }else{
  149.       loadScreenImage(xx,yy);
  150.      }
  151.     }
  152.    }
  153.   }
  154.   //加載指定屏的地圖圖片
  155.   private function loadScreenImage(screenX:int,screenY:int):void{
  156.    var starX:int = _screenImageRow*screenX < 0 ? 0 : _screenImageRow*screenX;
  157.    var starY:int = _screenImageCol*screenY < 0 ? 0 : _screenImageCol*screenY;
  158.    var endX:int = _screenImageRow*(screenX+1) > _row - 1 ? _row -1 : _screenImageRow*(screenX+1);
  159.    var endY:int = _screenImageCol*(screenY+1) > _col-1  ? _col-1 : _screenImageCol*(screenY+1);
  160.    for(var yy:int=starY;yy
  161.     for(var xx:int = starX;xx
  162.      var tempKey:String = yy+"_"+xx;
  163.      if(!_loadingMap.containsValue(tempKey) && !_imageMap.containsKey(tempKey)){
  164.       _waitLoadingArr.push(tempKey);
  165.      }
  166.     }
  167.     _waitLoadingArr.reverse();
  168.     loadImage();
  169.    }
  170.   }
  171.   
  172.   private function loadImage():void{
  173.    if(_waitLoadingArr.length > 0){
  174.     for(var i:int = 0;i<_loadingNo - _loadingMap.size();i++){
  175.      var key:String = _waitLoadingArr.pop();
  176.      var imageLoader:ImageLoader = new ImageLoader();
  177.      var fileName:String = Config.getValue("mapLib") + _map.name +"/" + key  + ".jpg";
  178. //     trace("fileName:" + fileName);
  179.      _loadingMap.put(imageLoader,key);
  180.      imageLoader.addEventListener(Event.COMPLETE,loadScreenImageSuccess);
  181.      imageLoader.addEventListener(ProgressEvent.PROGRESS,loadingHandler);
  182.      imageLoader.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
  183.      imageLoader.load(fileName);
  184.     }
  185.    }
  186.   }
  187.   
  188.   //成功加載某屏的圖片
  189.   private function loadScreenImageSuccess(evet:Event):void{
  190.    var imageLoader:ImageLoader = ImageLoader(evet.target);
  191.    var tempStr:String = String(_loadingMap.getValue(imageLoader));
  192.    var tempStrArr:Array = tempStr.split("_");
  193.    var yy:int = tempStrArr[0];
  194.    var xx:int = tempStrArr[1];
  195.    _loadingMap.remove(imageLoader);
  196.    var image:Bitmap = new Bitmap(imageLoader._data);
  197.    image.x = _sliceWidth*xx;
  198.    image.y = _sliceHeight*yy;
  199.    this.addChild(image);
  200.    _imageMap.put(yy+"_"+xx,image);
  201.    imageLoader.removeEventListener(Event.COMPLETE,loadScreenImageSuccess);
  202.    imageLoader.removeEventListener(ProgressEvent.PROGRESS,loadingHandler);
  203.    imageLoader.removeEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
  204.    imageLoader = null;
  205.    loadImage();
  206.   }
  207.   //卸載指定屏的地圖圖片
  208.   private function removeScreenImage(screenX:int,screenY:int):void{
  209.    var startX:int = (screenX - _preloadX < 0 ? 0 : screenX - _preloadX);
  210.    var startY:int = (screenY - _preloadY < 0 ? 0 : screenY - _preloadY);
  211.    
  212.    var endX:int = (screenX + _preloadX > _row ? _row : screenX + _preloadX);
  213.    var endY:int = (screenY + _preloadY > _col ? _col : screenY + _preloadY);
  214.    var keyArr:Array = _imageMap.keys();
  215.    for(var i:int = 0;i < keyArr.length;i++){
  216.     var key:String = keyArr;
  217.     var tempStrArr:Array = key.split("_");
  218.     var yy:int = tempStrArr[0];
  219.     var xx:int = tempStrArr[1];
  220.     if(xx < startX*_screenImageRow || xx > endX * _screenImageRow || yy < startY*_screenImageCol || yy > endY*_screenImageCol){
  221.      var image:Bitmap = Bitmap(_imageMap.getValue(key));
  222.      this.removeChild(image);
  223.      image = null;
  224.      _imageMap.remove(key);
  225.     }
  226.    }
  227.    HeptaFishGC.gc();
  228.   }
  229.   
  230.   //檢查是否需要加載
  231.   public function checkLoad(pointoint):void{
  232.    var nowX:int = Math.floor(point.x/_sliceWidth);//現在所處的索引X
  233.    var nowY:int = Math.floor(point.y/_sliceHeight);//現在所處的索引Y
  234.    var nowScreenX:int = Math.floor(nowX/_screenImageRow);//現在所處的屏索引X
  235.    var nowScreenY:int = Math.floor(nowY/_screenImageCol);//現在所處的屏索引Y
  236.    if(nowScreenX != _nowPlayerPoint.x || nowScreenY != _nowPlayerPoint.y){
  237.     loadSliceImage(point);
  238.    }
  239.    
  240.   }
  241. }
  242. }
  243. 在家上網賺錢更容易