arpg網頁遊戲之地圖(三)

  地圖分塊加載類MapEngine,主要包含如下屬性:算法

    1. g 地圖層graphics,地圖將畫在上面
    2. buffPixelRange 地圖加載範圍矩形
    3. viewPort 屏幕視窗
    4. currZoneArr 已經加載過的地圖塊
    5. waitLoadZone 待加載地圖塊
    6. showZone 加載完成即將顯示的地圖塊
    7. preLoaderNmu 預加載塊數

  單獨說下地圖層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

相關文章
相關標籤/搜索