|
При выполнении в лабораторной работе упражнения №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
Добавление звуковых эффектов
Звуковое сопровождение игры является ее неотъемлемым элементом и украшает игру. Прежде всего нужно приготовить все звуковые файлы. Потом загрузить их как объекты в проект игры и далее управлять средствами библиотеки XNA этими звуковыми объектами.
Для нашей игры мы добавим два звуковых эффекта. Один звук будет проигрываться в момент касания платформы и падающего объекта, второй звук запустится, когда объект упадет "в никуда".
-
В проводнике решений выделите узел Content проекта и добавьте к нему командой меню Project/New Folder новую папку с именем Sound
-
В проводнике решений выделите папку Sound и скопируйте в нее командой меню Project/Add Existing Item из прилагаемого к работе каталога Source файлы platform.wav и boom.wav
-
Через проводник решений Solution Explorer выделите в папке Sound скопированные в проект звуковые файлы и в панели Properties установите для них атрибуты компилятора оболочки, как показано на рисунке
Код управления звуком упакуем в отдельный класс.
-
В проводнике решений выделите корневой узел проекта Game2d и добавьте в проект командой Project/Add New Item меню оболочки новый класс C# с именем Sound
Поскольку звук в системе только один, то для управления им (и для тренировки) создадим статический класс. В соответствии с теорией языка C# статическом классе все поля данных и методы должны быть статическими и используется только конструктор по умолчанию.
-
Заполните статический класс Sound следующим кодом
using System;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
namespace Game2D
{
// Перечисление
enum SoundList
{
Platform, // Поймали
Boom // Промазали
}
static class Sound
{
static SoundEffect boom;
static SoundEffect platform;
public static void Load(ContentManager content)
{
boom = content.Load<SoundEffect>("Sound\\boom");
platform = content.Load<SoundEffect>("Sound\\platform");
}
// Воспроизведение звука
public static void Play(SoundList sound)
{
switch (sound)
{
case SoundList.Boom:
boom.Play();
break;
case SoundList.Platform:
platform.Play();
break;
}
}
}
}-
Вставьте использование класса Sound в соответствующие методы основного класса игры StartGame
public class StartGame : Microsoft.Xna.Framework.Game
{
............................................
protected override void LoadContent()
{
........................................
// Загружаем звук
Sound.Load(this.Content);
}
// Функция перемещения сверху вниз на величину speedSprite
void MoveSprite()
{
for (int i = 0; i < sprite.Length; i++)
{
sprite[i].spritePosition += sprite[i].speedSprite;
if (sprite[i].spritePosition.Y > this.Window.ClientBounds.Height)
{
// Сброс координат следующего прохода в начальную точку
...............................................
// Звукнуть плохо
Sound.Play(SoundList.Boom);
}
}
}
void Collisions()
{
...............................................
// Проверка пересечений ограничивающих прямоугольников
// летящих объектов с каймой платформы и реакция на них
for (int i = 0; i < bbSprite.Length; i++)
{
if (bbPlatform.Intersects(bbSprite[i]))
{
// Сброс координат следующего прохода в начальную точку.
// То же, что в методе MoveSprite(), только по другой причине
int minValue = 10;
int maxValue = this.Window.ClientBounds.Width - 300
- sprite[i].spriteTexture.Width / 12;
sprite[i].spritePosition = new Vector2(
rand.Next(minValue, maxValue), -300);
// Подсчет очков по сумме столкновений с объектами
scores[i]++;
// Звукнуть хорошо
Sound.Play(SoundList.Platform);
}
}
}
}-
Перекомпилируйте проект командой Rebuild и испытайте добавленный в игру звук
Добавление суммы очков
Добавим на табло общее количество очков, набранных игроком в текущей игре.
-
Добавьте в класс StartGame поле целого типа totalScores, а в метод Collisions() подсчет суммы очков
int totalScores;
void Collisions()
{
.................................................
// Проверка пересечений ограничивающих прямоугольников
// летящих объектов с каймой платформы и реакция на них
for (int i = 0; i < bbSprite.Length; i++)
{
if (bbPlatform.Intersects(bbSprite[i]))
{
....................................................
// Подсчет очков по сумме столкновений с объектами
scores[i]++;
totalScores++;
// Звукнуть хорошо
Sound.Play(SoundList.Platform);
}
}
}-
Добавьте в метод NewGame() сброс суммы очков
// Новая игра
void NewGame()
{
// Сброс очков
for (int i = 0; i < scores.Length; i++)
scores[i] = 0;
totalScores = 0;
// Начальные позиции объектов
this.Initialize();
}-
В методе Draw() вставьте код печати суммы очков на экране
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 ////////////// 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,
"Пауза в игре!",
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.DrawString(font1,
"Итого: " + totalScores,
new Vector2(this.Window.ClientBounds.Width - 150, shift),
Color.White);
spriteBatch.End();
} /////////////////// end else ///////////////////
base.Draw(gameTime);
}Сохранение рекорда
Для сохранения результата победителя воспользуемся встроенными средствами Visual Studio 2008.
-
Откройте окно свойств
текущего проекта командой Project/Game2D Properties
-
Выберите вкладку Settings и откройте таблицу параметров -
Заполните поля первой
записи таблицы следующим образом
-
Добавьте к функции UnloadContent() следующий код
// Для сохранения очков победителя
Properties.Settings settings = new Properties.Settings();
int victoryScores = 0;
protected override void UnloadContent()
{
// Запомнить рекорд
if (victoryScores > settings.victoryScores)
{
settings.victoryScores = victoryScores;
settings.Save();
}
}-
Добавьте в конец конструктора
класса игры код чтения рекорда
public StartGame()
{
.................................................
// Чтение рекорда
victoryScores = settings.victoryScores;
}-
Добавьте в функцию Collisions() код распознавания рекорда
void Collisions()
{
.........................................................
// Проверка пересечений ограничивающих прямоугольников
// летящих объектов с каймой платформы и реакция на них
for (int i = 0; i < bbSprite.Length; i++)
{
if (bbPlatform.Intersects(bbSprite[i]))
{
......................................................
// Подсчет очков по сумме столкновений с объектами
scores[i]++;
totalScores++;
// Обновление рекорда
if (totalScores > victoryScores)
victoryScores = totalScores;
// Звукнуть хорошо
Sound.Play(SoundList.Platform);
}
}
}-
Добавьте в метод Draw() класса StartGame код вывода рекорда на экран монитора
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 ////////////// else ////////////////
{
........................................................
// Печать суммы очков
spriteBatch.DrawString(font1,
"Итого: " + totalScores,
new Vector2(this.Window.ClientBounds.Width - 150, shift),
Color.White);
// Печать очков победителя
spriteBatch.DrawString(font1, "Рекорд: " + victoryScores,
new Vector2(this.Window.ClientBounds.Width - 175, 225),
Color.White);
spriteBatch.End();
} /////////////////// end else ///////////////////
base.Draw(gameTime);
}-
Откомпилируйте проект
командой Rebuild и убедитесь в работе механизма сохранения очков победителя
Конечно, планировать игру нужно с самого начала, чтобы не пришлось на ходу перестраивать код как в известном анекдоте: "-Ты что программируешь? -А вот сейчас откомпилирую и узнаю!" Но мы шли от простого к сложному, постепенно наращивая код, и нам была важнее - практика программирования, а не планирование (и даже не сама игра).
Мы познакомились с основными этапами построения игрового приложения и дальнейшее усложнение игры становится рутинной работой. Поэтому остановимся на этом и рассмотрим завершающий этап - формирование инсталляционного пакета, чтобы можно было профессионально распространять наш продукт.



