Опубликован: 05.08.2010 | Доступ: свободный | Студентов: 2009 / 47 | Оценка: 4.50 / 4.40 | Длительность: 60:26:00
Самостоятельная работа 2:

Компьютерная графика 3D в XNA

Добавление механизма подсчета очков и уровней сложности

Опишем схему, по которой мы будем вести подсчет очков и изменять уровни сложности игры. Под уровнями сложности будем понимать последовательные этапы в игре, в которых нарастает скорость падения мячей. Ключом для перехода на новый уровень будет служить количество попаданий для каждого мяча (установим 20 попаданий), набранных на текущем уровне. При этом ни один мяч не должен коснуться поля стадиона, в противном случае все очки текущего уровня сгорают.

Текущий уровень и количество попаданий для каждого мяча будем отображать в табло, размещенном в левом верхнем углу экрана режима игры. В табло будут нарисованы три мяча, используемых в игре, над которыми расположим счетчики попаданий, а внизу отобразим текущий уровень игры. Если по какому-то мячу выполнено 20 попаданий, то на нем рисуется крестик, но мяч с экрана не исчезает и все равно продолжает участвовать в игре. Когда по всем мячам будет выполнена норма, то очки сбрасываются и увеличивается уровень.

Всего предусмотрим 8 уровней. При успешном прохождении очередного уровня будем выдавать заставку выигрыша, а в случае падения мяча на поле стадиона - заставку проигрыша. В любом из этих двух режимов при нажатии клавиши Esc пользователь вновь попадает в режим игры. Но при выигрыше на последнем уровне пользователь попадает в меню игры.

  • Добавьте в папку Textures проекта из прилагаемого каталога Source оставшиеся файлы с рисунками:
    • bad.png - проигрыш
    • dagger.png - крестик
    • g1_over.png - girls слева при проигрыше
    • g1_victory.png - girls слева при выигрыше
    • g2_over .png - girls справа при проигрыше
    • g2_victory.png - girls справа при выигрыше
    • good.png - отлично
    • tablo.png - табло

Для управления всеми этими ресурсами создадим специальный класс.

  • Командой Project/Add Class добавьте в корневой узел проекта Game3D новый файл с именем ResultScreen.cs и скопируйте в него из файла StartGame3D.cs секцию using
  • Создайте в каталоге Fonts файл font1.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>12</Size>
    <Spacing>0</Spacing>
    <UseKerning>true</UseKerning>
    <Style>Bold</Style>
    <CharacterRegions>
      <CharacterRegion>
        <Start>&#32;</Start>
        <End>&#126;</End>
      </CharacterRegion>
      <CharacterRegion>
        <Start>&#1040;</Start>
        <End>&#1103;</End>
      </CharacterRegion>
    </CharacterRegions>
  </Asset>
