2013-06-07 52 views
5

Tôi đã chuyển một trò chơi bắn súng cuộn mà tôi đã thực hiện trong XNA qua Linux bằng MonoGame. Hầu như tất cả mọi thứ đã diễn ra suôn sẻ, nhưng tôi đang gặp vấn đề ở một nơi cụ thể với các cuộc gọi tới SpriteBatch.Draw() làm tê liệt tốc độ khung hình. Hầu hết các trò chơi chạy tốt mà không có bất kỳ trục trặc. Nó rút ra một số lượng tốt của kẻ thù và số lượng lớn đạn cùng một lúc mà không có bất kỳ sự chậm lại. Tuy nhiên, phần gây ra khung bị rớt là nền cuộn được xếp lớp. Các phần mã có liên quan ở đây.Tốc độ khung hình thấp của Monogame XNA từ một số cuộc gọi Draw()

Level.cs:

public void Draw(SpriteBatch spriteBatch) 
{ 
    foreach (ScrollingBackgroundLayer sbl in scrollingBackground) 
    { 
     sbl.Draw(spriteBatch); 
    } 
} 

Các "scrollingBackground" ở trên là danh sách các ScrollingBackgroundLayers, các phần có liên quan trong đó là:

ScrollingBackgroundLayers.cs:

Vector2[] scrollingBackgroundImages; 
public float DrawLayer; 

public ScrollingBackgroundLayer(GameScene newScene, Texture2D texture, float scrollSpeed, Color color) 
{ 
    layerColor = color; 
    layerSpeed = scrollSpeed; 
    layerTexture = texture; 
    thisScene = newScene; 

    Initialize(); 
} 

public void Initialize() 
{ 
    scrollingBackgroundImages = new Vector2[2]; 

    for (int i = 0; i < 2; i++) 
    { 
     scrollingBackgroundImages[i] = new Vector2(0, thisScene.ScreenArea.Height - (layerTexture.Height * i)); 
    } 
} 


public void Update(GameTime gameTime) 
{ 
    for (int i = 0; i < scrollingBackgroundImages.Length; i++) 
    { 
     scrollingBackgroundImages[i].Y += (float)gameTime.ElapsedGameTime.TotalSeconds * layerSpeed; 

     if (layerSpeed > 0 && scrollingBackgroundImages[i].Y >= thisScene.ScreenArea.Height) 
     { 
      scrollingBackgroundImages[i] = new Vector2(scrollingBackgroundImages[i].X, (scrollingBackgroundImages[i].Y - layerTexture.Height * 2)); 
     } 
     else if (layerSpeed < 0 && scrollingBackgroundImages[i].Y + layerTexture.Height <= 0) 
     { 
      scrollingBackgroundImages[i] = new Vector2(scrollingBackgroundImages[i].X, (scrollingBackgroundImages[i].Y + layerTexture.Height * 2)); 
     } 
    } 
} 

public void Draw(SpriteBatch spriteBatch) 
{ 
    foreach (Vector2 sb in scrollingBackgroundImages) 
    { 
     spriteBatch.Draw(layerTexture, sb, null, layerColor, 0f, Vector2.Zero, 1f, SpriteEffects.None, DrawLayer); 
    } 
} 

Tất cả các vấn đề về tốc độ khung hình biến mất ngay sau khi tôi nhận xét cuộc gọi tới ScrollingBackgroundLayer.Draw(), do đó dường như là một gợi ý khá lớn về sự cố đến từ S PriteBatch cố gắng vẽ các lớp cuộn. Rõ ràng, tôi muốn tìm ra lý do tại sao điều này đang xảy ra. Tôi đã xem xét một số vấn đề khác với SpriteBatches và điều phổ biến nhất mà tôi thấy có thể hướng tới câu trả lời là một SpriteBatch mới được tạo bất cứ khi nào texture được thay đổi, nhưng thậm chí thiết lập SpriteSortMode thành Texture cũng không có cải tiến nào. Sự giảm tốc độ khung hình xảy ra trên một giai đoạn của trò chơi có 7 ScollingBackgroundLayers khác nhau, mỗi hình vẽ có một kết cấu riêng biệt rộng khoảng 700 pixel và 900 cao (mỗi lớp nên làm điều này không quá 2 lần để tính đến hiệu ứng cuộn). Tôi cảm thấy như tôi phải thiếu một cái gì đó hiển nhiên, bởi vì các trò chơi đôi khi ám đến 2-300 viên đạn bằng cách sử dụng cùng một quá tải chính xác, do đó, 14 cuộc gọi khác sẽ là một giọt trong xô. Đây có phải chỉ đơn giản là một vấn đề với cố gắng để rút ra kết cấu quá lớn cho SpriteBatch để có hiệu quả xử lý? Đây không phải là một vấn đề trên phiên bản Windows, vì vậy tôi tự hỏi nếu không có một số nền tảng cụ thể workaround này, hoặc nếu MonoGame của việc thực hiện Draw chỉ là không hiệu quả. Bất kỳ thông tin phản hồi sẽ được chào đón.

