XNA и базы данных с использованием Entity Framework. Часть 2

XNA и базы данных с использованием Entity Framework. Часть 2

В прошлый раз мы остановились на том, что создали модель Entity Framework в нашем приложении.

Сейчас мы воспользуемся ей для того, чтобы извлечь данные из базы данных


Сперва я создам новый класс, который будет реализовывать примитив нашем приложении.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Primitives3D;

using Microsoft.Xna.Framework;

using Microsoft.Xna.Framework.Graphics;

using MyGame.Context;

namespace MyGame

{


class
MyPrimitive

{


GeometricPrimitive primitive;


public
Vector3 Position;


public MyPrimitive(Game game, Primitives DBPrimitive)

{


switch (DBPrimitive.PrimitiveTypes.Name)

{


case
«Teapot»: primitive = new
TeapotPrimitive(game.GraphicsDevice);


break;


case
«Cube»: primitive = new
CubePrimitive(game.GraphicsDevice);


break;


case
«Torus»: primitive = new
TorusPrimitive(game.GraphicsDevice);


break;


default: primitive = new
TeapotPrimitive(game.GraphicsDevice);


break;

}

Position = new
Vector3((float)DBPrimitive.X, (float)DBPrimitive.Y, (float)DBPrimitive.Z);

}


public
void Draw(Effect effect)

{

effect.Parameters[«World»].SetValue(Matrix.CreateTranslation(Position));

primitive.Draw(effect);

}

}

}

Конструктор MyPrimitive принимает в качестве параметра Primitives – тип, который мы соответствует записи в таблице Primitives в нашей базе данных.

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

Обратите внимание на то, что мы можем обратиться к названию типа примитива через объекта типа Primitives, несмотря на то, что он находится в другой таблице.

Метод Draw тривиален, мы устанавливаем значение мировой матрицы для эффекта и рисуем примитив. Метод Draw основывается на предположении, что все остальные параметры шейдера уже заданы и шейдер содержит параметр «World».

Теперь самое интересное, нужно получить все значения из базы данных. Для этого нужно создать новый контекст данных GameDBEntities. Обратите внимание, что он создается в блоке using, это нужно делать, что контекст автоматически удалился и освободил неупраляемые ресурсы (подключение в базе данных) как только он станет не нужен.

У контекста данных есть свойства Primitives и PrimitiveTypes, которые вернут нам все строки содержащиеся в базе данных в виде классов (в этом месте выполнится запрос к базе данных, который может занять немало времени).


List<MyPrimitive> primitives;


protected
override
void Initialize()

{


// TODO: Add your initialization logic here

Components.Add(new
FPSCounter(this));

light = new
Light(this);

light.DefaultPosition = new
Vector3(1, 1, 1);

Components.Add(light);

camera = new
FreeCamera(this, new
Vector3(0, 0, 2), Vector3.Zero);

Components.Add(camera);

debugInfo = new
DebugInfo(this);

Components.Add(debugInfo);

primitives = new
List<MyPrimitive>();


using (var ctx = new
GameDBEntities())

{


foreach (var item in ctx.Primitives

{

primitives.Add(new
MyPrimitive(this, item));

}

}


base.Initialize();

}


protected
override
void Draw(GameTime gameTime)

{

GraphicsDevice.Clear(Color.Black);


Matrix view = camera.View;


Matrix proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 0.1f, 10f);


// TODO: Add your drawing code here

effect.Parameters[«World»].SetValue(Matrix.CreateRotationY((float)gameTime.TotalGameTime.TotalSeconds));

effect.Parameters[«View»].SetValue(view);

effect.Parameters[«Projection»].SetValue(proj);

effect.Parameters[«LightPosition»].SetValue(light.Position);

effect.Parameters[«SpecularPower»].SetValue(specularPower);

effect.Parameters[«Eye»].SetValue(camera.Position);


foreach (var item in primitives)

{

item.Draw(effect);

}

light.Draw(view, proj);


base.Draw(gameTime);

}

Сейчас в коде намеренно допущена ошибка, если попробовать запустить его, то мы увидем исключение:


Дело в том, что имя типа примитива содержится в другой таблице и не выбирается из базы данных в нашем случае.

Чтобы исправить эту ошибку нужно лишь изменить наш запрос на следующий:


using (var ctx = new
GameDBEntities())

{


foreach (var item in ctx.Primitives.Include(«PrimitiveTypes»))

{

primitives.Add(new
MyPrimitive(this, item));

}

}

Такой вид запроса загрузит и связанные строки из таблицы PrimitiveTypes вместе со строками из Primitives.

Теперь, если все сделано правильно, мы увидим такую картинку (да, примитивы можно было расположить и получше):


Исходный код:

Game1.cs

using System;

using System.Collections.Generic;

using System.Linq;

using Microsoft.Xna.Framework;

using Microsoft.Xna.Framework.Audio;

using Microsoft.Xna.Framework.Content;

using Microsoft.Xna.Framework.GamerServices;

using Microsoft.Xna.Framework.Graphics;

using Microsoft.Xna.Framework.Input;

using Microsoft.Xna.Framework.Media;

using Microsoft.Xna.Framework.Net;

using Microsoft.Xna.Framework.Storage;

