Опубликован: 28.04.2009 | Доступ: свободный | Студентов: 1840 / 107 | Оценка: 4.36 / 4.40 | Длительность: 16:40:00
Специальности: Программист
Лекция 1:

Введение в XNA Framework

Лекция 1: 123456789 || Лекция 2 >

Конфигурация Release в проектах C# по умолчанию настроена довольно оптимально и вам вряд ли придeтся еe менять. К сожалению, этого нельзя сказать о конфигурации Debug. Сейчас мы с вами это исправим. Активируйте конфигурацию Debug при помощи выпадающего списка на панели задач. Щелкните два раза на узле Properties во вкладке Solution, чтобы открыть вкладку свойств проекта10Эта вкладка, по сути, является визуальным редактором файла проекта (*.cjproj и т.п.) . (рисунок 1.11).

 Свойства проекта

увеличить изображение
Рис. 1.11. Свойства проекта

Для начала щeлкните на закладку Debug и включите флажок Enable unmanaged code debugging. Из названия нетрудно догадаться, что этот флажок включает отладку неуправляемого кода. Зачем это надо? Большинство классов сборки XNA Framework являются тонкими надстройками над COM -компонентами "обычного" DirectX11Данное утверждение может быть не верным для платформ, отличных от Windows . В результате при выключенной отладке неуправляемого кода Visual Studio 2005 не может получать информацию от COM -компонентов отладочной версии DirectX и, соответственно, выводить еe в окно Output.

Попробуйте включить эту опцию в примере Ch01\Ex02 (визуализация шахматной доски) и понаблюдать в окне Output за сообщениями отладочной версии DirectX (рисунок 1.12). Отметьте ощутимо возросшее время загрузки приложения.

 Окно Output

увеличить изображение
Рис. 1.12. Окно Output

В целом, окно Output в сочетании с опцией Enable unmanaged code Debugging является неплохой интегрированной альтернативой утилите Debug View, хотя и не лишенной ряда недостатков – очень низкой производительности и отсутствия поддержки в Visual C# 2005 Express.

Внимание

Даже если вы выбрали конфигурацию Release, Visual Studio при нажатии клавиши F5 ( Start with Debugging ) все равно запускает .NET -приложение под управлением отладчика, что ощутимо снижает быстродействия. Для полного отключения отладки необходимо запустить приложение на выполнение комбинацией клавиш Ctrl + F5 ( Start without debugging ).

Проверка переполнения

Вторая полезная опция, Check for arithmetic overflow/underflow, находится в диалоговом окне Advanced Build Setting, открываемом при помощи кнопки Advanced Build Setting в закладке Build (рисунок 1.13). Этот флажок включает проверку целочисленного переполнения для всей программы: если в ходе вычислений результат вдруг выйдет за пределы допустимого диапазона, то программа автоматически сгенерирует исключение System.OverflowException. Эта поможет сэкономить вам много времени и нервов, при поиске трудноуловимых ошибок вроде:

// Объявляем 16-битную переменную со знаком и присваиваем ей 32767
short a = 32767;
// Увеличиваем еe на 5. Из за переполнения переменная a станет 
равна -32764, а не 32772 !!!
a = (short) (a + 5);
// В итоге оператор WriteLine выведет на экран -32764
Console.WriteLine(a);
 Диалоговое окно Advanced Build Setting

Рис. 1.13. Диалоговое окно Advanced Build Setting

Так как проверка переполнения несколько снижает производительность программы, еe рекомендуется выключать в конфигурации Release. Если же у вас имеется потенциально опасный код, в котором может произойти переполнение, поместите его во внутрь блока checked. Например:

checked {
a = (short) (a + 5);
 }

Остальные особенности конфигурирования проектов C# мы рассмотрим в следующих разделах по мере необходимости. Более подробную информацию по этой теме можно найти в [К.7], [К.8] и [К.9].

1.2.3. Изменение размеров окна

Запустите на выполнение нашу программу, рисующую шахматную доску ( Ex02 ) и попробуйте поизменять размеры окна. Думаю, вы быстро заметите, что с программой что-то не так. При уменьшении размеров окна шахматная доска не масштабируется, в результате чего изображение начинает выглядеть как-то странновато (рисунок 1.14). А при увеличении окна изображение шахматной доски искажается непонятным образом (рисунок 1.15).

Некорректная реакция программы на уменьшение размера окна

Рис. 1.15. Некорректная реакция программы на уменьшение размера окна
Некорректная реакция программы на увеличение размера окна

Рис. 1.15. Некорректная реакция программы на увеличение размера окна

