|
При выполнении в лабораторной работе упражнения №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" или один из зависимых от них компонентов. Не удается найти указанный файл. Делаю все пунктуально. В чем может быть проблема? |
Компьютерная 2D-графика в Microsoft XNA Game Studio 3.0
Добавление игрового меню
Игровое меню создадим в виде стартовой страницы приложения, с которой пользователь попадает в основной процесс. На заставке экрана меню мы нарисуем две дощечки с надписями Игра и Выход, имитирующие стандартные кнопки. Переключение фокуса между кнопками закрепим за клавишами "Стрелка вверх" и "Стрелка вниз" . Надпись на неактивной кнопке будем подкрашивать желтым цветом, а активную кнопку будем сдвигать влево на 50 пикселов.
Появление меню на экране будем регулировать флагом menuState, который изначально при запуске приложения будет поднят, а при входе в игру мы его сбросим. За переходом между кнопками меню будем следить с помощью целой переменной buttonState: значение 1 - фокус на кнопке Игра, значение 2 - фокус на кнопке Выход. Клавиша Enter будет активизировать команду текущей кнопки. Клавиша Esc будет вызывать меню из процесса игры.
Для описания игрового меню создадим отдельный класс с именем Menu. С помощью этого класса нужно будет загрузить в игру общий фон меню и на этом фоне нарисовать две кнопки с надписями.
-
Вызовите в проводнике решений Solution Explorer контекстное меню для узла проекта с именем Game2D и командой Add/New Item добавьте к проекту новый класс с именем Menu
-
Скопируйте из файла StartGame.cs все инструкции using и замените ими инструкции using в файле Menu.cs
-
Отредактируйте класс Menu следующим образом
class Menu
{
// Закрытые поля-ссылки на рисунки
Texture2D menuTexture; // Заставка меню
public Texture2D buttonGame; // Кнопка входа в игру
public Texture2D buttonExit; // Кнопка выхода из приложения
// Закрытые поля-ссылки на координаты
Vector2 menuPosition, buttonGamePosition, buttonExitPosition;
// Свойства
public Vector2 ButtonGamePosition
{
get { return buttonGamePosition; }
set { buttonGamePosition = value; }
}
public Vector2 ButtonExitPosition
{
get { return buttonExitPosition; }
set { buttonExitPosition = value; }
}
// Конструктор
public Menu()
{
menuPosition = new Vector2(0, 0);
buttonGamePosition = new Vector2(650, 400);
buttonExitPosition = new Vector2(700, 550);
}
// Загрузка рисунков
public void Load(ContentManager content)
{
menuTexture = content.Load<Texture2D>("Textures\\menu");
buttonGame = content.Load<Texture2D>("Textures\\buttonGame");
buttonExit = content.Load<Texture2D>("Textures\\buttonExit");
}
// Вывод на экран
public void DrawMenu(SpriteBatch spriteBatch, int buttonState)
{
spriteBatch.Draw(menuTexture, menuPosition, Color.White);
switch (buttonState)
{
case 1:
spriteBatch.Draw(buttonGame, buttonGamePosition, Color.White);
spriteBatch.Draw(buttonExit, buttonExitPosition, Color.Yellow);
break;
case 2:
spriteBatch.Draw(buttonGame, buttonGamePosition, Color.Yellow);
spriteBatch.Draw(buttonExit, buttonExitPosition, Color.White);
break;
}
}
}-
Выделите в проводнике решений узел Textures и командой Add/Existing Item скопируйте в проект из прилагаемого каталога Source файлы с рисунками menu, buttonGame, buttonExit
Подключим класс Menu к основному классу игры StartGame.
-
Объявите и инициализируйте в начале класса StartGame три поля следующим образом
public class StartGame : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Sprite[] sprite = new Sprite[5];
Sprite platform = new Sprite();
//Для хранения шрифтов
SpriteFont font1, font2;
// Для управления меню
Menu menu = new Menu();
bool menuState = true;
int buttonState = 1;
...............................................
}-
Добавьте в конец метода LoadContent() код загрузки рисунков меню
protected override void LoadContent()
{
................................................
// Загрузка спрайтов шрифтов
font1 = this.Content.Load<SpriteFont>("Fonts\\font1");
font2 = this.Content.Load<SpriteFont>("Fonts\\font2");
// Загрузка спрайтов меню
menu.Load(this.Content);
}-
В метод Update() класса StartGame вставьте код, организующий логику управления меню в зависимости от нажатия закрепленных клавиш и состояния флагов
KeyboardState keyboardState;
protected override void Update(GameTime gameTime)
{
// Выход из игры...
// Читать буфер клавиатуры
keyboardState = Keyboard.GetState();
// Выход в меню из игрового процесса
if (keyboardState.IsKeyDown(Keys.Escape))
menuState = true;
// Показываем меню
if (menuState) ///////////// if /////////////
{
// Отслеживаем управление клавиатурой
if (keyboardState.IsKeyDown(Keys.Up))
{
buttonState = 1;
menu.ButtonGamePosition = new Vector2(650, 400);
menu.ButtonExitPosition = new Vector2(700, 550);
}
else if (keyboardState.IsKeyDown(Keys.Down))
{
buttonState = 2;
menu.ButtonGamePosition = new Vector2(700, 400);
menu.ButtonExitPosition = new Vector2(650, 550);
}
// Распознаем клавишу Enter для новой игры
if (buttonState == 1 && keyboardState.IsKeyDown(Keys.Enter))
{
this.NewGame();
menuState = false;
}
// Распознаем клавишу Enter для завершения приложения
else if (buttonState == 2 && keyboardState.IsKeyDown(Keys.Enter))
{
this.Exit();
}
} //////////// end if ////////////
// Игровой процесс
else
{ ///////////// else /////////////
// Все движение посадим на проверку условия флага паузы
Pause();// Отслеживание клавиши паузы и поднятие флага
if (paused == false)
{
// Смена кадров
double elapsed = gameTime.ElapsedGameTime.TotalSeconds;
for (int i = 0; i < sprite.Length; i++)
sprite[i].UpdateFrame(elapsed);
// Перемещение сверху вниз на величину speedSprite
MoveSprite();
// Перемещение платформы по экрану
MovePlatform();
// Проверка столкновений и реакция на них
Collisions();
}
} /////////// end else ///////////
base.Update(gameTime);
}
// Новая игра
void NewGame()
{
// Сброс очков
for (int i = 0; i < scores.Length; i++)
scores[i] = 0;
// Начальные позиции объектов
this.Initialize();
}-
Откорректируйте функцию Draw(), которая в зависимости от состояния флага menuState будет рисовать либо меню, либо объекты игры
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// Рисуем меню
if (menuState)
{
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
menu.DrawMenu(spriteBatch, buttonState); // Рисует меню
spriteBatch.End();
}
else ////////////// else ////////////////
{
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
spriteBatch.Draw(background1, new Vector2(0, 0), Color.White);
for (int i = 0; i < sprite.Length; i++)
sprite[i].DrawAnimationSprite(spriteBatch);
spriteBatch.Draw(background2, new Vector2(0, 0), Color.White);
platform.DrawSprite(spriteBatch);// В верхний слой над тросом
// Вывод текста
if (paused)
{
spriteBatch.DrawString(font2,
"Pause",
new Vector2(350, 100),
Color.Red);
}
int shift = 248;
for (int i = 0; i < 5; i++)
{
spriteBatch.DrawString(font1,
scores[i].ToString(),
new Vector2(this.Window.ClientBounds.Width - 95, shift),
Color.White);
shift += 35;
}
spriteBatch.End();
} /////////////////// end else ///////////////////
base.Draw(gameTime);
}-
Откомпилируйте проект
в проводнике решений Solution Explorer через контекстное меню для
узла проекта Game2D командой Rebuild, запустите игру и убедитесь
в ее работоспособности
Добавление управления мышью
Задействуем механизм работы с мышью, с помошью которого мы будем выбирать опции в игровом меню. Прежде всего необходимо добавить графическое изображение курсора. Затем в отдельном методе организуем получение координат курсора, слежение за пересечением ограничивающих прямоугольников курсора и кнопок меню, а также обработку нажатия левой кнопки мыши.
Код предыдущего раздела, касающийся выбора пунктов меню с помощью клавиатуры, можно полностью удалить, тогда пользователь запуском игры и выходом из нее будет управлять только мышью. Но если ничего не удалять, то будет возможность использовать параллельно клавиатуру и мышь. Удалять механизм запуска игры с клавиатуры не будем.
-
Через проводник решений добавьте в узел Textures спрайт с изображением курсора и именем mouse из прилагаемого к работе каталога Source
-
Добавьте в класс StartGame поля-ссылки на объекты, связанные с механизмом работы мыши
public class StartGame : Microsoft.Xna.Framework.Game
{
...............................................
// Для управления меню с помощью мыши
Sprite mouse = new Sprite();// Объект изображения курсора
MouseState mouseState; // Структура состояния мыши (нажатие кнопок, координаты,...)
BoundingBox bbMouse; // Структура граничивающего прямоугольника курсора
BoundingBox bbButtonGame; // Структура ограничивающего прямоугольника верхней кнопки меню
BoundingBox bbButtonExit; // Структура ограничивающего прямоугольника нижней кнопки меню
...............................................
}-
Добавьте в метод LoadContent() класса StartGame загрузку спрайта в объект
protected override void LoadContent()
{
..................................................
// Загрузка спрайта курсора мыши
mouse.Load(this.Content, "Textures\\mouse");
}Код управления мышью мы упакуем в классе StartGame в отдельный метод с именем UpdateMouse(), в котором будем определять координаты курсора, фиксировать факт пересечения ограничивающих прямоугольников курсора и кнопок меню и определять при этом состояние левой кнопки мыши.
-
Добавьте в класс StartGame следующую функцию с именем UpdateMouse()
// Функция управления с помощью мыши
void UpdateMouse()
{
// Читаем координаты мыши
mouseState = Mouse.GetState();
// Присваиваем координаты мыши левому верхнему углу спрайта курсора
mouse.spritePosition = new Vector2(mouseState.X, mouseState.Y);
// Создаем ограничивающий прямоугольник для курсора
// размером 1x1 пиксел на конце стрелы
bbMouse.Min = new Vector3(mouse.spritePosition.X,
mouse.spritePosition.Y, 0);
bbMouse.Max = new Vector3(mouse.spritePosition.X + 1,
mouse.spritePosition.Y + 1, 0);
// Создаем ограничивающие прямоугольники для кнопок меню
bbButtonGame.Min = new Vector3(menu.ButtonGamePosition.X,
menu.ButtonGamePosition.Y, 0);
bbButtonGame.Max = new Vector3(menu.ButtonGamePosition.X +
menu.buttonGame.Width,
menu.ButtonGamePosition.Y +
menu.buttonGame.Height, 0);
bbButtonExit.Min = new Vector3(menu.ButtonExitPosition.X,
menu.ButtonExitPosition.Y, 0);
bbButtonExit.Max = new Vector3(menu.ButtonExitPosition.X +
menu.buttonExit.Width,
menu.ButtonExitPosition.Y +
menu.buttonExit.Height, 0);
// Обрабатываем пересечение ограничивающих прямоугольников
if (bbMouse.Intersects(bbButtonGame))
{
buttonState = 1;
menu.ButtonGamePosition = new Vector2(650, 400);
menu.ButtonExitPosition = new Vector2(700, 550);
}
if (bbMouse.Intersects(bbButtonExit))
{
buttonState = 2;
menu.ButtonGamePosition = new Vector2(700, 400);
menu.ButtonExitPosition = new Vector2(650, 550);
}
// Распознаем нажатие левой кнопки мыши
if (mouseState.LeftButton == ButtonState.Pressed &&
bbMouse.Intersects(bbButtonGame))
{
this.NewGame();
menuState = false;
}
else if (mouseState.LeftButton == ButtonState.Pressed &&
bbMouse.Intersects(bbButtonExit))
{
this.Exit();
}
}-
Вставьте вызов функции UpdateMouse() в функцию Update() основного класса StartGame
protected override void Update(GameTime gameTime)
{
// Выход из игры...
// Читать буфер клавиатуры
keyboardState = Keyboard.GetState();
// Выход в меню из игрового процесса
if (keyboardState.IsKeyDown(Keys.Escape))
menuState = true;
// Показываем меню
if (menuState)
{
// Отслеживаем управление мышью
UpdateMouse();
// Отслеживаем управление клавиатурой
........................................
}
// Игровой процесс
else
{
........................................
}
base.Update(gameTime);
}-
Откорректируйте функцию Draw(), которая в состоянии флага menuState=true кроме рисования меню будет рисовать и курсор мыши
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// Рисуем меню
if (menuState)
{
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
menu.DrawMenu(spriteBatch, buttonState);
mouse.DrawSprite(spriteBatch);
spriteBatch.End();
}
else
{
...........................................
}
base.Draw(gameTime);
}-
Откомпилируйте процесс в проводнике решений Solution Explorer через контекстное меню для узла проекта Game2D командой Rebuild, запустите игру и убедитесь в ее работоспособности


