71
XNA Game Studio Express: разработка casual games для PC и Xbox 360 Александр Ложечкин Сергей Гайдуков

XNA Game Studio Express: разработка casual games для PC и Xbox 360

  • Upload
    dieter

  • View
    57

  • Download
    0

Embed Size (px)

DESCRIPTION

XNA Game Studio Express: разработка casual games для PC и Xbox 360. Александр Ложечкин Сергей Гайдуков. Содержание. XNA Framework на платформе Windows .NET Compact Framework for Xbox 360 Компоненты XNA Framework Оптимизация XNA- приложений XNA Framework и Windows Forms. - PowerPoint PPT Presentation

Citation preview

Page 1: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

XNA Game Studio Express: разработка casual games для

PC и Xbox 360

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

Page 2: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Содержание

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

Page 3: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

XNA Game Studio Express

• Инструментарий разработки игровых приложений для платформ– 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– Утилиты– Образование

Page 4: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Marblets

Page 5: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

XNA Framework

• Кроссплатформенный API для разработки игровых приложений– Не привязан к Windows

• Основан на платформе .NET Framework– .NET Framework 2.0 (Windows)– .NET Compact Framework for Xbox 360– Mono (Linux)

Page 6: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

XNA на платформе Windows

• Компоненты для разработки приложений

• Компоненты для распространения приложений

– Очень просто интегрируются в дистрибутив приложения средствами Visual Studio 2005 Pro

Компонент Размер дистрибутиваVisual C# Express 2005 + SP1 440MB + (24-53MB)XNA Game Studio Express 1.0 81MB.NET Framework 1.1 23MB

Компонент Размер дистрибутива.NET Framework 2.0 22 – 27MBXNA Framework 1.0 2MBОбновление D3DX, XACT, XINPUT

4MB

Page 7: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

.NET Compact Framework 2.0

• Отличия от .NET Framework 2.0:– Значительно меньшие требования к ресурсам компьютера– Является подмножеством .NET Framework (содержит

примерно 30% классов)– Ограниченная поддержка web-приложений и баз данных– Ограниченная поддержка Windows Forms– Не поддерживается генерация кода на лету

(System.Reflection.Emit)– Ограниченная поддержка JIT аппаратных вычислений с

плавающей точкой– Более простой сборщик мусора

Page 8: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

.NET Compact Framework /Xbox 360

• Подмножество .NET Compact Framework– Нет поддержки Windows Forms – В настоящее время отсутствует поддержка сетевых

технологий• Дополнительные возможности

– Аппаратные вычисления с плавающей точкой• Но нет поддержки векторных инструкций VMX128

– Привязка потоков к одному из четырех (всего 6) логических процессоров (Hardware threads)• Метод Thread.SetProcessorAffinity задаёт логический

процессоры, предпочтительные для выполнения потока

Page 9: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Кроссплатформенные приложения

• Создаются отдельные проекты для PC и Xbox 360

• Проекты могут использовать общий исходный код и контент (Add As Link)• Поддерживается только C#• При создания кода, специфичного для Windows и Xbox 360, используйте

директивы условной компиляции #if/#else/#endif и [Conditional]

#if !XBOX360// Код, специфичный для Windows#endif

[Conditional("XBOX360"]void XboxCode(){// Код, специфичный для Xbox }

Page 10: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компоненты XNA Framework

Platform

CoreFramework

ExtendedFramework

Games

XACT XINPUT XContentDirect3D

Graphics Audio Input Math Storage

Application Model Content Pipeline

Starter Kits Code Content Components

Page 11: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Application Model

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

пользовательских компонентов

Page 12: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Application Model

Page 13: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Простейшее приложение(Ex01)

Page 14: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Простейшее приложение

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); } }}

Page 15: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Input

Работа с устройствами ввода-вывода

Устройство Класс ПоддержкаWindows Xbox 360

Клавиатура Keyboard X X

Мышь Mouse X

Геймпад GamePad X X

Page 16: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Input

Page 17: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример использования компонента Input