Как гласит народная мудрость, за двумя зайцами погонишься – ни одного не поймаешь. Поэтому для начала мы сосредоточимся на первой проблеме – неизменном размере шахматной доски при уменьшении формы. Эта проблема вызвана тем, что по умолчанию Windows Forms не гарантирует вызов события Paint при изменении размеров формы. В принципе, для борьбы с этим недоразумением мы могли бы добавить в обработчик события Resize12Событие Resize генерируется при изменении размеров формы вызов метода Invalidate, генерирующего событие Paint.

Однако существует гораздо более элегантное решение: если установить у формы стиль ResizeRedraw, то при изменении размера формы будет автоматически генерироваться событие Paint. Для этого добавьте в обработчик Load строку:

SetStyle(ControlStyles.ResizeRedraw, true);

Попробуйте ещe раз запустить программу на выполнение. И что мы видим? Хотя теперь приложение и реагирует на изменение размера окна, появились новая, гораздо более неприятная проблема – при изменении размеров окна форма непрерывно мерцает. Чтобы понять причину этого явления попробуйте изменить цвет формы на зелeный (свойство BackColor ) и снова запустите на выполнение. Мерцания шахматной доски обретут зеленоватый оттенок.

Итак всe дело в том, что перед вызовом обработчика события Paint класс Form вызывает виртуальный метод OnPaintBackground, который по умолчанию очищает экран цветом BackColor. Эта функциональность позволяет разработчику, использующему GDI+, не заботится об очистке экрана, однако в нашем случае такая "самовольная" очистка формы приводит лишь к мерцанию. Следовательно, нам необходимо каким-нибудь образом запретить форме закрашивать экран перед вызовом обработчика события Paint. Первое, что приходит в голову - перегрузить метод OnPaintBackground protected override void OnPaintBackground(PaintEventArgs pevent)

{
 // Ничего не делаем 
}

Впрочем, если покопаться в документации, можно найти и более изящное решение проблемы. Если установить у формы стиль ControlStyles.Opaque, то форма не будет автоматически закрашивать фон, что собственно нам и нужно: SetStyle(ControlStyles.Opaque, true ); После добавления этой строки в обработчик события Load мерцания наконец-то исчезнут.

Итак, первую проблему мы решили, но осталась вторая, гораздо более неприятная - некорректное масштабирование шахматной доски при изменении размера окна. На первый взгляд проблема возникает буквально на пустом месте - мы задаeм параметры двойной буферизации и вспомогательных буферов, создаeм новое устройство, после чего перерисовываем экран в обработчике события Paint. Вроде бы ничего противозаконного мы не делаем… Стоп! При создании графического устройства мы задаeм размер вспомогательного буфера, используемого при двойной буферизации, равный размеру клиентской области окна, что вполне логично. Когда мы изменяем размер окна, его клиентская область так же изменяется. А вот размер вспомогательного буфера остаeтся неизменным - мы ведь задаeм его размер только один раз в обработчике события Load. Получается что, при изменении размеров окна происходит рассинхронизация между размером клиентской области окна и вспомогательного буфера, в котором собственно рисуется изображение, после чего приложение естественно начинает работать некорректно.

Следовательно, нам необходимо добавить в программу коррекцию размера вспомогательного буфера при изменении размера окна. В XNA Framework эта операция выполняется с использованием метода Reset класса GraphicsDevice:

public void Reset(params PresentationParameters[] 
presentationParameters);

где

  • presentationParameters - набор структур PresentationParameters, описывающих новое представление данных на экране. Каждому монитору соответствует своя структура PresentationParameters.

Итак, нам придeтся вынести локальную переменную PresentationParameters presentParams за пределы метода Load (то есть сделать еe полем класса MainForm ) и добавить в обработчик события Resize изменение высоты и ширины вспомогательного буфера структуры presentParams с последующим вызовом метода Device.Reset (листинг 1.5).

private void MainForm_Resize(object sender, EventArgs e)
{
// Задаем новые размеры буфера глубины
presentParams.BackBufferWidth = ClientSize.Width;
presentParams.BackBufferHeight = ClientSize.Height; 
// Применяем новые параметры к устройству
device.Reset(presentParams);
 }
Листинг 1.5. Листинг 1.5

Примечание

Сброс устройства является очень медленной операцией. Никогда не вставляйте еe без причины в обработчик события Paint, так как это приведeт к заметному падению производительности.

Лекция 1: 123456789 || Лекция 2 >
Андрей Леонов
Андрей Леонов

Reference = add reference, в висуал студия 2010 не могу найти в вкладке Solution Explorer, Microsoft.Xna.Framework. Его нету.