XNA 3.1 до 4.0 требует постоянного перерисования или отобразит фиолетовый экран

StackOverflow https://stackoverflow.com/questions/4235439

  •  26-09-2019
  •  | 
  •  

Вопрос

Для меню в моей игре я рисую их один раз на экран, а затем только перерисовал, если они считаются грязными. Это обрабатывается через логическое значение для true, всякий раз, когда пользователь выполняет действие, которое должно вызывать перерисование, а затем цикл для вытягивания проверит это значение, прежде чем рисовать меню. Эта логика отлично работала в 3.1, но в 4.0 меню будет мерцать (нарисовано для 1 рамы), затем показать фиолетовый экран, пока снова нарисован.

Я создал очень простую тестовую игру в 4.0, чтобы продемонстрировать проблему, показанную ниже. Вы заметите, что экран просто выглядит фиолетовым. Если вы удалите настройку строки _isdirty до false, вы увидите синюю предпосылку васильфорша.

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    bool _isDirty = true;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
    }
    protected override void Draw(GameTime gameTime)
    {
        if (_isDirty)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            _isDirty = false;
        }
        base.Draw(gameTime);
    }
}

Как бы я пошел, получая поведение от XNA 3.1? Я видел несколько людей, упомянувших серверы, но это не имеет никакого эффекта в 4.0, если я не применяю его неправильно.

Это было полезно?

Решение

Вот грубый обзор того, что называется в ггной игре:

Update
BeginDraw
Draw
EndDraw

Реализация по умолчанию EndDraw в конечном итоге звонит GraphicsDevice.Present. Отказ С включенной двойной буферией это сводится к спине и передние буферы.

Так что происходит:

  • Первый раз вокруг: вы рисуете вашу сцену к задним буфере, а затем отпустить XNA на передней.

  • Второй раз вокруг: вы ничего не рисовали, оставив поверхность, наполненную фиолетовым цветом, который DirectX инициализирует эти поверхности, и замена это спереди!

  • Последующие времена: вы ничего не рисуете, поэтому вы увидите мерцание дисплея между этими двумя поверхностями.

Существует несколько способов подавления рисунка в XNA. Я иду над ними в Этот ответ на аналогичный вопрос. Отказ Как и в этом ответе, я рекомендую переопределить Begindraw, как так:

protected override bool BeginDraw()
{
    if(_isDirty)
        return base.BeginDraw();
    else
        return false;
}

Когда BeginDraw Возвращает false, Draw а также EndDraw (и так Present) не будет называться этой рамкой. Ничто не будет рисовать, а буферы фронта / задней части не поменяются.

Другие советы

Я недавно наткнулся на это тоже; Я не думаю, что это проблема с листыми буферами. Это должно быть то же самое в 3.1 и 4.0. Я посмотрел на GraphicsDevice с Ilspy и узнал это:

То, что изменилось, в том, что в 4.0 текущая цель рендеринга сначала очищается в GraphicateDevice.present (), если установлен личный флаг. По умолчанию этот флаг будет установлен изначально (рендеринг цели чисто). Рисунок в цель рендеринга очищает этот флаг (рендеринг цели сейчас грязно). После выполнения дежурства, GraphicsDevice.present () снова устанавливает флаг (рендеринг цели был «покрасен» к вашему окну и теперь снова считается чистым).

Чтобы получить результаты от GraphicsDevice.present (), вам нужно позвонить на рисовать () и enddraw () в строгой последовательности.

Если вы вызываете EndDraw () без предварительного вызова, чтобы нарисовать (), вы не получите содержимое цели рендеринга (что устанавливается), вместо этого можно получить только фиолетовый экран.

К сожалению, флаг является частным, и нет чистого способа добраться до него. Вы можете использовать отражение для очистки такого такого флага, принудительно принуждение целевой целевой цели, не рисуя ничего в нее:

GraphicsDevice.gettype (). Getfield («LazyclearFlags», BindingFlags.nonpublic | BindingFlags.Instance) .stebalue (GraphicsDevice, 0);

(GraphicsDevice - ваш текущий экземпляр графических данных)

Поместите вышеуказанную линию перед вызовом в EndDraw (), и поведение возвращается к тому, что было в 3.1

В моем конкретном случае у меня есть государственная машина, которая переключается между состояниями, которые несут ответственность за рисунок. Поэтому, когда я перехожу между двумя игровыми состояниями, нечего рисовать, и экран мигает фиолетовым, пока не будет активно следующее игровое состояние.

Что я сделал, чтобы решить, что это было просто, в обновлении, если у меня нет состояния, позвоните SupressDraw () Метод в игровом объекте. Это предотвращает проведение рисунка до тех пор, пока не произойдет следующее обновление.

Я полагаю, что нет ничего останавливать вас от того, что вы всегда называете его в обновлении, за исключением случаев, когда вы устанавливаете флаг ISDIRTY. Но вы должны были быть готовы обрабатывать другие события / случаи, когда экран может быть разбитым.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top