地圖分塊加載類MapEngine,主要包含如下屬性:算法
單獨說下地圖層graphics,Graphics實際上爲一個shape對象,我把全部的加載的地圖塊,draw到graphics上,也有不少建立多個bitmap對象或者shape對象堆疊到地圖層,或者建立和屏幕視窗同樣的大的bitmap每次都draw到這個上面,我一開始接觸網頁的遊戲的時候,就是這種方法。嘗試事後,發後面的方式,在推圖的時候,斗的較厲害,直接畫在graphics上,可能給玩具啊最好的體驗,這也是破解了多款網頁遊戲代碼以後,參考大部分網頁遊戲推圖算法,最後加以總結概括,造成了我如今如今所用的。另外說下預加載塊數,preLoaderNmu 我設置爲1,就是相對屏幕視窗,實際計算出來的地圖塊,我上下左右都多加載一塊,以此來提供玩家體驗。具體的加載算法以下:api
public function calcLoadZone() : void { var rect:Rectangle = viewPort.viewRect; var tileSize:int = SceneConfig.TILE_SIZE; var scale:Number = 1 / tileSize; var leftX:int = int(rect.x * scale) - preLoaderNmu; var leftY:int = int(rect.y * scale) - preLoaderNmu; var rightX:int = int(rect.x + rect.width) * scale + preLoaderNmu; var rightY:int = int(rect.y + rect.height) * scale + preLoaderNmu; leftX = max(0, leftX); leftY = max(0, leftY); rightX = min(rightX, maxMapCountX); rightY = min(rightY, maxMapCountY); buffPixelRange.x = leftX * tileSize; buffPixelRange.y = leftY * tileSize; buffPixelRange.width = (rightX - leftX + 1) * tileSize; buffPixelRange.height = (rightY - leftY + 1) * tileSize; var centerX:int = (leftX + rightX) * 0.5; var centerY:int = (leftY + rightY) * 0.5; var temp:int = 0; var key:int = 0; var zone:Zone = null; while (leftY <= rightY) { temp = leftX; while (temp <= rightX) { key = temp + leftY * titleX; zone = currZoneArr[key]; // 判斷是否加載過此地圖塊 if (zone == null) { zone = new Zone(); zone.xpos = temp; zone.ypos = leftY; currZoneArr[key] = zone; zone.dis = pow(temp - centerX, 2) + pow(leftY - centerY, 2); //計算離加載範圍中心的距離 waitLoadZone[waitLoadZone.length] = zone; // 添加到加載隊列 } temp++; } leftY++; } waitLoadZone.sort(sortByDis); // 對要即在的地圖塊進行排序 }
上面的代碼,重要的部分已經註釋。那個sort函數,單獨說下,有不少加載地圖的效果,會有一個動畫效果,就是地圖塊的顯示,是從中心開始顯示,而後逐步擴展到四周。因此離加載範圍中心進的地圖塊優先加載,這樣就會保證離中心近的,先加載,也就會優先顯示出來。函數
玩家進入地圖以前,會優先下載小地圖,因此在全部 地圖塊加載以前,把小地圖放大後,直接畫在graphics上,這樣就實現馬賽克效果。爲了提升玩家的體驗,在每幀的循環裏,只加載一張地圖塊,而且只顯示有給地圖塊。通常網頁的幀率是沒秒30幀,理論上一針顯示一張地圖塊。代碼以下:優化
public function render(param1:int, param2:Number) : void { var zone2:Zone; var zone:Zone; var loadInfo:ILoadInfo; var size:int; var stepFrame:int = param1; var stepTime:Number = param2; if (waitLoadZone.length > 0) // 只加載一張地圖塊 { zone = waitLoadZone.shift(); loadInfo = api.loadCenter.getNewLoadInfo(); loadInfo.url = getPath(getMapId(), zone.xpos + "_" + zone.ypos); loadInfo.completeHanlder = function (param1:Bitmap) : void { var key:int = zone.xpos + zone.ypos * titleX; if (loadingDic[key] != undefined) { loadingDic[key] = null; delete loadingDic[key]; } if (!zone.isComplete) { zone.bpd = param1.bitmapData; showZone.push(zone); } loadedDic.push(loadInfo.url); return; } api.loadCenter.addLoadInfo(loadInfo); } while (showZone.length) // 只顯示一張已經加載過的地圖塊 { zone2 = showZone.shift(); size = SceneConfig.TILE_SIZE; g.beginBitmapFill(zone2.bpd); g.drawRect(zone2.xpos * size, zone2.ypos * size, size, size); break; } return; }
可能會有人疑惑,爲何每幀加載一塊,並且只顯示一塊地圖塊?爲何不根據,一下在都加載完,或者加載完,爲何不直接畫在地圖層。咱們都知道AS3.0 渲染機制,即跑道模型。若是AS每幀處理的事情太多,就會出現卡幀的狀況。這樣作的目的,就是儘可能把一些運算平均分攤到這個幀上,儘可能以平穩流暢爲主,算是一種優化策略。可能有的人機器配置高,或者網速快,他的體驗就會更好,的確是這樣。可是人眼能識別出的最低頻率24幀,一些電影就是以24幀的頻率動畫播放,因此把一些運算分攤到各個幀上,對於玩家來講,體驗並不會差多少,範圍提升了平穩性和流暢性。動畫
轉載請代表出處url