(Ex02)

Page 18: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример использования компонента Input

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);}

Page 19: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Math

Page 20: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Math

• Больше не является настройкой над 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)

• Поддерживается только правосторонняя система координат

Page 21: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Использования компонента Math на примере

встраивания камеры(Ex03)

Page 22: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример компонента «камера»Каркас компонента

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); }}

Page 23: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример компонента «камера»Расчет матриц трансформации

// Углы и положение камерыpublic Vector2 angles = Vector2.Zero;public Vector3 translate = new Vector3(0.0f, 0.0f, -500.0f);// Угол обзора и плоскости отсеченияpublic float fov = MathHelper.Pi / 4.0f;public float zNear = 0.1f;public float zFar = 10000.0f;

// Расчет матриц проекции, вида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; }}

Page 24: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример компонента «камера»Взаимодействие с геймпадом

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);}

Page 25: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример компонента «камера»Взаимодействие с клавиатурой

// Получаем состояние клавиатуры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;

Page 26: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример компонента «камера»Взаимодействие с мышью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}

Alexander Lozhechkin
Про столкновение с границей не понял
Page 27: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример компонента «камера»Интеграция в приложение

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); }}

Page 28: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Экспорт сцены из 3DS MAX 9

Page 29: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Загрузка модели(Ex04)

Page 30: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Загрузка модели

public class Game1 : Microsoft.Xna.Framework.Game{// Информация о модели Model biplane;

protected override void LoadGraphicsContent(bool loadAllContent) { if (loadAllContent) {// Загружаем модель biplane = content.Load<Model>("Content\\Biplane"); } }}

Page 31: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Класс Model

Page 32: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Анимация винта самолета(Ex05)

Page 33: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Анимация винта самолета

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);… }}

Page 34: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Graphics

• Объектная надстройка над Direct3D 9– В отличии от MDX не является тонкой оберткой над интерфейсами

Direct3D• Нет поддержки fixed function pipeline• Часть функциональности FFP реализуется посредством класса

BasicEffect– Пока только вершинное освещение– До трех источников света– Одна текстура– Туман

• Класс SpriteBatch инкапсулирует спрайтовую графику• Нет встроенных базовых объектов вроде куба, сферы и чайника• Нет поддержки визуализации вершин без трансформации

вершинным шейдером и т.д.

Page 35: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Graphics

Page 36: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Визуализация самолета(Ex06)

Page 37: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Визуализация самолета

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);}

Page 38: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Content Pipeline

DDC контент

ContentImporter

Content DOM

ContentProcessor

Content DOM

XNB Content Manager

.X

TextureImporter

TextureContent

SpriteTexture

Processor.XNB

Texture2DReader.JPG

.PNG

.XML

Texture Processor

ModelTexture

Processor

ProcedureTextureImporter

TextureContent

XImporter

NodeContent

ModelProcessor

ModelContent

TerrainProcessor

ModelReader

.FBX FbxImporter

Page 39: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Content PipelineStandart Importers

Типы файлов

Названиеимпортера

Класс импортера

Выходной класс

.bmp, .dds,

.dib, .hdr, .jpg, .pfm, .png, .ppm, .tga.

XNA Texture Importer

TextureImporter TextureContent

.fx XNA Effect Importer

EffectImporter EffectContent

.x XNA X File Importer

Ximporter NodeContent

.fbx XNA Autodesk FBX Importer

FbxImporter NodeContent

.xml XNA XML Importer

XmlImporter Object

.xap XNA XACT Project Importer

- -

Page 40: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Попиксельное освещение(Ex07)

Page 41: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Попиксельное освещениеЭффект

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 = <diffuseTexture>;…};

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(); }}

Page 42: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Попиксельное освещениеContent Processor

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<EffectContent>(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); }}

Page 43: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Использование нового Content Processor в C# Express

