Я портировал шутер со скроллингом, созданный на XNA, на Linux с помощью MonoGame. Почти все прошло гладко, но у меня в одном месте проблема с вызовами SpriteBatch.Draw (), снижающими частоту кадров. Большая часть игры проходит нормально, без сбоев. Он притягивает большое количество врагов и большое количество пуль одновременно без замедления. Однако часть, которая вызывает выпадение кадров, - это многоуровневый фон прокрутки. Соответствующие разделы кода находятся здесь.
Level.cs:
public void Draw(SpriteBatch spriteBatch)
{
foreach (ScrollingBackgroundLayer sbl in scrollingBackground)
{
sbl.Draw(spriteBatch);
}
}
Вышеупомянутый scrollingBackground - это список ScrollingBackgroundLayers, соответствующие разделы которого:
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);
}
}
Все проблемы с частотой кадров исчезнут, как только я закомментирую вызов ScrollingBackgroundLayer.Draw (), так что, похоже, это довольно большой намек на то, что проблема исходит из попытки SpriteBatch нарисовать прокручиваемые слои. Очевидно, я хочу выяснить, почему это происходит. Я изучил некоторые другие проблемы с SpriteBatches, и наиболее распространенная вещь, которую я обнаружил, которая может указывать на ответ, - это тот факт, что новый SpriteBatch создается всякий раз, когда изменяется текстура, но даже установка SpriteSortMode на Texture не дала никаких улучшений.
Уменьшение частоты кадров происходит на этапе игры с 7 различными слоями ScollingBackgroundLayers, каждый из которых рисует отдельную текстуру шириной около 700 пикселей и высотой 900 пикселей (каждый слой должен делать это не более 2 раз, чтобы учесть эффект прокрутки). . Я чувствую, что мне не хватает чего-то очевидного, потому что игра иногда отображает до 2-300 пуль, используя ту же самую перегрузку, поэтому еще 14 вызовов должны быть каплей в море. Это просто проблема с попыткой нарисовать текстуры, слишком большие для того, чтобы SpriteBatch мог эффективно справиться с ними? Это не проблема для версии для Windows, поэтому мне интересно, нет ли какого-либо обходного пути для конкретной платформы, или реализация Draw в MonoGame просто неэффективна. Любые отзывы приветствуются.
Полный исходный код для заинтересованных:
Linux - https://github.com/cmark89/AsteroidRebuttal-Linux
Windows - https://github.com/cmark89/AsteroidRebuttal
Изменить: я попытался немного повозиться с этим. Я изменил вызов на Draw (), чтобы убедиться, что целевой прямоугольник равен доступной для рисования области экрана, но заметных изменений не произошло. Я поменял текстуру на очень маленькую, и это устранило задержку, так что я предполагаю, что это как-то связано с размером текстуры.
Редактировать 2: Хорошо, я закончил тем, что просто укусил пулю и разрезал слои прозрачности, которые я использовал (как какой-то не-ленивый парень). Он решил проблему, по-видимому, поскольку ему больше не нужно отображать огромное количество бесполезных пикселей, но он все еще заставляет меня задуматься, почему это проблема только в Linux. Несмотря на то, что я решил свою проблему на данный момент, я собираюсь оставить это открытым на всякий случай, если кто-то знает, что может вызвать резкую разницу в производительности.