nguồn đầy đủ cho những người quan tâm:

Linux - https://github.com/cmark89/AsteroidRebuttal-Linux
Windows - https://github.com/cmark89/AsteroidRebuttal

Edit: Tôi cố gắng mày mò với nó hơn một chút. Tôi đã thay đổi cuộc gọi thành Draw() để đảm bảo rằng hình chữ nhật đích bằng với khu vực có thể kéo được của màn hình, nhưng không có thay đổi đáng chú ý. Tôi đổi texture thành một cái rất nhỏ và loại bỏ độ trễ, vì vậy tôi đoán nó có liên quan đến kích thước của texture.

Chỉnh sửa 2: Được rồi, tôi vừa mới cắn viên đạn và cắt các lớp trong suốt mà tôi đang sử dụng (giống như một người không lười biếng). Nó giải quyết vấn đề, có lẽ vì nó không còn phải render số lượng lớn các pixel vô dụng, nhưng nó vẫn khiến tôi tự hỏi tại sao đây chỉ là một vấn đề trên Linux. Mặc dù tôi đã giải quyết được vấn đề của mình trong thời gian này, tôi sẽ để nó mở một chút trong trường hợp ai đó có bất kỳ cái nhìn sâu sắc về những gì có thể gây ra sự khác biệt về hiệu suất quyết liệt.

+1

Tôi không thể nhớ chi phí hiệu suất cho những thứ khác nhau nhưng buộc GPU phải vẽ nhiều họa tiết có độ phân giải cao có lẽ không phải là ý tưởng hay và bạn có thể thiết kế theo cách khác. Nếu bộ nhớ phục vụ cho tôi, những kết cấu đó sẽ kết thúc là 1024 * 1024 kết cấu (do sức mạnh của 2 yêu cầu và làm lại thành kích thước đó trong suốt thời gian chạy) khi được gửi tới GPU. –

+0

Vấn đề trong trường hợp này là mỗi hình ảnh của nền cuộn với tốc độ khác nhau hoặc có mức độ minh bạch khác nhau. Một số người trong số họ tôi chắc chắn có thể chop lên và tạo ra các lớp vẽ trong các khu vực nhỏ hơn của màn hình, nhưng một số người trong số họ (chủ yếu là các lớp minh bạch) không phải là dễ dàng như vậy. Tôi không biết rằng GPU đã thay đổi kích thước không quyền lực của hai kết cấu; có lẽ tôi sẽ thay đổi kích thước chúng và xem nó có thay đổi gì không. Không phân biệt các tối ưu hóa mà tôi sẽ xem xét, tôi thực sự bối rối vì sao vấn đề này không xảy ra trên Windows. – cmark89

Trả lời

2

Trong trường hợp này, tôi khuyên bạn nên sử dụng trình đổ bóng để thay thế. Bạn sẽ thấy hiệu suất của bạn tăng vọt bằng cách làm điều này.Hãy xem ví dụ sau:

http://www.david-gouveia.com/scrolling-textures-with-zoom-and-rotation/

Làm theo cách này, sẽ giảm bớt rất nhiều sử dụng CPU, GPU và làm cho bạn làm phần lớn công việc.

Bạn cũng có thể muốn lưu trữ hoạ tiết của mình có sức mạnh là 2, thay vì 700x900. (làm một cái gì đó như 512x512). Đường ống đồ họa của bạn có hiệu suất tăng liên quan đến kết cấu có sức mạnh của hai.

+0

Tôi đang xem xét điều này, nhưng nó có thể là quá mức cần thiết cho những gì tôi cần làm. Có lẽ đó chỉ là vì bóng râm làm tôi kinh ngạc. Tôi sẽ liên lạc lại với bạn khi tôi có cơ hội thử nó. – cmark89

+0

Đây không phải là quá mức cần thiết, tôi đảm bảo với bạn nó rất đơn giản. Bạn thậm chí không cần phải biết bất cứ điều gì về shaders để có được điều này để làm việc;) – jgallant

+0

Đã không nhận được xung quanh để cố gắng này kể từ khi tôi đã kết thúc chỉ bằng cách sử dụng một công việc đơn giản xung quanh, nhưng vì đây là câu trả lời duy nhất tôi đánh dấu nó như được chấp nhận. Nó thực sự trông giống như một giải pháp rất tốt đẹp nếu bạn có thể nhận được các tập tin hiệu quả để làm việc (tiếp tuyến, điều này dường như là một thử thách với phiên bản hiện tại của MonoGame, đó là lý do tại sao tôi đã không thử nó). – cmark89

Các vấn đề liên quan