using Primitives3D;

using MyGame.Context;

namespace MyGame

{


///
<summary>


/// This is the main type for your game


///
</summary>


public
class
Game1 : Microsoft.Xna.Framework.Game

{


GraphicsDeviceManager graphics;


SpriteBatch spriteBatch;


Light light;


DebugInfo debugInfo;


Effect effect;


List<MyPrimitive> primitives;


FreeCamera camera;


KeyboardState oldState;


float specularPower = 8;


public Game1()

{

graphics = new
GraphicsDeviceManager(this);

Content.RootDirectory = «Content»;

graphics.SynchronizeWithVerticalRetrace = false;

IsFixedTimeStep = false;

}


///
<summary>


/// Allows the game to perform any initialization it needs to before starting to run.


/// This is where it can query for any required services and load any non-graphic


/// related content. Calling base.Initialize will enumerate through any components


/// and initialize them as well.


///
</summary>


protected
override
void Initialize()

{


// TODO: Add your initialization logic here

Components.Add(new
FPSCounter(this));

light = new
Light(this);

light.DefaultPosition = new
Vector3(1, 1, 1);

Components.Add(light);

camera = new
FreeCamera(this, new
Vector3(0, 0, 2), Vector3.Zero);

Components.Add(camera);

debugInfo = new
DebugInfo(this);

Components.Add(debugInfo);

primitives = new
List<MyPrimitive>();


using (var ctx = new
GameDBEntities())

{


foreach (var item in ctx.Primitives.Include(«PrimitiveTypes»))

{

primitives.Add(new
MyPrimitive(this, item));

}

}


base.Initialize();

}


///
<summary>


/// LoadContent will be called once per game and is the place to load


/// all of your content.


///
</summary>


protected
override
void LoadContent()

{


// Create a new SpriteBatch, which can be used to draw textures.

spriteBatch = new
SpriteBatch(GraphicsDevice);


// TODO: use this.Content to load your game content here

effect = Content.Load<Effect>(«light»);

}


///
<summary>


/// UnloadContent will be called once per game and is the place to unload


/// all content.


///
</summary>


protected
override
void UnloadContent()

{


// TODO: Unload any non ContentManager content here

}


///
<summary>


/// Allows the game to run logic such as updating the world,


/// checking for collisions, gathering input, and playing audio.


///
</summary>


///
<param name=»gameTime»>Provides a snapshot of timing values.</param>


protected
override
void Update(GameTime gameTime)

{


// Allows the game to exit


if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)


this.Exit();


// TODO: Add your update logic here


KeyboardState state = Keyboard.GetState();


if (state.IsKeyDown(Keys.Z) && oldState.IsKeyUp(Keys.Z))

{

specularPower = specularPower — 1f;

}


if (state.IsKeyDown(Keys.X) && oldState.IsKeyUp(Keys.X))

{

specularPower = specularPower + 1f;

}


DebugInfo.SetVariable(«specularPower», specularPower.ToString());

oldState = state;


base.Update(gameTime);

}


///
<summary>


/// This is called when the game should draw itself.


///
</summary>


///
<param name=»gameTime»>Provides a snapshot of timing values.</param>


protected
override
void Draw(GameTime gameTime)

{

GraphicsDevice.Clear(Color.Black);


Matrix view = camera.View;


Matrix proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 0.1f, 10f);


// TODO: Add your drawing code here

effect.Parameters[«World»].SetValue(Matrix.CreateRotationY((float)gameTime.TotalGameTime.TotalSeconds));

effect.Parameters[«View»].SetValue(view);

effect.Parameters[«Projection»].SetValue(proj);

effect.Parameters[«LightPosition»].SetValue(light.Position);

effect.Parameters[«SpecularPower»].SetValue(specularPower);

effect.Parameters[«Eye»].SetValue(camera.Position);


foreach (var item in primitives)

{

item.Draw(effect);

}

light.Draw(view, proj);


base.Draw(gameTime);

}

}

}

MyPrimitive.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Primitives3D;

using Microsoft.Xna.Framework;

using Microsoft.Xna.Framework.Graphics;

using MyGame.Context;

namespace MyGame

{


class
MyPrimitive

{


GeometricPrimitive primitive;


public
Vector3 Position;


public MyPrimitive(Game game, Primitives DBPrimitive)

{


switch (DBPrimitive.PrimitiveTypes.Name)

{


case
«Teapot»: primitive = new
TeapotPrimitive(game.GraphicsDevice);


break;


case
«Cube»: primitive = new
CubePrimitive(game.GraphicsDevice);


break;


case
«Torus»: primitive = new
TorusPrimitive(game.GraphicsDevice);


break;


default: primitive = new
TeapotPrimitive(game.GraphicsDevice);


break;

}

Position = new
Vector3((float)DBPrimitive.X, (float)DBPrimitive.Y, (float)DBPrimitive.Z);

}


public
void Draw(Effect effect)

{

effect.Parameters[«World»].SetValue(Matrix.CreateTranslation(Position));

primitive.Draw(effect);

}

}

}

Реклама
Запись опубликована в рубрике Компьютерная графика, Uncategorized с метками , , , , , , . Добавьте в закладки постоянную ссылку.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s