2016-07-16 115 views
0

我目前正在創建一個2D遊戲,我想知道如果瓷磚必須移動或字符?我是否需要在2d瓷磚世界中移動瓷磚或玩家?

我問這個問題,因爲我已經創建了「2D瓷磚地圖」,但它運行速度太慢,我無法修復它。我現在試了一切,結果是我得到30幀/秒。

運行速度太慢的原因是因爲每1ms帶一個定時器,瓷磚正在重繪。但我無法弄清楚如何解決這個問題。

如果有人能幫助我,我會非常感激!

我這是怎麼使地圖:

 public void makeBoard() 
    { 
     for (int i = 0; i < tileArray.GetLength(0); i++) 
     { 
      for (int j = 0; j < tileArray.GetLength(1); j++) 
      { 
       tileArray[i, j] = new Tile() { xPos = j * 50, yPos = i * 50 }; 
      } 
     } 
    } 

在這裏,我重繪每1毫秒以上的瓷磚和精靈:

 private void Wereld_Paint_1(object sender, PaintEventArgs e) 
    { 
     //label1.Text = k++.ToString(); 
     using (Graphics grap = Graphics.FromImage(bmp)) 
     { 
      for (int i = 0; i < tileArray.GetLength(0); i++) 
      { 
       for (int j = 0; j < tileArray.GetLength(1); j++) 
       { 
        grap.DrawImage(tileArray[i, j].tileImage, j * 50, i * 50, 50, 50); 
       } 
      } 
      grap.DrawImage(player.movingObjectImage, player.xPos, player.yPos, 50, 50); 
      grap.DrawImage(enemyGoblin.movingObjectImage, enemyGoblin.xPos, enemyGoblin.yPos, 50, 50); 

      groundPictureBox.Image = bmp; 
      // grap.Dispose(); 

     } 
    } 

這是一個特定的定時器間隔:

 private void UpdateTimer_Tick(object sender, EventArgs e) 
    { 
     if(player.Update()==true) // true keydown event is fired 
     { 
      this.Invalidate(); 
     } 
     label1.Text = lastFrameRate.ToString(); // for fps rate show 
     CalculateFrameRate(); // for fps rate show 
    } 
+0

只畫那些應該出現在屏幕上的瓦片,並用相機來幫你畫的東西:http://stackoverflow.com/questions/9997006/slick2d-and-jbox2d-how- to-draw?answertab = votes#tab-top – user3814613

+0

@ user3814613首先,感謝您的評論!我真的不明白你在說什麼。我必須重新繪製所有的瓷磚,因爲我希望瓷磚移動,所以它看起來像玩家在「世界」周圍走動。此外,我從來沒有使用過相機功能,我不知道從哪裏開始。 –

+0

您是否閱讀過該評論中鏈接的帖子?如果你有,你不會說*我不知道從哪裏開始*。人們提供其他問題的鏈接來幫助;在他們完成了爲你找到它的工作之後忽略他們是不好的。 –

回答

1

正如在評論中提到你的概念是錯誤的。

  1. 瓦片地圖是靜態

    從功能的角度,如果玩家移動或地圖,從性能的角度來看並不重要:所以在這裏只是如何做這個任務的一個簡單的總結瓷磚的數量比玩家的數量大得多,所以移動的玩家更快。

    要實現玩家居中或觀看視野,您必須移動相機。

  2. 渲染

    重繪每1ms爲瘋狂,最有可能不可能對當今的計算機,如果你有中等場景的複雜程度。人類視覺無法檢測到它,所以沒有意義重繪更多25-40 fps。更高fps需求的唯一原因是與顯示器刷新同步以避免掃描線僞影(即使LCD使用掃描線刷新也是如此)。爲了獲得更多的fps,你的顯示器的刷新率是毫無意義的(許多fps玩家會反對,但我們的看法是什麼,不管他們說什麼......)。

    無論如何,如果你的渲染花費了1ms以上(這可能更有可能),那麼你的計時器就會失效,因爲它應該在第一個處理程序停止之前多次發射。由於同步問題,這通常會導致大規模的慢速拍攝,所以最終的fps通常會比渲染引擎提供的更小。那麼如何補救呢?

    1. 設置timer間隔20ms以上
    2. 添加bool _redraw=false 而僅使用它重繪當你需要重繪屏幕。因此,對於任何動作,如玩家移動,相機移動或轉動,動畫更改將其設置爲true
    3. 內部計時器事件處理程序僅在_redraw==true內調用重新繪製並將其設置爲false後。

    這會提高性能很多。即使重新繪製時間比定時器間隔還要多,仍然會比目前的方法快得多。

    避免閃爍使用返回緩衝

  3. 相機和剪裁

    你的地圖是屏幕最有可能更大,所以沒有點重繪所有的瓷磚。您可以將相機視爲選擇地圖右側部分的方法。如果你的遊戲不使用旋轉,那麼你只需要position,可能是zoom/scale。如果你想旋轉,那麼2D 3x3均勻矩陣就是這種方式。

    讓假設你只得到了位置(無縮放或旋轉),那麼你可以使用這個轉換:

    screen_x=world_x-camera_x 
    screen_y=world_y-camera_y 
    
    world_x=screen_x+camera_x 
    world_y=screen_y+camera_y 
    

    所以camera是你的相機視圖位置,world是你平鋪位置在地圖上的座標和screen是在屏幕上的位置。如果您在地圖上獲得了瓦片的indexes,則只需將它們乘以瓦片大小(以像素爲單位)即可獲得world座標。

    要僅選擇可見圖塊,需要獲取屏幕的角點位置,將其轉​​換爲世界座標,然後轉換爲地圖中的索引,並最終只渲染矩形內的這些點在地圖中形成的圖塊+某些誤差範圍(例如,在所有方向上呈現1個拼貼放大的矩形)。這樣,渲染將獨立於您的地圖大小。這個過程被稱爲剪輯