Page 44: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Попиксельное освещениеИнтеграция в приложение

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(-0.5265408f, -0.5735765f, -0.6275069f), new Vector3(0.7198464f, 0.3420201f, 0.6040227f), new Vector3(-0.4545195f, 0.7660444f, 0.9545195f)};

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);}

Page 45: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Content Processors из XNA Creators Club

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

http://creators.xna.com/

Page 46: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Storage

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

Page 47: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Сохранение конфигурации(Ex08)

Page 48: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Сохранение конфигурацииСериализация данных

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; }}

Page 49: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Сохранение конфигурацииРабота с носителями информации

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; } }}

Page 50: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Audio / XACT

• Основан на Microsoft Cross-Platform Audio Creation Tool (XACT)– Визуальный windows-инструментарий для

создания аудио контента• Позволяет создавать именованные

последовательности wave-файлов с возможностью организации циклов, изменения громкости и т.п., и привязывать их к событиям приложения без перекомпиляции

– Высокоуровневая кросс-платформенная библиотека для работы с аудио подсистемой PC и Xbox 360

Page 51: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Audio / XACTОсновные компоненты проекта

• Файл проекта .xap. Текстовый файл, с описанием проекта и инструкциями по сборке

• Файл глобальных настроек .gsf, затрагивающих весь проект

• Wave bank – коллекция wave-файлов, логически сгруппированных в один .xwb файл

Page 52: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент Audio / XACTОсновные компоненты проекта

• SoundBank – .xsb файл с набором Sounds и Cues– Sound – инструкции, описывающие как надо проиграть

набор указанных звуков (микширование, последовательность, циклы, громкость)

– Cue – логическая группа Sounds, проигрываемая приложением при наступление определенного события

Page 53: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Компонент AudioОсновные классы

• Надстройка над XACT– AudioEngine – главный объект, управляющий аудио-

подсистемой PC / Xbox 360. Настройки загружаются из .gsf-файла

– WaveBank и SoundBank – работа с .xwb и .xsb файлами соответственно• Доступ к Cue осуществляется методом GetCue класса

SoundBank• Проигрывание звуков управляется стандартным

набором Play/Pause/Resume/Stop и свойствами наподобие IsPlaying

Page 54: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Звук двигателя(Ex09)

Page 55: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Microsoft Cross-Platform Audio Creation Tool (XACT)

Page 56: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Запуск двигателя самолета

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();... }

Page 57: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Starter Kits

Page 58: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Rocket Commander XNA

Page 59: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Чего нет в текущей версии…но появится в будущем

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

Page 60: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Производительность сборщика мусора

• Плюсы сборщика мусора– Высокая скорость выделения памяти– Локальность данных, практически отсутствует проблема

фрагментации– Нет утечек памяти

• В том числе и при использовании циклических ссылок• Но не всё так хорошо

– Иногда все же приходится собирать мусор– Частый вызов сборщика мусора может поставить крест на

производительности

Page 61: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Сборщик мусора .NET Framework 2.0

• Сборка мусора похожа на процесс дефрагментации HDD– Затраты на сборку мусора преимущественно определяются количеством “выживших”

объектов• Сборщик мусора с поддержкой поколении (0, 1, 2)

– Куча располагается в непрерывном адресном пространстве, разделенном на поколения

– В каждом поколении объекты имеют примерно одинаковый возраст• Мусор собирается в первую очередь в поколении 0

– Размер поколения 0 примерно равен кэшу L2– При построении графа достижимых объектов как правило игнорируются объекты

поколений 1 и 2– Время сборки мусора в поколении 0 порядка 1 мс

• Старайтесь не допустить перехода кратко живущих объектов в старшие поколения (избегайте Finalize)

Поколение2

Поколение1

Поколение0

Свободная память

Page 62: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Сборщик мусора .NET CF for Xbox 360

• Поколения не поддерживаются– Отличная производительность, если объем выделенной памяти

сопоставим с размером поколения 0 в .NET Framework 2.0 (порядка 1MB)

– С ростом объема выделенной памяти эффективность стремительно снижается

• Заблаговременно выделяйте память перед началом вычислений– Даже незначительное выделение памяти при визуализации каждого

