Reference = add reference, в висуал студия 2010 не могу найти в вкладке Solution Explorer, Microsoft.Xna.Framework. Его нету. |
Введение в XNA Framework
После такой модернизации наша программа наконец-то заработала без ошибок. Хотя так ли это? Как гласит известная пословица, в каждой программе есть как минимум одна ошибка. Наша программа не исключение. Попробуйте из интереса уменьшить еe размер до минимума. Как только высота клиентской области окна станет меньше одного пикселя, в окне Output появятся сообщения от отладочной версии DirectX, а программа аварийно завершится с исключением:
Direct3D9: (ERROR) :Failed to create driver surface Direct3D9: (ERROR) :Reset failed and Reset/TestCooperativeLevel/Release are the only legal APIs to be called subsequently A first chance exception of type 'Microsoft.DirectX.Direct3D. DriverInternalErrorException' occurred in Microsoft.DirectX.Direct3D.dll
Поведение Direct3D вполне логично, ведь попытка вывести изображение на форму с клиентской областью размером менее одного пикселя выглядит, мягко говоря, довольно странной. Однако пользователя такое оправдание вряд ли обрадует, поэтому неплохо бы обезопаситься от подобных казусов, ограничив минимальный размер клиентской области одним пикселем. Это легко можно сделать при помощи свойства MinimumSize, которое задаeт минимальные размеры окна. Правда задание этого свойства во вкладке Properties не самая лучшая идея - область, отводимая формой под клиентскую область, зависит от множества факторов: установленной операционной системы, пользовательских настроек и т.п. Гораздо надeжнее вычислять его прямо в обработчике события Load посредством метода формы SizeFromClientSize, который возвращает размер окна при заданном размере клиентской области:
// Вычисляем размер окна при клиентской области 1x1 пиксель. Полученное значение присваиваем // свойству MinimumSize MinimumSize = SizeFromClientSize(new Size(1, 1)) ;
Ещe одной ошибкой стало меньше. Думаю, вы уже убедились, что написать приложение без единой ошибки для такой сложной операционной системы, как Windows,не так уж и просто. Всегда существует вероятность пропустить какой-нибудь нюанс. Например, мы до сих пор не пробовали минимизировать окно при помощи соответствующей стандартной кнопки в правом верхнем углу окна. Попробуйте нажать эту кнопку, и в обработчике события Resize тут же произойдeт исключение - приложение попытается установить размер заднего буфера равным 0 на 0 пикселей. Такое поведение программы обусловлено тем, что при минимизации окна программы Windows уменьшает его размер до нуля пикселей. Следовательно, нам необходимо вставить в обработчик события Resize проверку состояния окна - если окно минимизировано, то программа не должна пытаться изменять размер заднего буфера:
private void MainFormResize(object sender, EventArgs e) { // Если окно не минимизировано, то изменяем размер заднего буфера и сбрасываем устройство if (WindowState != FormWindowState.Minimized) { presentParams.BackBufferWidth = ClientSize.Width; presentParams.BackBufferHeight = ClientSize.Height; device.Reset(presentParams); } }Листинг 1.6. Листинг 1.6.
Вот теперь наша программа похоже уже не содержит явных ошибок13Некоторые ошибки всe же остались, и мы в этом убедимся в следующем разделе (1.2.4) . Полный текст полученного приложения приведeн в листинге 1.7 (Ex03).
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows. Forms ; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Xna = Microsoft.Xna.Framework; using XnaGraphics = Microsoft.Xna.Framework.Graphics; namespace GSP.XNA.Book.Ch01.Ex03 { public partial class MainForm : Form { GraphicsDevice device=null; PresentationParameters presentParams ; public MainForm() { InitializeComponent(); } private void MainFormLoad(object sender, EventArgs e) { SetStyle(ControlStyles.Opaque | ControlStyles.ResizeRedraw, true); MinimumSize = SizeFromClientSize(new Size(1, 1)); presentParams = new PresentationParameters(); presentParams.IsFullScreen = false; presentParams.BackBufferCount = 1; presentParams.SwapEffect = SwapEffect.Discard; presentParams.BackBufferWidth = ClientSize.Width; presentParams.BackBufferHeight = ClientSize.Height; device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.Handle, CreateOptions.SoftwareVertexProcessing | CreateOptions.SingleThreaded, presentParams) ; } private void MainFormPaint(object sender, PaintEventArgs e) { device.Clear(ClearOptions.Target, XnaGraphics.Color.WhiteSmoke, 0.0f, 0); Xna.Rectangle[] rects = new Xna.Rectangle[32]; int k = 0; for (int j = 0; j < 8; j++) for (int i = j % 2; i < 8; i += 2) { rects[k] = new Xna.Rectangle(i * ClientSize.Width / 8, Ь j * ClientSize.Height / 8, ClientSize.Width / 8, ClientSize.Height / 8); k++; } device.Clear(ClearOptions.Target, XnaGraphics.Color.Brown, 0.0f, 0, rects); device.Present(); } private void MainForm_Resize(object sender, EventArgs e) { if (WindowState != FormWindowState.Minimized) { presentParams.BackBufferWidth = ClientSize.Width; presentParams.BackBufferHeight = ClientSize.Height; device.Reset(presentParams); } } private void MainForm_FormClosed(object sender, FormClosedEventArgs e) { if (device != null) { device.Dispose(); device = null; } } } }Листинг 1.7.
Обратите внимание на применение псевдонимов для пространств имен Microsoft.Xna.Framework и Microsoft.Xna.Framework.Graphics , позволившие упростить обращение к структурам Microsoft.Xna.Framework.Color и Microsoft.Xna.Framework.Graphics.Rectangle . Обычная директива using прошлых версий C# в подобных ситуация оказывалась бессильной из-за конфликта с одноименными структурами из пространства имен System.Drawing .
Практическое упражнение №1.1.
Создайте приложение, рисующее на экране 10 вложенных разноцветных прямоугольников (рисунок 1.14). Самый крупный прямоугольник должен иметь синий цвет, а самый маленький зелeный. Остальные прямоугольники имеют промежуточные цвета, образуя плавный переход от синего к зелeному. Приложение должно корректно реагировать на изменение размера экрана.
Примечание
Если у вас возникнут трудности при выполнении этого упражнения, вы можете посмотреть исходный текст готового приложения, которое находится в example.zip в каталоге Ch01\Ex04 .
Для вычисления промежуточных значений цвета воспользуйтесь конструктором public Color(byte r, byte g, byte b) , создающим структуру Color на основе значений красного, зеленого и синих цветов. Значения цветов находятся в диапазоне 0…255 (0 – минимальная яркость, 255 – максимальная яркость).