2013-05-15 3 views
14

Я сделал просмотрщик изображений XNA, но он всегда перерисовывает сцену, даже если она не меняется, и это заставляет мой нетбук сгореть, как ад, поэтому я хотел бы сделать паузу при рисовании, когда ничего не меняется.Как приостановить перерисовку в XNA?

Уменьшение частоты кадров до 1 - это один из способов сохранить ее в прохладном состоянии, но это приводит к задержке выхода.

Как предотвратить перерисовку, пока нет ввода?


Эта проблема была решена, но другая проблема была найдена - игра потребляет много ресурсов процессора, когда окно находится в фокусе, но когда это не так, она занимает лишь около 1% от CPU. Смотрите этот вопрос подробно о том, как решить эту другую проблему:

How to reduce XNA game CPU usage while nothing worth computing is happening?

+0

Это было быстрое понижение и закрытое голосование. Помогите улучшить вопрос? – user1306322

+3

Было бы хорошо, если бы люди оставляли комментарии, чтобы объяснить их downvotes. Это кажется вполне законным вопросом с определенным ответом. –

ответ

10

Вы можете использовать метод Game.SupressDraw для этой цели. Из замечаний по ссылке:

Вызовите этот метод во время обновления, чтобы предотвратить вызовы Draw до следующего вызова Update. Этот метод можно использовать на небольших устройствах для экономии времени автономной работы, если дисплей не изменился в результате обновления. Например, если экран статичен без фоновой анимации, вход игрока может быть проверен во время обновления, чтобы определить, выполняет ли игрок какое-либо действие. Если вход не обнаружен, этот метод позволяет пропустить рисунок до следующего обновления.

В качестве примера, следующий код вызывает только функцию Draw. Когда я протестировал это, я заметил, что использование ЦП было высоким (70%) без вызова SuppressDraw. При использовании SupressDraw использование ЦП резко сократилось (до менее 15%). Ваши номера могут отличаться.

public class Game1 : Microsoft.Xna.Framework.Game 
{ 
    ... 
    private bool _drawn = false; 
    protected override void Update(GameTime gameTime) 
    { 
     if (_drawn) 
      SuppressDraw(); 
    } 

    protected override void Draw(GameTime gameTime) 
    { 
     GraphicsDevice.Clear(Color.CornflowerBlue); 
     spriteBatch.Begin(); 
     /* draw stuff here */ 
     spriteBatch.End(); 

     _drawn = true; 
    } 
    ... 
} 

SupressDraw Обратите внимание, что подавляет только один Draw вызов. Чтобы предотвратить больше звонков на Draw, вы должны постоянно звонить SupressDraw в Update. Надеюсь, это имеет смысл.

+0

Это определенно работает, хотя это не спасает меня от большого количества CPU, как я надеялся. Анализ производительности говорит о том, что при каждом подаче кадра дроби, основной метод обновления получает все внимание, но все же он стоит столько же CPU, как раньше.На мой вопрос задан ответ, но мне все еще нужно знать, как снизить стоимость процессора почти ничего. – user1306322

+0

@ user1306322 - не видя своего кода, сложно дать ответ о том, почему использование вашего ЦП не уменьшилось. Как вы можете видеть с моим ответом выше, это ** уменьшило время процессора моей выборки - от 70% до примерно 15%. –

+0

Как вы сказали - процент варьируется. Я предполагаю, что вызов Draw фактически не потреблял сколько-нибудь значительного количества ресурсов, тогда как все приложение использовало столько, сколько могло бы (и до сих пор). Таким образом, в основном это стало еще одной проблемой - определение того, что именно потребляет процессор, пока ничего особенного не происходит, кроме ожидания ввода и рисования кадра 60 раз в секунду. – user1306322

0

Как говорится в принятом ответе, вы можете использовать SuppressDraw, чтобы избежать рисования неизмененного кадра. Однако ваш метод Update будет работать независимо от того, почему он все еще использует больше процессора, чем вы ожидаете. Чтобы избежать использования как можно большего количества CPU, вам нужно как-то избежать обновления вещей, которые, как вы знаете, не изменились с момента последнего кадра.

Я полагаю, вы знаете, это точно так же, как вы знаете, когда для подавления дро, так что вам нужно сделать, это изменить свой Update-метод, как это:

private void Update(GameTime gameTime) 
{ 
    var frameHasChanges = DetectChanges(); //This method you need to figure out yourself 
    if (!frameHasChanges) 
    { 
     SuppressDraw(); 
     base.Update(gameTime); 
     return; 
    } 

    //Do the rest of normal Update 

} 

В качестве последнего замечания; Мне никогда не приходилось использовать это в любой игре, которую я когда-либо делал. Я считаю, что у вас может быть и другая, основная проблема с производительностью. Однако я использовал много методов, чтобы избежать рендеринга текста и т. Д. На каждом кадре (вызывает бокс/распаковку). Спросите об этом в комментарии, если хотите узнать больше.

+0

Хотя в этом конкретном случае, как я уже сказал в этом случае, метод обновления очень прост, и он не может запугать весь процессор только для проверки наличия изменений в состояниях ввода (и это не так, я проверил четыре раза). Решение было найдено с помощью другого вопроса к проблеме, возникшей после решения проблемы отсутствия повтора в этом вопросе. См. Сноски для деталей. – user1306322

Смежные вопросы