我強烈建議看一下這些相關QA S:

演示中的鏈接進行質量檢查只使用GDI和直接像素訪問的位圖的Win32應用程序的形式,所以你可以用你的代碼比較性能(他們應該是相似的)和調整你的代碼,直到它的行爲應該。

+0

首先,謝謝你的幫助:)我完成了第2步,但現在我不需要第3步。我有一個想法如何做到這一點。但首先,我想擺脫de 30 fps p/s。你有什麼技巧可以在每20ms繪製完整的地圖達到50/60 fps左右?我只畫出與屏幕一樣大的地圖,所以沒有瓷磚出現。後來我將執行其餘的......謝謝你的時間! –

+0

@MYil第一個鏈接的QA也是我的演示源代碼,速度足夠快。沒有看到你怎麼渲染很難說瓶頸在哪裏......你怎麼渲染精靈?還是你只有瓷磚(沒有透明度或面具)?無論如何錯誤地編碼gfx渲染可以痛苦緩慢... – Spektre

+0

感謝您的答案!奧克,生病要儘可能清楚:)我有一個裝滿瓷磚的二維陣列。那些瓷磚是類,在這些類中有一個圖像。該圖像大約1kb。我每隔1ms(或20ms,給出相同的性能)將圖像重繪爲位圖。並在一個大型的電影箱上繪畫。位圖大小與圖片框大小一樣大。每當我按下一個keydown事件時,重繪就完成了。然後計時器將打開精靈類中的移動方法並使其移動。讓我把我的代碼porition,掛在:) –

1

您是否正在自己編寫瓷磚實施?可能問題在於,你在繪製所有瓷磚的每一幀中。

具有滾動貼圖的2D引擎應該在比屏幕更大的精靈上繪製貼圖,然後繪製該精靈周圍的快速操作(您需要指定您正在使用的語言,以便我可以提供一些提示如何真正讓那麼快 - 基本上是一個在顯存加快位塊,但每一種語言都有它的方式來做到這一點)

enter image description here

當這個超級精靈的邊界是靠近屏幕邊緣比一個閾值(通常是一半瓦片),較大的精靈會在當前位置周圍重新繪製 - 但是不需要在這個上繪製所有的圖塊!開始複製這個重新生成的精靈上的supersprite,你只需要繪製由於偏移量而從前一個supersprite中丟失的圖塊。

enter image description here

+1

忘了在我的答案中提到這一點。所以+1。順便說一句,這被稱爲回緩衝或雙緩衝,而不是超級精靈......我的理解是,超級精靈用來結合層的精靈,以提高每個瓷磚基礎上的動畫性能,而不是陰影屏幕......但這個想法是正確的 – Spektre

+0

back/double buffering具有精確的含義,並且每幀都有一個後臺緩衝區,併爲前臺緩衝區交換 - 在這裏您創建一個預發佈的表單,之後您可以在後臺或前臺緩衝區上刷新 - 因此它是正交的 - 但想法是相似的,有圖形卡推最大像素,而不是CPU –

+0

嗯,我認爲你是正確的超滾動陰影屏幕完全不適合賬單... – Spektre