кадра может иметь печальные последствия– Выделяемая памяти предварительно обнуляется, так что пропускная

способность оперативной памяти может стать узким местом• Самостоятельно форсируйте сборку мусора в местах, не

критичных к незначительным провалам производительности

Page 63: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Неявное выделение памятиБоксирование (boxing)

Пример 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);}

Page 64: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Неявное выделение памятиЦикл foreach

• Получает Enumerator посредством метода GetEnumerator– Если Enumerator является классом, происходит выделение памяти– Если Enumerator является структуройКоллекция List Коллекция EffectPassCollection

public class List<T> : IList<T>, ...{ public struct Enumerator : IEnumerator<T>, ... { public bool MoveNext(); public T Current { get; } }

public Enumerator<T> GetEnumerator() {// Нет выделения памяти в управляемой куче// Но если использовать коллекцию List<T> через // интерфейс вроде IList<T>, выделение памяти // все же произойдет return new Enumerator<T>((List<T>)this); }}

public sealed class EffectPassCollection : IEnumerable<EffectPass>{ public struct Enumerator : IEnumerator<T>, … {... } public Enumerator<T> GetEnumerator() { return new Enumerator<T>((List<T>)this); } public IEnumerator<EffectPass> GetEnumerator() {// Внимание: боксирование и выделение памяти в куче. return (IEnumerator<EffectPass>)this.pPass.GetEnumerator(); }}

Page 65: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Использование XNA Framework в WinForms

• Всегда используйте 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

Page 66: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример использования MSBuildдля компиляции модели

• Model.proj<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <UsingTask TaskName="BuildContent" AssemblyName="Microsoft.Xna.Framework.Content.Pipeline, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" /> <PropertyGroup> <XnaInstall> C:\Program Files (x86)\Microsoft XNA\XNA Game Studio Express\v1.0\References\Windows\x86 </XnaInstall> </PropertyGroup> <ItemGroup> <PipelineAssembly Include="C:\Program Files (x86)\Microsoft XNA\XNA Game Studio Express\v1.0\References\Windows\x86\Microsoft.Xna.Framework.Content.Pipeline.FBXImporter.dll" /> <PipelineAssembly Include="C:\Program Files (x86)\Microsoft XNA\XNA Game Studio Express\v1.0\References\Windows\x86\Microsoft.Xna.Framework.Content.Pipeline.TextureImporter.dll" /> </ItemGroup>   <ItemGroup> <Content Include="biplane.FBX"> <Importer>FbxImporter</Importer> <Processor>ModelProcessor</Processor> </Content> </ItemGroup>   <Target Name="Build"> <BuildContent SourceAssets="@(Content)" PipelineAssemblies="@(PipelineAssembly)" TargetPlatform="Windows" /> </Target> </Project>

Page 67: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Пример подмены классовGame и GraphicsDeviceManage

// Реализация класса GraphicsDeviceManage с поддердкой// Windows Formsclass 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 класса Gamepublic 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<Model>("Content\\biplane"); }

#region IServiceProvider Members public object GetService(Type serviceType) { if (serviceType == typeof(IGraphicsDeviceService)) return graphics; else throw new NotImplementedException(); } #endregion}

Page 68: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

XNA Game Studio Express 1.1

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

приложений• Обратная совместимость с 1.0

Page 69: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Учебная литература

Page 70: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Интернет ресурсы

• http://msdn2.microsoft.com/en-us/xna/default.aspx• http://blogs.msdn.com/xna/• http://creators.xna.com/• http://forums.microsoft.com/msdn/• http://abi.exdream.com/

• www.xnadev.ru • www.gotdotnet.ru

Page 71: XNA Game Studio Express:  разработка  casual games  для  PC  и  Xbox 360

Вопросы

• Александр Ложечкин– [email protected]– http://blogs.gotdotnet.ru/personal/allo

• Сергей Гайдуков– [email protected]– http://blogs.gotdotnet.ru/personal/gsaf