</XnaContent>
  • Дополните класс ResultScreen следующим кодом
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
{
    class ResultScreen
    {
        // Внешние данные
        ContentManager content;
        SpriteBatch spriteBatch;
        int maxScore = 20; // Флаг для рисования крестика
        SpriteFont font;
    
        // Рисунки
        Texture2D bad, dagger, g1_over, g1_victory, g2_over, g2_victory, good, tablo;
    
        // Свойство доступа
        public int MaxScore
        {
            get { return maxScore; }
            set { maxScore = value; }
        }
    
        public ResultScreen() { }   // Конструктор по умолчанию
        public ResultScreen(ContentManager content, SpriteBatch spriteBatch)
        {
            this.content = content;
            this.spriteBatch = spriteBatch;
        }
    
        public void Load()
        {
            // Загружаем шрифт
            font = content.Load<SpriteFont>("Fonts\\font1");
            // Загружаем рисунки
            bad = content.Load<Texture2D>("Textures\\bad");
            dagger = content.Load<Texture2D>("Textures\\dagger");
            g1_over = content.Load<Texture2D>("Textures\\g1_over");
            g1_victory = content.Load<Texture2D>("Textures\\g1_victory");
            g2_over = content.Load<Texture2D>("Textures\\g2_over");
            g2_victory = content.Load<Texture2D>("Textures\\g2_victory");
            good = content.Load<Texture2D>("Textures\\good");
            tablo = content.Load<Texture2D>("Textures\\tablo");
        }
    
        public void DrawResult(int[] scores, int level)
        {
            int x = 0, y = 0;
            spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
            spriteBatch.Draw(tablo, new Vector2(x, y), Color.White);
            int shift = 33;
            for (int i = 0; i < scores.Length; i++)
            {
                spriteBatch.DrawString(font, scores[i].ToString(), new Vector2(x + shift, y + 5), Color.White);
                if (scores[i] >= maxScore)
                    spriteBatch.Draw(dagger, new Vector2(x + shift - 23, y + 37), Color.White);
                shift += 65;
            }
            spriteBatch.DrawString(font, level.ToString(), new Vector2(x + 142, y + 108), Color.White);
            spriteBatch.End();
        }
    
        public void DrawResult(int x, int y, GameState gameState)
        {
            //x = 300;
            //y = 200;
            switch (gameState)
            {
                case GameState.VictotyScreen:
                    spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
                    spriteBatch.Draw(g1_victory, new Vector2(x, y), Color.White);
                    spriteBatch.Draw(good, new Vector2(x + g1_victory.Width + 20, y + 50), Color.White);
                    spriteBatch.Draw(g2_victory, new Vector2(x + g1_victory.Width + good.Width, y), Color.White);
                    spriteBatch.End();
                    break;
                case GameState.GameOverScreen:
                    spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
                    spriteBatch.Draw(g1_over, new Vector2(x, y), Color.White);
                    spriteBatch.Draw(bad, new Vector2(x + g1_over.Width - 20, y + 50), Color.White);
                    spriteBatch.Draw(g2_over, new Vector2(x + g2_over.Width + bad.Width, y), Color.White);
                    spriteBatch.End();
                    break;
            }
        }
    }
}
  • Измените код класса StartGame3D для введения механизма подсчета очков и реализации логики игры
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 GameState
    {
        AboutScreen,    // Экран с информацией об игре
        GameOverScreen, // Экран проигрыша
        GameScreen,     // Экран игрового процесса
        HelpScreen,     // Инструкция о правилах
        MenuScreen,     // Меню игры
        SplashScreen,   // Первая игровая заставка 
        VictotyScreen   // Экран выигрыша
    }
    
    public class StartGame3D : Microsoft.Xna.Framework.Game
    {    
        #region Поля класса 
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        int screenWidth, screenHeight;  // Размеры экрана
        KeyboardState keyboardState;    // Буфер клавиатуры 
        GameState gameState = GameState.SplashScreen;   // Переменная состояния игры
    
        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;
    
        // Флаги освобождения задействованных клавиш 
        bool enterFree = true;  // Enter
        bool upFree=true;       // Стрелка вверх
        bool downFree = true;   // Стрелка вниз
        bool escFree = true;    // Esc
        // Флаг освобождения мыши
        bool mouseFree = true;
    
        // Результаты игры
        ResultScreen resultScreen;
        int[] scores = { 0, 0, 0 };// Порядок индексов: Blue, Green, Red
        int level = 1;
        int maxLevel = 8;
        #endregion
    
        public StartGame3D()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
    
            // Создание экземпляров класса ModelClass   
            //ball = new ModelClass();                  
            for (int i = 0; i < ball.Length; i++)       
            {                                           
                ball[i] = new ModelClass();             
            }           
    
            // Включаем стандартный курсор мыши
            //this.IsMouseVisible = true;        
        }
    
        protected override void Initialize()
        {
            GraphicsAdapter adapter = graphics.GraphicsDevice.
                CreationParameters.Adapter;                     // Получить ссылку на параметры адаптера
            screenWidth = adapter.CurrentDisplayMode.Width;     // Сохранить текущие размеры экрана
            screenHeight = adapter.CurrentDisplayMode.Height;   
            graphics.PreferredBackBufferWidth = screenWidth;    // Настроить размеры экранного буфера
            graphics.PreferredBackBufferHeight = screenHeight;  
            graphics.IsFullScreen = true;                       // Перевести в полноэкранный режим
            graphics.ApplyChanges();                            // Применить настройки
            aspectRatio = (float)screenWidth / screenHeight;    // Коэффициент искажения проекции
    
            base.Initialize();
        }
    
        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);
    
            // Создаем объект с результатами игры
            resultScreen = new ResultScreen(this.Content, spriteBatch);
            resultScreen.Load();
        }
    
        // Устанавливаем начальную позицию объекта
        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)));
            }                                                           
        }
    
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }
    
        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);
                else
                {
                    gameState = GameState.GameOverScreen;// Присуждаем поражение
                    BeginPosition();
                }
            }
        }
    
        // Механизм стрельбы по целям 
        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 && mouseFree)
            {
                // Пересчитываем координаты курсора на трехмерный объем
                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)));
                        scores[i] += 1;
                    }
                }
    
                // Проверяем победу
                if (scores[0] >= resultScreen.MaxScore && scores[1] >= resultScreen.MaxScore 
                    && scores[2] >= resultScreen.MaxScore)
                {
                    gameState = GameState.VictotyScreen;
                    BeginPosition();
                }
            }
    
            // Ждем освобождения кнопки мыши
            mouseFree = mouseState.LeftButton == ButtonState.Released;
        }
    
        protected override void Update(GameTime gameTime)
        {
            // Читать буфер клавиатуры 
            keyboardState = Keyboard.GetState();
    
            switch (gameState)
            {
                case GameState.AboutScreen:
                    // Выход из AboutScreen
                    if (keyboardState.IsKeyDown(Keys.Escape) && escFree)
                        gameState = GameState.MenuScreen;
                    break;
                case GameState.GameOverScreen:
                    // Выход из режима
                    if (keyboardState.IsKeyDown(Keys.Escape) && escFree)
                    {
                        // Сброс очков
                        for (int i = 0; i < scores.Length; i++)
                            scores[i] = 0;
                        gameState = GameState.GameScreen;
                    }
                    break;
                case GameState.GameScreen:
                    // Выход из GameScreen
                    if (keyboardState.IsKeyDown(Keys.Escape) && escFree)
                        gameState = GameState.MenuScreen;
    
                    MoveBalls();
                    MouseClick();
                    break;
                case GameState.HelpScreen:
                    // Выход из HelpScreen
                    if (keyboardState.IsKeyDown(Keys.Escape) && escFree)
                        gameState = GameState.MenuScreen;
                    break;
                case GameState.MenuScreen:
                    // Выход из MenuScreen
                    if (keyboardState.IsKeyDown(Keys.Escape) && escFree)
                        gameState = GameState.SplashScreen;
    
                    // Вход в другие состояния
                    if (keyboardState.IsKeyDown(Keys.Enter) && enterFree)
                    {
                        if ((MenuState)menuState == MenuState.Game)
                            gameState = GameState.GameScreen;
                        else if ((MenuState)menuState == MenuState.Help)
                            gameState = GameState.HelpScreen;
                        else if ((MenuState)menuState == MenuState.About)
                            gameState = GameState.AboutScreen;
                        else if ((MenuState)menuState == MenuState.Esc)
                            gameState = GameState.SplashScreen;
                    }
    
                    // Управление пунктами меню
                    if (keyboardState.IsKeyDown(Keys.Up) && upFree)
                    {
                        menuState--;
                        if (menuState < 0)
                            menuState = 3;
                    }
                    else if (keyboardState.IsKeyDown(Keys.Down) && downFree)
                    {
                        menuState++;
                        menuState %= 4; // Деление по модулю
                    }
                    break;
                case GameState.SplashScreen:
                    // Выход из игрового процесса
                    if (keyboardState.IsKeyDown(Keys.Escape) && escFree)
                        this.Exit();
                    else if (keyboardState.IsKeyDown(Keys.Enter) && enterFree)
                        gameState = GameState.MenuScreen;
                    break;
                case GameState.VictotyScreen:
                    // Выход из режима
                    if (keyboardState.IsKeyDown(Keys.Escape) && escFree)
                    {
                        // Сброс очков
                        for (int i = 0; i < scores.Length; i++)
                            scores[i] = 0;
                        if (level < maxLevel)
                        {
                            level++;
                            gameState = GameState.GameScreen;
                        }
                        else
                        {
                            level = 1;
                            gameState = GameState.MenuScreen;
                        }
                    }
                    break;
            }
    
            // Устанавливаем флаги освобождения клавиш
            enterFree = keyboardState.IsKeyUp(Keys.Enter);
            upFree = keyboardState.IsKeyUp(Keys.Up);
            downFree = keyboardState.IsKeyUp(Keys.Down);
            escFree = keyboardState.IsKeyUp(Keys.Escape);
    
            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:
                    GraphicsDevice.Clear(Color.LightSalmon);
                    resultScreen.DrawResult(300, 200, gameState);
                    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(new Vector3(0, 0, 0));
                    stadium.DrawModel(world, view, proj);
    
                    // Рисуем табло до мячей и курсора
                    resultScreen.DrawResult(scores, level);
    
                    // Нарисовать модели мячей
                    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:
                    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:
                    GraphicsDevice.Clear(Color.PaleGreen);
                    resultScreen.DrawResult(300, 200, gameState);
                    break;
            }
    
            base.Draw(gameTime);
        }
    
        // Метод пересчета координат курсора в трехмерную сцену игры
        Ray GetPickRay()
        {
            // Читаем стандартные координаты курсора
            mouseState = Mouse.GetState();
    
            // Вспомогательные переменные
            int mouseX = mouseState.X;
            int mouseY = mouseState.Y;
            Vector3 nearSource = new Vector3((float)mouseX, (float)mouseY, 0.0f);
            Vector3 farSource = new Vector3((float)mouseX, (float)mouseY, 1.0f);
    
            // Обнуляем мировую матрицу
            world = Matrix.CreateTranslation(0, 0, 0);
            // Матрица вида, как в трехмерной сцене
            view = Matrix.CreateLookAt(camera, Vector3.Zero, Vector3.Up);
            // Матрица проекции, как в трехмерной сцене
            proj = Matrix.CreatePerspectiveFieldOfView(FOV, aspectRatio, nearClip, farClip);
            // Проекция курсора на ближнюю плоскость отсечения объема 
            Vector3 nearPoint = graphics.GraphicsDevice.Viewport.Unproject(nearSource, proj, view, world);
            // Проекция курсора на дальнюю плоскость отсечения объема
            Vector3 farPoint = graphics.GraphicsDevice.Viewport.Unproject(farSource, proj, view, world);
            Vector3 direction = farPoint - nearPoint;
            direction.Normalize();
    
            return new Ray(nearPoint, direction);
        }
    }
}

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

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

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




Алексей Бабушкин
Алексей Бабушкин

При выполнении в лабораторной работе упражнения №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" или один из зависимых от них компонентов. Не удается найти указанный файл.

Делаю все пунктуально. В чем может быть проблема?