|
При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода: 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.Graphics;
namespace Application1 { public partial class MainForm : Form { // Объявим поле графического устройства для видимости в методах GraphicsDevice device;
public MainForm() { InitializeComponent();
// Подпишемся на событие Load формы this.Load += new EventHandler(MainForm_Load);
// Попишемся на событие FormClosed формы this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed); }
void MainForm_FormClosed(object sender, FormClosedEventArgs e) { // Удаляем (освобождаем) устройство device.Dispose(); // На всякий случай присваиваем ссылке на устройство значение null device = null; }
void MainForm_Load(object sender, EventArgs e) { // Создаем объект представления для настройки графического устройства PresentationParameters presentParams = new PresentationParameters(); // Настраиваем объект представления через его свойства presentParams.IsFullScreen = false; // Включаем оконный режим presentParams.BackBufferCount = 1; // Включаем задний буфер // для двойной буферизации // Переключение переднего и заднего буферов // должно осуществляться с максимальной эффективностью presentParams.SwapEffect = SwapEffect.Discard; // Устанавливаем размеры заднего буфера по клиентской области окна формы presentParams.BackBufferWidth = this.ClientSize.Width; presentParams.BackBufferHeight = this.ClientSize.Height;
// Создадим графическое устройство с заданными настройками device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.Handle, presentParams); }
protected override void OnPaint(PaintEventArgs e) { device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);
base.OnPaint(e); } } } Выбрасывается исключение: Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл. Делаю все пунктуально. В чем может быть проблема? |
Компьютерная графика 3D в XNA
Формирование трехмерной сцены
В этом разделе мы загрузим в игру модель стадиона, на фоне которой будут летать мячи, и установим камеру под определенным углом, одинаковым и для мячей и для стадиона.
-
В классе StartGame3D установите
новое значение поля camera для выбора наилучшего ракурса (угла зрения)
всей сцены игры и добавьте объект стадиона, в который мы позднее загрузим
трехмерный мэш
public class StartGame3D : Microsoft.Xna.Framework.Game
{
#region Поля класса
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
int screenWidth, screenHeight; // Размеры экрана
KeyboardState keyboardState; // Буфер клавиатуры
GameState gameState = GameState.GameScreen; // Переменная состояния игры
Matrix world;
Matrix view;
Matrix proj;
float aspectRatio;
float FOV = MathHelper.PiOver4;
float nearClip = 1.0f;
float farClip = 1000.0f;
//Vector3 camera = new Vector3(0.0f, 0.0f, 150.0f);
Vector3 camera = new Vector3(0.0f, 20.0f, 250.0f);
//ModelClass ball;
ModelClass[] ball = new ModelClass[3];
MouseState mouseState;
Random rand = new Random();
// Создание объекта курсора-прицела
Game2D.Sprite cursor = new Game2D.Sprite();
// Создание объекта модели стадиона
ModelClass stadium = new ModelClass();
#endregion
..................................................
}-
Добавьте из прилагаемого
каталога Source в папку Models проекта файл с именем stadium 1.x
-
В методе LoadContent() основного
класса игры загрузите модель стадиона в созданный ранее объект stadium программы
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
//ball.Load(this.Content, "Models\\Soccerball");
// Загружаем модели мячей
ball[0].Load(this.Content, "Models\\Soccerball");
ball[1].Load(this.Content, "Models\\SoccerballGreen");
ball[2].Load(this.Content, "Models\\SoccerballRed");
// Загружаем трехмерную модель стадиона
stadium.Load(this.Content, "Models\\stadium 1");
// Устанавливаем начальную позицию объектов
BeginPosition();
// Загружаем рисунок курсора-прицела
cursor.Load(this.Content, "Textures\\cursor");
}-
В методе Draw() основного
класса игры вставьте код вывода изображения стадиона на экран монитора (раньше
кода вывода других объектов)
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
switch (gameState)
{
case GameState.AboutScreen:
break;
case GameState.GameOverScreen:
break;
case GameState.GameScreen:
// Включить буфер глубины
graphics.GraphicsDevice.RenderState.DepthBufferEnable = true;
// Установить камеру
view = Matrix.CreateLookAt(camera, Vector3.Zero, Vector3.Up);
// Задать проекционную матрицу
proj = Matrix.CreatePerspectiveFieldOfView(FOV,
aspectRatio, nearClip, farClip);
// Определить матрицу преобразования
//world = Matrix.CreateTranslation(ball.Position);
// Нарисовать модель в начальном состоянии
//ball.DrawModel(world, view, proj);
// Нарисовать модель стадиона самой первой
world = Matrix.CreateTranslation(new Vector3(0, 0, 0));
stadium.DrawModel(world, view, proj);
// Нарисовать модели мячей
for (int i = 0; i < ball.Length; i++)
{
// Определить матрицу преобразования
world = Matrix.CreateTranslation(ball[i].Position);
// Нарисовать модель в начальном состоянии
ball[i].DrawModel(world, view, proj);
}
// Нарисовать курсор-прицел
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
cursor.DrawSprite(spriteBatch);
spriteBatch.End();
break;
case GameState.HelpScreen:
break;
case GameState.MenuScreen:
break;
case GameState.SplashScreen:
break;
case GameState.VictotyScreen:
break;
}
base.Draw(gameTime);
}-
Запустите игру и убедитесь,
что начальные позиции мячей нуждаются в корректировке
Обратите внимание на позиции установки всех моделей игры, включая камеру. Если бы камера была совмещена с экраном монитора, то начало мировой системы координат находилось бы в плоскости экрана. Позиции мячей мы формируем в отрицательном направлении оси Oz в диапазоне [-20,-150] пикселов. Сам стадион рисуем относительно начала мировой системы координат. И для того, чтобы увидеть его целиком, мы камеру отодвинули в положительном направлении на 250 пикселов. В результате мячи удалились от наблюдателя и к тому же падают на дальней границе стадиона. Поэтому нужно приблизить мячи к наблюдателю, скорректировав их начальные координаты по оси Oz в новом диапазоне [-50,150].
-
Введите изменения в
код функций BeginPosition() и MouseClick(), где задается координата z полета мячей
// Устанавливаем начальную позицию объекта
void BeginPosition()
{
for (int i = 0; i < ball.Length; i++)
{
ball[i].Position = new Vector3(
rand.Next(-rand.Next(0, 80), rand.Next(0, 80)),
rand.Next(0, 80),
//-rand.Next(20, 150));
rand.Next(-rand.Next(0, 50), rand.Next(0, 150)));
}
}
.....................................................
// Механизм стрельбы по целям
BoundingSphere[] bb = new BoundingSphere[3];
void MouseClick()
{
// Получаем текущие координаты курсора и передаем их центру объекта прицела
mouseState = Mouse.GetState();
cursor.spritePosition.X = mouseState.X - cursor.spriteTexture.Width / 2;
cursor.spritePosition.Y = mouseState.Y - cursor.spriteTexture.Height / 2;
// Одеваем на каждый мячик ограничивающую сферу с заданным радиусом
for (int i = 0; i < bb.Length; i++)
{
bb[i].Center = ball[i].Position;
bb[i].Radius = ball[i].Radius;
}
// Определяем попадание и при успехе
// устанавливаем мяч в начальную позицию
if (mouseState.LeftButton == ButtonState.Pressed)
{
// Пересчитываем координаты курсора на трехмерный объем
Ray pickRay = GetPickRay();
// Проверяем попадание
for (int i = 0; i < ball.Length; i++)
{
Nullable<float> result = pickRay.Intersects(bb[i]);
if (result.HasValue == true)
{
ball[i].Position = new Vector3(
rand.Next(-rand.Next(0, 80), rand.Next(0, 80)),
rand.Next(0, 80),
//-rand.Next(20, 150));
rand.Next(-rand.Next(0, 50), rand.Next(0, 150)));
}
}
}
}-
Запустите приложение
и убедитесь, что мячи теперь падают над поверхностью поля стадиона
Нам нужно сделать, чтобы мячи останавливались на поверхности поля, а не проваливались сквозь него. Поверхность поля стадиона проходит через ось Oy мировой системы координат на расстоянии ( -32 ) пиксела, поэтому двигать мячи в вертикальном направлении следует только до этой величины.
-
Внесите следующие изменения
в функцию MoveBalls() основного класса игры
void MoveBalls()
{
for (int i = 0; i < ball.Length; i++)
{
if (ball[i].Position.Y > -32)
ball[i].Position -= new Vector3(0, ball[i].Speed, 0);
}
}-
Запустите приложение
и убедитесь, что мячи теперь останавливаются на поверхности поля стадиона
Дополним сцену подходящим задним фоном, чтобы стадион и вся сцена смотрелись более красочно.
-
Добавьте в папку Textures проекта файл hallake001.png из прилагаемого каталога Source
-
В классе StartGame3D добавьте поле-ссылку background для хранения объекта текстуры, а в
методах LoadContent() и Draw() - код загрузки и вывода рисунка на экран
#region Поля класса
..................................................
// Создание объекта модели стадиона
ModelClass stadium = new ModelClass();
// Создание объекта для рисунка пейзажа
Game2D.Sprite background = new Game2D.Sprite();
#endregion
..................................................
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
//ball.Load(this.Content, "Models\\Soccerball");
// Загружаем модели мячей
ball[0].Load(this.Content, "Models\\Soccerball");
ball[1].Load(this.Content, "Models\\SoccerballGreen");
ball[2].Load(this.Content, "Models\\SoccerballRed");
// Загружаем трехмерную модель стадиона
stadium.Load(this.Content, "Models\\stadium 1");
// Устанавливаем начальную позицию объектов
BeginPosition();
// Загружаем рисунок курсора-прицела
cursor.Load(this.Content, "Textures\\cursor");
// Загружаем рисунок заднего фона
background.Load(this.Content, "Textures\\hallake001");
// Чуть приподнимем вверх экрана
background.spritePosition = new Vector2(0, -50);
}
..................................................
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
switch (gameState)
{
case GameState.AboutScreen:
break;
case GameState.GameOverScreen:
break;
case GameState.GameScreen:
// Нарисовать фон самым первым
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
background.DrawSprite(spriteBatch);
spriteBatch.End();
// Включить буфер глубины
graphics.GraphicsDevice.RenderState.DepthBufferEnable = true;
// Установить камеру
view = Matrix.CreateLookAt(camera, Vector3.Zero, Vector3.Up);
// Задать проекционную матрицу
proj = Matrix.CreatePerspectiveFieldOfView(FOV,
aspectRatio, nearClip, farClip);
// Определить матрицу преобразования
//world = Matrix.CreateTranslation(ball.Position);
// Нарисовать модель в начальном состоянии
//ball.DrawModel(world, view, proj);
// Нарисовать стадион
world = Matrix.CreateTranslation(new Vector3(0, 0, 0));
stadium.DrawModel(world, view, proj);
// Нарисовать модели мячей
for (int i = 0; i < ball.Length; i++)
{
// Определить матрицу преобразования
world = Matrix.CreateTranslation(ball[i].Position);
// Нарисовать модель в начальном состоянии
ball[i].DrawModel(world, view, proj);
}
// Нарисовать курсор-прицел
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
cursor.DrawSprite(spriteBatch);
spriteBatch.End();
break;
case GameState.HelpScreen:
break;
case GameState.MenuScreen:
break;
case GameState.SplashScreen:
break;
case GameState.VictotyScreen:
break;
}
base.Draw(gameTime);
}-
Запустите приложение
и полюбуйтесь на солидную сцену, сделанную своими руками

