При выполнении в лабораторной работе упражнения №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
Добавление меню
Для формирования заставки с элементами меню создадим игровой класс MenuScreen. Меню будет содержать фоновую заставку, титульный заголовок, подсказку действий пользователя по выбору вариантов и аналоги кнопок выбора команд. Как и в двух предыдущих заставках оставим три мяча, вращающихся относительно центра в плоскости экрана.
В центре экрана разместим команды:
- Игра - режим GameScreen
- Помощь - режим HelpScreen
- О программе - режим AboutScreen
- Выход - завершение работы
Каждую команду будем представлять текстовой надписью, под которую будем подкладывать желтый прямоугольник, если она имеет фокус ввода. Для этого придется подключить кириллический шрифт требуемого размера и гарнитуры. По краям экрана для украшательства разместим фигуры ' girl ' свободного поведения. И еще уберем отображение пуль.
- Добавьте из прилагаемого к работе каталога Source в папку Textures проекта файлы menu.jpg, cursorMenu.png, girlLeft.png, girlRight.png
- Добавьте к папке Content подпапку Fonts
- Добавьте в папку Fonts файл font.spritefont
- Откорректируйте файл font.spritefont следующим образом
<?xml version="1.0" encoding="utf-8"?> <XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics"> <Asset Type="Graphics:FontDescription"> <FontName>Arial</FontName> <Size>24</Size> <Spacing>0</Spacing> <UseKerning>true</UseKerning> <Style>Bold</Style> <CharacterRegions> <CharacterRegion> <Start> </Start> <End>~</End> </CharacterRegion> <CharacterRegion> <Start>А</Start> <End>я</End> </CharacterRegion> </CharacterRegions> </Asset> </XnaContent>
- Скопируйте файл HelpScreen.cs и назовите копию MenuScreen.cs
- Откорректируйте файл следующим образом
using System; using System.Collections.Generic; 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; namespace Game3D { // Объявление состояний меню enum MenuState { Game, // Меню установлено на первой позиции Help, About, Esc } class MenuScreen { #region Поля класса // Объекты рисунков Texture2D menu, title, enter, cursorMenu, girlLeft, girlRight; // Объекты мячей ModelClass [] ball = new ModelClass[3]; float aspectRatio; // Коэффициент искажения проекции float FOV = MathHelper.PiOver4; // Ракурс камеры 45 градусов float nearClip = 1.0f; // Ближняя отсекающая плоскость float farClip = 1000.0f; // Дальняя отсекающай плоскость float angle = 0; // Угол поворота Matrix world, view, proj; // Матрицы преобразований SpriteFont font; // Для загрузки шрифта Arial 24 Bold String[] menuCommant = { // Команды меню "Игра", "Помощь", "О программе", "Выход" }; #endregion // Инициализация объектов // content - контент экземпляра основного класса игры // width - текущаяя ширина экрана // height - текущая высота экрана public void InitializeSplashScreen(ContentManager content, int width, int height) { // Создаем объекты для мячей for (int i = 0; i < ball.Length; i++) ball[i] = new ModelClass(); // Загружаем в объекты изображения и модели мячей menu = content.Load<Texture2D>("Textures\\menu"); cursorMenu = content.Load<Texture2D>("Textures\\cursorMenu"); title = content.Load<Texture2D>("Textures\\title"); enter = content.Load<Texture2D>("Textures\\enter"); girlLeft = content.Load<Texture2D>("Textures\\girlLeft"); girlRight = content.Load<Texture2D>("Textures\\girlRight"); ball[0].Load(content, "Models\\Soccerball"); ball[0].Position = new Vector3(-30, 40, -30); ball[1].Load(content, "Models\\SoccerballGreen"); ball[1].Position = new Vector3(50, 30, -50); ball[2].Load(content, "Models\\SoccerballRed"); ball[2].Position = new Vector3(-50, -30, 40); // Коэффициент искажения проекции aspectRatio = (float)width / height; // Загружаем шрифт font = content.Load<SpriteFont>("Fonts\\font"); } // Вывод заставки на экран // spriteBatch - объект рисования спрайтов // graphics - объект графического устройства GDI // width - текущаяя ширина экрана // height - текущая высота экрана // gameTime - длительность одного такта игры public void DrawScreen(SpriteBatch spriteBatch, GraphicsDeviceManager graphics, int width, int height, GameTime gameTime, int menuState) { // Очищаем экран своим цветом graphics.GraphicsDevice.Clear(Color.DarkGreen); // Рисуем в GDI плоские компоненты относительно центра экрана и в Z-последовательности spriteBatch.Begin(SpriteBlendMode.AlphaBlend); spriteBatch.Draw(menu, new Vector2(width / 2 - menu.Width / 2, height / 2 - menu.Height / 2), Color.White); spriteBatch.Draw(title, new Vector2(width / 2 - title.Width / 2, 30), // Чуть опустили Color.White); spriteBatch.Draw(enter, new Vector2(width / 2 - enter.Width / 2, height - enter.Height - 30), // Чуть приподняли Color.White); // Рисуем girls spriteBatch.Draw(girlLeft, new Vector2( 0, height / 2 - girlLeft.Height / 2), Color.White); spriteBatch.Draw(girlRight, new Vector2( width - girlRight.Width, height / 2 - girlRight.Height / 2), Color.White); spriteBatch.End(); // Рисуем мячи graphics.GraphicsDevice.RenderState.DepthBufferEnable = true;// Включаем буфер глубины view = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 250.0f), Vector3.Zero, Vector3.Up); proj = Matrix.CreatePerspectiveFieldOfView(FOV, aspectRatio, nearClip, farClip); angle += (float)(gameTime.ElapsedGameTime.TotalSeconds * 1.0f); Matrix rotationMatrixY = Matrix.CreateRotationY(angle); Matrix rotationMatrixZ = Matrix.CreateRotationZ(angle); for (int i = 0; i < ball.Length; i++) { world = Matrix.CreateTranslation(ball[i].Position); ball[i].DrawModel(rotationMatrixY * world * rotationMatrixZ, view, proj); } // Рисуем надписи меню и фон spriteBatch.Begin(SpriteBlendMode.AlphaBlend); int posX=width / 2 + width / 7; int posY= height / 2; int shift = 50; spriteBatch.Draw(cursorMenu, new Vector2(posX - 7, posY + shift * menuState), Color.White); for (int i = 0; i < menuCommant.Length; i++) { spriteBatch.DrawString(font, menuCommant[i], new Vector2(posX, posY), Color.Red); posY += shift; } spriteBatch.End(); } } }
Обратите внимание, что расчет координат вывода графических компонентов мы ведем относительно центра экрана с учетом текущих значений его ширины и высоты. Разрешение экрана у разных пользователях может отличаться, а такой подход позволяет сохранить компоновку графических элементов на экране при разном разрешении. Для этого мы сами жестко и не устанавливаем размеры экрана, а пользуемся текущими настройками.
- Для тестирования разработанного класса MenuScreen введите временно следующие изменения в основной класс игры
public class StartGame3D : Microsoft.Xna.Framework.Game { #region Поля класса GraphicsDeviceManager graphics; SpriteBatch spriteBatch; int screenWidth, screenHeight; // Размеры экрана KeyboardState keyboardState; // Буфер клавиатуры GameState gameState = GameState.MenuScreen; // Переменная состояния игры 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(); // Создание объекта для рисунка пейзажа Game2D.Sprite background = new Game2D.Sprite(); // Создание объектов для других состояний экранов SplashScreen splash = new SplashScreen(); AboutScreen about = new AboutScreen(); HelpScreen help = new HelpScreen(); MenuScreen menu = new MenuScreen(); int menuState = (int)MenuState.Game; #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); // Инициализация объектов других состояний экранов splash.InitializeSplashScreen(this.Content, screenWidth, screenHeight); about.InitializeSplashScreen(this.Content, screenWidth, screenHeight); help.InitializeSplashScreen(this.Content, screenWidth, screenHeight); menu.InitializeSplashScreen(this.Content, screenWidth, screenHeight); } ........................................................ protected override void Update(GameTime gameTime) { // Читать буфер клавиатуры keyboardState = Keyboard.GetState(); switch (gameState) { case GameState.AboutScreen: // Выход из игрового процесса if (keyboardState.IsKeyDown(Keys.Escape)) this.Exit(); break; case GameState.GameOverScreen: break; case GameState.GameScreen: // Выход из игрового процесса if (keyboardState.IsKeyDown(Keys.Escape)) this.Exit(); MoveBalls(); MouseClick(); break; case GameState.HelpScreen: // Выход из игрового процесса if (keyboardState.IsKeyDown(Keys.Escape)) this.Exit(); break; case GameState.MenuScreen: // Выход из игрового процесса if (keyboardState.IsKeyDown(Keys.Escape)) this.Exit(); break; case GameState.SplashScreen: // Выход из игрового процесса if (keyboardState.IsKeyDown(Keys.Escape)) this.Exit(); break; case GameState.VictotyScreen: break; } base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); switch (gameState) { case GameState.AboutScreen: about.DrawScreen(this.spriteBatch, this.graphics, screenWidth, screenHeight, gameTime); break; case GameState.GameOverScreen: break; case GameState.GameScreen: .................................................. break; case GameState.HelpScreen: help.DrawScreen(this.spriteBatch, this.graphics, screenWidth, screenHeight, gameTime); break; case GameState.MenuScreen: menu.DrawScreen( this.spriteBatch, this.graphics, screenWidth, screenHeight, gameTime, menuState); break; case GameState.SplashScreen: splash.DrawScreen(this.spriteBatch, this.graphics, screenWidth, screenHeight, gameTime); break; case GameState.VictotyScreen: break; } base.Draw(gameTime); } }
- Запустите приложение и убедитесь, что код класса MenuScreen работает нормально в основном цикле игры. Должна получиться примерно такая картинка