標籤:
地圖分塊載入類MapEngine,主要包含以下屬性:
-
- g 地圖層graphics,地圖將畫在上面
- buffPixelRange 地圖載入範圍矩形
- viewPort 螢幕視窗
- currZoneArr 已經載入過的地圖塊
- waitLoadZone 待載入地圖塊
- showZone 載入完成即將顯示的地圖塊
- preLoaderNmu 預先載入塊數
單獨說下地圖層graphics,Graphics實際上為一個shape對象,我把所有的載入的地圖塊,draw到graphics上,也有很多建立多個bitmap對象或者shape對象堆疊到地圖層,或者建立和螢幕視窗一樣的大的bitmap每次都draw到這個上面,我一開始接觸網頁的遊戲的時候,就是這種方法。嘗試過後,發後面的方式,在推圖的時候,鬥的較厲害,直接畫在graphics上,可能給玩具啊最好的體驗,這也是破解了多款網頁遊戲代碼之後,參考大部分網頁遊戲推圖演算法,最後加以總結歸納,形成了我現在現在所用的。另外說下預先載入塊數,preLoaderNmu 我設定為1,就是相對螢幕視窗,實際計算出來的地圖塊,我上下左右都多載入一塊,以此來提供玩家體驗。具體的載入演算法如下:
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幀的頻率動畫播放,所以把一些運算分攤到各個幀上,對於玩家來說,體驗並不會差多少,範圍提高了平穩性和流暢性。
arpg網頁遊戲之地圖(三)