Александр Ложечкин Сергей Гайдуков. XNA Framework на платформе Windows.NET Compact Framework for Xbox 360 Компоненты XNA Framework Оптимизация XNA-приложений.

Презентация:



Advertisements
Похожие презентации
Microsoft TechDays Виталий Дильмухаметов Oogway software.
Advertisements

Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Язык программирования C# Дмитрий Сошников
©Павловская Т.А. (СПбГУ ИТМО) Курс «С#. Программирование на языке высокого уровня» Павловская Т.А.
Наследование Наследование – это отношение является между классами. class Person { string first_name; int birth_year;... } class Student : Person { float.
Виды проектов Visual Studio.Net 2012 предлагает различные шаблоны для ваших начальных проектов. Основные поддерживаемые языки программирования: С#, C++,
Тема 5. Введение в среду визуального программирования Borland Delphi 7.0.
Слезко Полина Сергеевна Учитель информатики Белоярской СОШ Томской области.
ДонНУ, кафедра КТ, проф.В.К.Толстых WCF-службы Создание и тестирование.dll-библиотеки WCF-служб Из цикла лекций «Internet-технологии разработки приложений»
АССОЦИАТИВНЫЕ КОЛЛЕКЦИИ Лекция 6 1. Отличие от последовательных 2 В последовательной коллекции каждый элемент ассоциируется с номером, начиная с 0. В.
Высокоуровневые методы информатики и программирования Лекция 9 Делегаты.
Тема 5. Основы современной технологии программирования Программирование в средах современных информационных систем. Интегрированные системы разработки.
Коллекции классов Лекция 12. С помощью коллекций вместо создания структур данных программист использует готовые структуры данных, не заботясь об их реализации.
Обработка исключительных ситуаций Исключительная ситуация (исключение) – это ошибка, возникающая во время выполнения программы. Например, ошибка работы.
Обобщения ( generics) Обобщения – это классы, структуры, интерфейсы и методы, в которых некоторые типы сами являются параметрами. Эти типы перечисляются.
Особенности C# Индексаторы, события, частичные методы, расширяющие методы, сборщик мусора DraggonZ.
САОД кафедра ОСУ 1 Основные абстрактные типы данных Схема процесса создания программ для решения прикладных задач ВУ.
Microsoft.NET Первая лекция. COM Доступ к компонентам только через интерфейсы Назначение уникальных идентификаторов компонентам и интерфейсам Регистрация.
Основы ООП и C# Работа с объектами и классами. Классы Класс специальный тип данных для описания объектов. Он определяет данные и поведение типа. Определение.
1 Умение мыслить объектно (проектирование архитектуры) Культура кодирования Знание языка и технологий Знание языка и технологий Понимание процесса Задача.
Транксрипт:

Александр Ложечкин Сергей Гайдуков

XNA Framework на платформе Windows.NET Compact Framework for Xbox 360 Компоненты XNA Framework Оптимизация XNA-приложений XNA Framework и Windows Forms

Инструментарий разработки игровых приложений для платформ –Windows Windows XP x86 Home/Pro/MCE/Tablet Windows XP x64 (посредством WOW64) Windows Vista (с Visual C# 2005 Express SP1) Windows Server 2003 (*) –Xbox 360 Сферы применения –Casual Games –Прототипы игр –Demo –Утилиты –Образование

Кроссплатформенный API для разработки игровых приложений –Не привязан к Windows Основан на платформе.NET Framework –.NET Framework 2.0 (Windows) –.NET Compact Framework for Xbox 360 –Mono (Linux)

Компоненты для разработки приложений Компоненты для распространения приложений –Очень просто интегрируются в дистрибутив приложения средствами Visual Studio 2005 Pro Компонент Размер дистрибутива Visual C# Express SP1440MB + (24-53MB) XNA Game Studio Express 1.081MB.NET Framework 1.123MB Компонент Размер дистрибутива.NET Framework – 27MB XNA Framework 1.02MB Обновление D3DX, XACT, XINPUT 4MB

Отличия от.NET Framework 2.0: –Значительно меньшие требования к ресурсам компьютера –Является подмножеством.NET Framework (содержит примерно 30% классов) –Ограниченная поддержка web-приложений и баз данных –Ограниченная поддержка Windows Forms –Не поддерживается генерация кода на лету (System.Reflection.Emit) –Ограниченная поддержка JIT аппаратных вычислений с плавающей точкой –Более простой сборщик мусора

Подмножество.NET Compact Framework –Нет поддержки Windows Forms –В настоящее время отсутствует поддержка сетевых технологий Дополнительные возможности –Аппаратные вычисления с плавающей точкой Но нет поддержки векторных инструкций VMX128 –Привязка потоков к одному из четырех (всего 6) логических процессоров (Hardware threads) Метод Thread.SetProcessorAffinity задаёт логический процессоры, предпочтительные для выполнения потока

Создаются отдельные проекты для PC и Xbox 360 Проекты могут использовать общий исходный код и контент (Add As Link) Поддерживается только C# При создания кода, специфичного для Windows и Xbox 360, используйте директивы условной компиляции #if/#else/#endif и [Conditional] #if !XBOX360 // Код, специфичный для Windows #endif [Conditional("XBOX360"] void XboxCode() { // Код, специфичный для Xbox }

Platform Core Framework Extended Framework Games XACTXINPUTXContent Direct3D GraphicsAudioInputMath Storage Application ModelContent Pipeline Starter Kits CodeContent Components

Каркас приложения Управление оконной подсистемой Управление графическим устройством Direct3D Управление контентом (текстуры, модели, звуки) Расширяемая функциональность за счет пользовательских компонентов

namespace MyGame { // Наследник класса Game public class Game1 : Microsoft.Xna.Framework.Game { // Объекты графического устройства и менеджера контента GraphicsDeviceManager graphics; ContentManager content; public Game1() { graphics = new GraphicsDeviceManager(this); content = new ContentManager(Services); } // Инициализация приложения protected override void Initialize() { IsFixedTimeStep = true; TargetElapsedTime = new TimeSpan(166667); // Инициализация пользовательских компонентов base.Initialize(); } // Загрузка контента protected override void LoadGraphicsContent(bool loadAllContent) { … } // Освобождение ресурсов protected override void UnloadGraphicsContent(bool unloadAllContent) { if (unloadAllContent == true) { content.Unload(); } // Обновление состояния игры protected override void Update(GameTime gameTime) {... base.Update(gameTime); } // Визуализация изображения protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); // Визуализация всех пользовательских DrawableGameComponent base.Draw(gameTime); }

Работа с устройствами ввода-вывода Устройство КлассПоддержка WindowsXbox 360 КлавиатураKeyboardXX МышьMouseX ГеймпадGamePadXX

protected override void Update(GameTime gameTime) { // Если нажата кнопка Back геймпада if (GamePad.GetState(PlayerIndex.One). Buttons.Back == ButtonState.Pressed) { Exit(); } // Если на клавиатуре нажата клавиша Esc if (Keyboard.GetState().IsKeyDown(Keys.Escape)) { Exit(); } base.Update(gameTime); }

Больше не является настройкой над D3DX Поиск компромисса между удобством и производительностью –public static Matrix operator *(Matrix matrix1, Matrix matrix2); –public static Matrix Multiply(Matrix matrix1, Matrix matrix2); –public static void Multiply(ref Matrix matrix1, ref Matrix matrix2, out Matrix result); Производительность операторов и обычных методов в два раза ниже C++ without SSE –c = a * b При использовании ref методов производительность примерно равна C++ without SSE –Matrix.Multiply(ref a, ref b, ref c) Поддерживается только правосторонняя система координат

public partial class Camera : Microsoft.Xna.Framework.GameComponent { public Camera(Game game) : base(game) { } // Инициализация компонента и загрузка контента public override void Initialize() { base.Initialize(); } // Обновление состояния компонента public override void Update(GameTime gameTime) { base.Update(gameTime); }

// Углы и положение камеры public Vector2 angles = Vector2.Zero; public Vector3 translate = new Vector3(0.0f, 0.0f, f); // Угол обзора и плоскости отсечения public float fov = MathHelper.Pi / 4.0f; public float zNear = 0.1f; public float zFar = f; // Расчет матриц проекции, вида public Matrix Projection { get { float aspect = (float)Game.Window.ClientBounds.Width / (float)Game.Window.ClientBounds.Height; return Matrix.CreatePerspectiveFieldOfView(fov, aspect, zNear, zFar); } public Matrix View { get { return Matrix.CreateRotationY(angles.X) * Matrix.CreateRotationX(angles.Y) * Matrix.CreateTranslation(translate); } public Matrix ViewProjection { get { return View * Projection; }

using Microsoft.Xna.Framework.Input; public override void Update(GameTime gameTime) { // Джойстик не должен воздействовать приложение, потерявшее фокус if (Game.IsActive) { // Получаем состояние миниджойстиков GamePadThumbSticks ThumbSticks = GamePad.GetState(PlayerIndex.One).ThumbSticks; // Правый министик используется для вращения камеры angles.X -= ThumbSticks.Right.X * 0.01f; angles.Y += ThumbSticks.Right.Y * 0.01f; // Левый джойстик приближает/удаляет камеру translate.Z += ThumbSticks.Left.Y * 5f; base.Update(gameTime); }

// Получаем состояние клавиатуры KeyboardState keyboardState = Keyboard.GetState(); // Корректируем углы поворота камеры if (keyboardState.IsKeyDown(Keys.Left)) angles.X += 0.01f; if (keyboardState.IsKeyDown(Keys.Right)) angles.X -= 0.01f; if (keyboardState.IsKeyDown(Keys.Up)) angles.Y += 0.01f; if (keyboardState.IsKeyDown(Keys.Down)) angles.Y -= 0.01f; // Корректируем положение камеры if (keyboardState.IsKeyDown(Keys.PageDown)) translate.Z -= 3.0f; if (keyboardState.IsKeyDown(Keys.PageUp)) translate.Z += 3.0f;

bool leftButton = false; Point lastMousePos; int lastMouseWheel; public override void Update(GameTime gameTime) {... // Класс Mouse не поддерживается Xbox 360 #if !XBOX360 MouseState mouseState = Mouse.GetState(); Rectangle rect = Game.Window.ClientBounds; // Приблежение/удаление камеры осуществляется колесиком int newMouseWheel = mouseState.ScrollWheelValue; int deltaMouseScroll = newMouseWheel - lastMouseWheel; translate.Z += (float)deltaMouseScroll * 0.1f; lastMouseWheel = newMouseWheel; // Вращение камеры осуществляется посредством перемещения // мыши при зажатой левой кнопке if (mouseState.LeftButton == ButtonState.Pressed) { if (leftButton == false) { lastMousePos = new Point(mouseState.X, mouseState.Y); // Если в момент нажатия левой кнопки указатель мыши //находится за пределами клиентской области окна, вращение // начинать не следует if ((lastMousePos.X >= 0) && (lastMousePos.Y >= 0) && (lastMousePos.X < rect.Width) && (lastMousePos.Y < rect.Height)) {leftButton = true;} else leftButton = false; } else { Point newMousePos = new Point(mouseState.X, mouseState.Y); Vector2 delta = new Vector2(lastMousePos.X - newMousePos.X, lastMousePos.Y - newMousePos.Y); angles += delta * 0.005f; // Центрируем указатель во избежание блокировки if (mouseState.X != rect.Width / 2) { newMousePos.X = rect.Width / 2; Mouse.SetPosition(newMousePos.X, newMousePos.Y); } if (mouseState.Y != rect.Height / 2) { newMousePos.Y = rect.Height / 2; Mouse.SetPosition(newMousePos.X, newMousePos.Y); } lastMousePos = newMousePos; } else leftButton = false; #endif }

public class Game1 : Microsoft.Xna.Framework.Game { Camera camera; public Game1() { graphics = new GraphicsDeviceManager(this); content = new ContentManager(Services); // Создаем компонент камера и добавляем его в список // компонентов camera = new Camera(this); Components.Add(camera); }

public class Game1 : Microsoft.Xna.Framework.Game { // Информация о модели Model biplane; protected override void LoadGraphicsContent(bool loadAllContent) { if (loadAllContent) { // Загружаем модель biplane = content.Load ("Content\\Biplane"); }

public class Game1 : Microsoft.Xna.Framework.Game { // Матрицы трансформации Matrix[] biplaneTransforms; protected override void LoadGraphicsContent(bool loadAllContent) { … // Выделяем память для хранения матриц трансформациии biplaneTransforms = new Matrix[biplane.Bones.Count]; } protected override void Update(GameTime gameTime) { … // Получаем значение матриц трасформации biplane.CopyBoneTransformsTo(biplaneTransforms); // Ищем вал винта for (int i = 0; i < biplane.Meshes.Count; i++) { ModelMesh mesh = biplane.Meshes[i]; if (mesh.Name == "Prop head") { // Поворачиваем вал винта biplaneTransforms[mesh.ParentBone.Index] *= Matrix.CreateRotationX(0.05f); } // Копируем измененные матрицы обратно в модель biplane.CopyBoneTransformsFrom(biplaneTransforms); // Вычисляем итоговые матрицы трансформации для каждого меша biplane.CopyAbsoluteBoneTransformsTo(biplaneTransforms); … }

Объектная надстройка над Direct3D 9 –В отличии от MDX не является тонкой оберткой над интерфейсами Direct3D Нет поддержки fixed function pipeline Часть функциональности FFP реализуется посредством класса BasicEffect –Пока только вершинное освещение –До трех источников света –Одна текстура –Туман Класс SpriteBatch инкапсулирует спрайтовую графику Нет встроенных базовых объектов вроде куба, сферы и чайника Нет поддержки визуализации вершин без трансформации вершинным шейдером и т.д.

protected override void Draw(GameTime gameTime) { // Закарска экрана синим цветом graphics.GraphicsDevice.Clear(Color.CornflowerBlue); // Перебираем все меши сцены for (int i = 0; i < biplane.Meshes.Count; i++) { ModelMesh mesh = biplane.Meshes[i]; // Перебираем все эффекты меша и устанавливаем параметры for (int j = 0; j < mesh.Effects.Count; j++) { BasicEffect effect = (BasicEffect)mesh.Effects[j]; // Включаем освещение по умолчанию (3 источника) effect.EnableDefaultLighting(); // Задаем матрицы мира, вида и проекции effect.World = biplaneTransforms[mesh.ParentBone.Index]; effect.View = camera.View; effect.Projection = camera.Projection; } // Визуализируем Mesh mesh.Draw(); } base.Draw(gameTime); }

DDC контент Content Importer Content DOM Content Processor Content DOM XNB Content Manager.X Texture Importer Texture Content Texture Content Sprite Texture Processor.XNB Texture2D Reader.JPG.PNG.XML Texture Processor Model Texture Processor Procedure Texture Importer Texture Content Texture Content X Importer Node Content Node Content Model Processor Model Content Model Content Terrain Processor Model Reader.FBX Fbx Importer

Типы файлов Название импортера Класс импортера Выходной класс.bmp,.dds,.dib,.hdr,.jpg,.pfm,.png,.ppm,.tga. XNA Texture Importer TextureImporterTextureContent.fxXNA Effect Importer EffectImporterEffectContent.xXNA X File Importer XimporterNodeContent.fbxXNA Autodesk FBX Importer FbxImporterNodeContent.xmlXNA XML Importer XmlImporterObject.xapXNA XACT Project Importer --

const static int LightCount = 3; // Текстура texture diffuseTexture; // Матрицы трасформации float4x4 worldViewProj : WorldViewProjection; float4x4 worldView : WorldView; //Направления источников света float3 lightDirView[LightCount]; // Цвета источников света float4 lightColor[LightCount]; // Цвет диффузной составляющей материала float4 materialDiffuse; // Цвет зеркальной составляющей материла float4 materialSpecular; // Глянцевитость float shininess; // Накладывается ли текстура bool textured; struct vertexInput { float3 position : POSITION; float3 normal : NORMAL; float2 texCoordDiffuse: TEXCOORD0; }; struct vertexOutput { float4 hPosition : POSITION; float2 texCoordDiffuse : TEXCOORD0; float3 eye : TEXCOORD1; float3 N : TEXCOORD2; float3 L[LightCount] : TEXCOORD3; }; sampler TextureSampler = sampler_state { texture = ; … }; vertexOutput VS_PerPixelLighting(vertexInput IN) { vertexOutput OUT; OUT.hPosition = mul( float4(IN.position, 1.0), worldViewProj); OUT.texCoordDiffuse = IN.texCoordDiffuse; float3 vertPos = mul(float4(IN.position.xyz, 1.0), worldView).xyz; OUT.N = normalize(mul(IN.normal, (float3x3)worldView)); OUT.eye = -normalize(vertPos); for (int i = 0; i < LightCount; i++) { OUT.L[i] = lightDirView[i]; } return OUT; } float4 PS_PerPixelLighting( vertexOutput IN): COLOR { float3 normN = normalize(IN.N); float3 normEye = normalize(IN.eye); float4 color = float4(0.0, 0.0, 0.0, 0.0); float4 diffuseTexture; if (textured) diffuseTexture = tex2D( TextureSampler, IN.texCoordDiffuse ); else diffuseTexture = float4(1.0, 1.0, 1.0, 1.0); for (int i = 0; i < LightCount; i++) { float3 normL = normalize(IN.L[i]); float diff = max(0, dot(normN, normL)); float3 H = normalize(normEye + normL); float spec = pow(max(0, dot(normN,H) ), shininess ); float4 diffColor = materialDiffuse * diff * lightColor[i] * diffuseTexture; float4 specColor = materialSpecular * lightColor[i] * spec; color += diffColor + specColor; } return color; } technique textured { pass p0 { CullMode = None; VertexShader = compile vs_1_1 VS_PerPixelLighting(); PixelShader = compile ps_2_0 PS_PerPixelLighting(); }

using Microsoft.Xna.Framework.Content.Pipeline; using Microsoft.Xna.Framework.Content.Pipeline.Processors; using Microsoft.Xna.Framework.Content.Pipeline.Graphics;... [ContentProcessor] public class ModelPerpixelLightingProcessor : ModelProcessor { // Конвертирует материалы модели protected override MaterialContent ConvertMaterial( MaterialContent material, ContentProcessorContext context) { // Создаем материал, использующий наш эффект perpixel.fx EffectMaterialContent myMaterial = new EffectMaterialContent(); string effectPath = Path.GetFullPath("Content\\perpixel.fx"); myMaterial.Effect = new ExternalReference (effectPath); // Формируем параметры эффекта на основе объекта материала // BasicMaterialConten, созданного XNA if (material is BasicMaterialContent) { BasicMaterialContent basicMaterial = (BasicMaterialContent)material; // Текстура материала if (basicMaterial.Texture != null) { myMaterial.Textures.Add("diffuseTexture", basicMaterial.Texture); myMaterial.OpaqueData.Add("textured", true); } else myMaterial.OpaqueData.Add("textured", false); // Диффузный цвет if (basicMaterial.DiffuseColor != null) { myMaterial.OpaqueData.Add("materialDiffuse", new Vector4(basicMaterial.DiffuseColor.Value, 1.0f)); } else myMaterial.OpaqueData.Add("materialDiffuse", Vector4.One); // Цвет бликов и глянцевитость if ((basicMaterial.SpecularColor != null) && (basicMaterial.SpecularPower != null)) { myMaterial.OpaqueData.Add("shininess", basicMaterial.SpecularPower.Value); myMaterial.OpaqueData.Add("materialSpecular", new Vector4(basicMaterial.SpecularColor.Value, 1.0f)); } else { myMaterial.OpaqueData.Add("materialSpecular", Vector4.One); myMaterial.OpaqueData.Add("shininess", 128.0f); } else throw new NotImplementedException(); return base.ConvertMaterial(myMaterial, context); }

Vector4[] lightColor = new Vector4[] {Vector4.One, new Vector4(0.5f, 0.5f, 0.5f, 1.0f), new Vector4(0.5f, 0.5f, 0.5f, 1.0f)}; Vector3[] lightDir = new Vector3[]{ new Vector3( f, f, f), new Vector3( f, f, f), new Vector3( f, f, f)}; Vector3[] lightDirView = new Vector3[3]; protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); // Переводим векторы направления источников света в // систему координат камеры for (int k = 0; k < lightDir.Length; k++) { Matrix normalTransform = camera.View; normalTransform.Translation = Vector3.Zero; lightDirView[k] = Vector3.Normalize( Vector3.Transform(-lightDir[k], normalTransform)); } for (int i = 0; i < biplane.Meshes.Count; i++) { ModelMesh mesh = biplane.Meshes[i]; for (int j = 0; j < mesh.Effects.Count; j++) { // Получаем доступ к объекту эффекта Effect effect = (Effect)mesh.Effects[j]; // Задаем матрицы трансформации effect.Parameters.GetParameterBySemantic( "WorldViewProjection"). SetValue(biplaneTransforms[mesh.ParentBone.Index] * camera.ViewProjection); effect.Parameters.GetParameterBySemantic("WorldView"). SetValue(biplaneTransforms[mesh.ParentBone.Index] * camera.View); // Цвет источников света effect.Parameters["lightColor"].SetValue(lightColor); // Направление источников света (в системе координат // камеры) effect.Parameters["lightDirView"].SetValue( lightDirView); } mesh.Draw(); } base.Draw(gameTime); }

Работа со шрифтами и визуализация текста Генерация ландшафта на основе карты высот Height Map -> Normal Map Bump mapping Скелетная анимация

Кроссплатформенная надстройка над System.IO –Доступ к файлам данных приложения –Сохранение конфигурации приложения и сохраненных игр

public class Config { public Vector2 angles; public Vector3 translate; // Сохранение объекта в файла public void Save(string filename) { using (TextWriter fs = new StreamWriter(filename)) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(Config)); xmlSerializer.Serialize(fs, this); } // Загрузка данных из файла public static Config Load(string filename) { Config config; try { using (FileStream fs = new FileStream(filename, FileMode.Open)) { XmlSerializer xmlSerilizer = new XmlSerializer(typeof(Config)); config = (Config)xmlSerilizer.Deserialize(fs); } // При возникновении проблем используем // настройки по умолчанию catch (IOException) { config = new Config(); } catch (InvalidOperationException) { config = new Config(); } return config; }

protected override void Update(GameTime gameTime) { KeyboardState keyboadState = Keyboard.GetState(); GamePadState gamePadState = GamePad.GetState(PlayerIndex.One); // Если нажата клавиша S клавиатуры или кнопка B геймпада if (keyboadState.IsKeyDown(Keys.S) || (gamePadState.Buttons.B == ButtonState.Pressed)) { // Отображаем диалоговое окно выбора устройства хранения // информации StorageDevice storageDevice = StorageDevice.ShowStorageDeviceGuide(); // Проверяем, подключено ли это устройство if (!storageDevice.IsConnected) return; // Получаем доступ к файлам приложения на устройстве using (StorageContainer storageContainer = storageDevice.OpenContainer("GSP.Biplane")) { // Формируем полное имя файла конфигурации string configFile = Path.Combine(storageContainer.Path, "config.xml"); Config config = new Config(); config.angles = camera.angles; config.translate = camera.translate; / Сохраняем конфигурацию приложения config.Save(configFile); } // Если нажата клавиша L клавиатуры или кнопка A геймпада if (Keyboard.GetState().IsKeyDown(Keys.L) || (gamePadState.Buttons.A == ButtonState.Pressed)) { // Отображаем диалоговое окно выбора устройства хранения // информации StorageDevice storageDevice = StorageDevice.ShowStorageDeviceGuide(); // Проверяем, подключено ли это устройство if (!storageDevice.IsConnected) return; // Получаем доступ к файлам приложения на устройстве using (StorageContainer storageContainer = storageDevice.OpenContainer("GSP.Biplane")) { // Формируем полное имя файла конфигурации string configFile = Path.Combine(storageContainer.Path, "config.xml"); // Загружаем конфигурацию приложения Config config = Config.Load(configFile); camera.angles = config.angles; camera.translate = config.translate; }

Основан на Microsoft Cross-Platform Audio Creation Tool (XACT) –Визуальный windows-инструментарий для создания аудио контента Позволяет создавать именованные последовательности wave-файлов с возможностью организации циклов, изменения громкости и т.п., и привязывать их к событиям приложения без перекомпиляции –Высокоуровневая кросс-платформенная библиотека для работы с аудио подсистемой PC и Xbox 360

Файл проекта.xap. Текстовый файл, с описанием проекта и инструкциями по сборке Файл глобальных настроек.gsf, затрагивающих весь проект Wave bank – коллекция wave-файлов, логически сгруппированных в один.xwb файл

SoundBank –.xsb файл с набором Sounds и Cues –Sound – инструкции, описывающие как надо проиграть набор указанных звуков (микширование, последовательность, циклы, громкость) –Cue – логическая группа Sounds, проигрываемая приложением при наступление определенного события

Надстройка над XACT –AudioEngine – главный объект, управляющий аудио- подсистемой PC / Xbox 360. Настройки загружаются из.gsf-файла –WaveBank и SoundBank – работа с.xwb и.xsb файлами соответственно Доступ к Cue осуществляется методом GetCue класса SoundBank Проигрывание звуков управляется стандартным набором Play/Pause/Resume/Stop и свойствами наподобие IsPlaying

AudioEngine audioEngine; WaveBank waveBank; SoundBank soundBank; protected override void Initialize() { // Загружаем аудио данные audioEngine = new AudioEngine("Content\\audio.xgs"); waveBank = new WaveBank(audioEngine, "Content\\Wave Bank.xwb"); soundBank = new SoundBank(audioEngine, "Content\\Sound Bank.xsb"); // Запускаем проигрывание звука двигателя самолета soundBank.PlayCue("Biplane"); … } protected override void Update(GameTime gameTime) { // Периодически вызываем метод Update экземпляра класса AudioEngine audioEngine.Update();... }

Поддержка сетевых приложений Средства разработки GUI-интерфейса Низкоуровневая работа с Audio-устройствами Воспроизведение видеофайлов IDE для разработки и отладки шейдеров

Плюсы сборщика мусора –Высокая скорость выделения памяти –Локальность данных, практически отсутствует проблема фрагментации –Нет утечек памяти В том числе и при использовании циклических ссылок Но не всё так хорошо –Иногда все же приходится собирать мусор –Частый вызов сборщика мусора может поставить крест на производительности

Сборка мусора похожа на процесс дефрагментации HDD –Затраты на сборку мусора преимущественно определяются количеством выживших объектов Сборщик мусора с поддержкой поколении (0, 1, 2) –Куча располагается в непрерывном адресном пространстве, разделенном на поколения –В каждом поколении объекты имеют примерно одинаковый возраст Мусор собирается в первую очередь в поколении 0 –Размер поколения 0 примерно равен кэшу L2 –При построении графа достижимых объектов как правило игнорируются объекты поколений 1 и 2 –Время сборки мусора в поколении 0 порядка 1 мс Старайтесь не допустить перехода кратко живущих объектов в старшие поколения (избегайте Finalize) Поколение 2 Поколение 1 Поколение 0 Свободная память

Поколения не поддерживаются –Отличная производительность, если объем выделенной памяти сопоставим с размером поколения 0 в.NET Framework 2.0 (порядка 1MB) –С ростом объема выделенной памяти эффективность стремительно снижается Заблаговременно выделяйте память перед началом вычислений –Даже незначительное выделение памяти при визуализации каждого кадра может иметь печальные последствия –Выделяемая памяти предварительно обнуляется, так что пропускная способность оперативной памяти может стать узким местом Самостоятельно форсируйте сборку мусора в местах, не критичных к незначительным провалам производительности

Пример 1Пример 2 void Add(object item) { … } … // Неявное выделение памяти в // управляемой куче Add(2.0f); struct MyItem : IComparable { … } void Test(IComparable v1) { … } static void Main(string[] args) { MyItem item; // Неявное выделение памяти в // управляемой куче Test(item); }

Получает Enumerator посредством метода GetEnumerator –Если Enumerator является классом, происходит выделение памяти –Если Enumerator является структурой Коллекция List Коллекция EffectPassCollection public class List : IList,... { public struct Enumerator : IEnumerator,... { public bool MoveNext(); public T Current { get; } } public Enumerator GetEnumerator() { // Нет выделения памяти в управляемой куче // Но если использовать коллекцию List через // интерфейс вроде IList, выделение памяти // все же произойдет return new Enumerator ((List )this); } public sealed class EffectPassCollection : IEnumerable { public struct Enumerator : IEnumerator, … {... } public Enumerator GetEnumerator() { return new Enumerator ((List )this); } public IEnumerator GetEnumerator() { // Внимание: боксирование и выделение памяти в куче. return (IEnumerator )this.pPass.GetEnumerator(); }

Всегда используйте Platform Target x86 Класс GraphicsDevice легко интегрируется с визуальными компонентами и окнами Win32 –Для вывода на в заданную область формы просто разместите должным образом визуальный компонент, унаследованный от Control, запретить Erase Background и передать его Handle в GraphicsDevice –Не пытайтесь интегрировать Game в приложение Windows Forms. Он для этого не предназначен Нет поддержки Content Pipeline –Эффекты и текстуры можно использовать минуя Content Pipeline –Для экспорта моделей используйте Visual C# 2005 Express или MS Build –Необходимо самостоятельно реализовать интерфейсы классов Game и GraphicsDeviceManage

Model.proj C:\Program Files (x86)\Microsoft XNA\XNA Game Studio Express\v1.0\References\Windows\x86 FbxImporter ModelProcessor

// Реализация класса GraphicsDeviceManage с поддердкой // Windows Forms class WinFormsGraphicsDeviceService : IGraphicsDeviceService, IGraphicsDeviceManager { private GraphicsDevice graphicsDevice; private Control renderControl; public PresentationParameters presentParams; public WinFormsGraphicsDeviceService(Control renderControl) { this.renderControl = renderControl; } #region IGraphicsDeviceService Members public event EventHandler DeviceCreated; public event EventHandler DeviceDisposing; public event EventHandler DeviceReset; public event EventHandler DeviceResetting; public GraphicsDevice GraphicsDevice { get { return this.graphicsDevice; } } #endregion #region IGraphicsDeviceManager Members public void CreateDevice() { presentParams = new PresentationParameters(); presentParams.IsFullScreen = false; presentParams.BackBufferCount = 1; presentParams.BackBufferHeight = 0; presentParams.BackBufferWidth = 0; presentParams.EnableAutoDepthStencil = true; presentParams.AutoDepthStencilFormat = DepthFormat.Depth24; this.graphicsDevice = new GraphicsDevice( GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.renderControl.Handle, CreateOptions.HardwareVertexProcessing, presentParams); } #endregion } // Имплементация свойства Services класса Game public partial class MainForm : Form, IServiceProvider { WinFormsGraphicsDeviceService graphics = null; ContentManager contentManager = null; private void MainForm _Load(object sender, EventArgs e) { SetStyle(ControlStyles.Opaque | ControlStyles.ResizeRedraw, true); MinimumSize = SizeFromClientSize(new Size(1, 1)); this.graphics = new WinFormsGraphicsDeviceService(this); graphics.CreateDevice(); contentManager = new ContentManager(this); // Загрузка контента biplane = contentManager.Load ("Content\\biplane"); } #region IServiceProvider Members public object GetService(Type serviceType) { if (serviceType == typeof(IGraphicsDeviceService)) return graphics; else throw new NotImplementedException(); } #endregion }

Полная поддержка Windows Vista Поддержка Visual Studio 2005 Поддержка спрайтовых шрифтов Поддержка 3D звука BasicEffect поддерживает попиксельное освещение Расширенная математическая библиотека Улучшенная технология распространения приложений Обратная совместимость с 1.0

Александр Ложечкин – Сергей Гайдуков –