Разработка компьютерных игр для Windows Phone 7 с использованием технологий Silverlight и XNA

Озвучивание игр на платформе XNA

Разбить на страницы
Показывать лекцию целиком

Цель работы: Ознакомиться с методологией озвучивания игр

15.1. Озвучивание игр

Создадим новый игровой проект P9_1. Реализуем в нём следующую функциональность. Мы собираемся использовать два звука в формате .WAV, и одну .MP3-композицию для фонового проигрывания. Для этого проекта мы использовали звуковые материалы, распространяемые бесплатно, с ресурсов http://www.freeloopsdownload.com, http://www.koumis.com.

Надо отметить, что инструменты XACT при разработке для Windows Phone не используются. Звуковые эффекты и фоновую музыку для игры можно добавить в состав ресурсов проекта, как и другие файлы ресурсов.

На рис. 15.1 вы можете видеть экран Обозреватель решений.

(рис 15.1) Обозреватель решений, проект P9_1

Мы собираемся реализовать в этом проекте следующую функциональность. Игра начинается, начинает играть фоновая музыка, повторяемая циклично. Для того, чтобы приостановить воспроизведение фоновой музыки, используется жест HorizontalDrag.

Приостановить воспроизведение можно только из состояния проигрывания. Для прекращения воспроизведения используется жест DoubleTap. Прекратить воспроизведение можно только из состояния проигрывания. Для продолжения воспроизведения – либо – из состояния полной остановки, либо – из состояния приостановки – применяется жест VerticalDrag. При остановке воспроизведения проигрывается звуковой сигнал, который звучит тише, чем основное звуковое сопровождение. Если воспроизведение музыки приостановлено, касание экрана вызывает воспроизведение другого звукового сигнала.

В листинге 15.1 приведен код проекта, реализующего эту функциональность.

using System;
using System.Collections.Generic;
using System.Linq;
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.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace P9_1
{
    /// <summary>
    /// Это главный тип игры
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        //Звуковые эффекты
        SoundEffect MySound1, MySound2;
        //Фоновая музыка
        Song gameMusic;
        //Разрешено ли воспроизведение звукового эффекта
        //при касании экрана
        bool fireIsAllowed = false;
        //Сообщение
        string message;
        //Шрифт
        SpriteFont MyFont;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            //Разрешим использовать жесты
            TouchPanel.EnabledGestures = GestureType.HorizontalDrag | GestureType.VerticalDrag|GestureType.DoubleTap;
            // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
            TargetElapsedTime = TimeSpan.FromTicks(333333);
            // Дополнительный заряд аккумулятора заблокирован.
            InactiveSleepTime = TimeSpan.FromSeconds(1);
        }

        /// <summary>
        /// Позволяет игре выполнить инициализацию, необходимую перед запуском.
        /// Здесь можно запросить нужные службы и загрузить неграфический
        /// контент.  Вызов base.Initialize приведет к перебору всех компонентов и
        /// их инициализации.
        /// </summary>
        protected override void Initialize()
        {
            //Включим повторение проигрываемой композиции
            MediaPlayer.IsRepeating = true;
            //Загрузим музыкальную композици.
            gameMusic= Content.Load<Song>("Music");
            //Запустим проигрывание
            MediaPlayer.Play(gameMusic);
            //Загрузим звуковые эффекты
            MySound1 = Content.Load<SoundEffect>("SoundFx1");
            MySound2 = Content.Load<SoundEffect>("SoundFx2");

            base.Initialize();
        }

        /// <summary>
        /// LoadContent будет вызываться в игре один раз; здесь загружается
        /// весь контент.
        /// </summary>
        protected override void LoadContent()
        {
            // Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //Шрифт
            MyFont = Content.Load<SpriteFont>("MyFont");
        }

        /// <summary>
        /// UnloadContent будет вызываться в игре один раз; здесь выгружается
        /// весь контент.
        /// </summary>
        protected override void UnloadContent()
        {
            // ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager
        }

        /// <summary>
        /// Позволяет игре запускать логику обновления мира,
        /// проверки столкновений, получения ввода и воспроизведения звуков.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        protected override void Update(GameTime gameTime)
        {
            // Позволяет выйти из игры
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            //Если разрешено воспроизведение звука при касании
            if (fireIsAllowed)
            {
                TouchCollection touchLocations = TouchPanel.GetState();


                foreach (TouchLocation touchLocation in touchLocations)
                {
                    //Если было касание
                    if (touchLocation.State == TouchLocationState.Pressed)
                    {
                        //Воспроизведем звук 2
                        MySound2.Play();
                    }
                }

            }
            //До тех пор, пока жесты разрешены
            while (TouchPanel.IsGestureAvailable)
            {
                //прочитаем жест
                GestureSample gs = TouchPanel.ReadGesture();
                 //Если обнаружен жест вертикального перетаскивания
               if (gs.GestureType == GestureType.VerticalDrag)
                {
                   //Если в настоящий момент плеер ничего не проигрывает
                    if (MediaPlayer.State != MediaState.Playing)
                    {
                        //Если проигрывание "на паузе"
                        if (MediaPlayer.State == MediaState.Paused)
                        {
                            //Возобновим проигрывание
                            MediaPlayer.Resume();
                        }
                        //Если проигрывание остановлено
                        if (MediaPlayer.State == MediaState.Stopped)
                        {
                            //Начнём проигрывание с начала композиции
                            MediaPlayer.Play(gameMusic);
                        }
                    }
                   //Запретим воспроизводить звук 2 при касании экрана
                    fireIsAllowed = false;
                }
                //Если обнаружен жест горизонтального перетаскивания
                if (gs.GestureType == GestureType.HorizontalDrag)
                {
                    //Если медиаплеер что-то проигрывает
                    if (MediaPlayer.State == MediaState.Playing)
                    {
                        //Приостановим проигрывание (поставим "на паузу")
                        MediaPlayer.Pause();
                        //Разрешим воспроизведение звука 2
                        fireIsAllowed = true;
                    }
                }
                //Если обнаружен жест двойного касания
                if (gs.GestureType == GestureType.DoubleTap)
                {
                    //Если медиаплеер что-то проигрывает
                    if (MediaPlayer.State == MediaState.Playing)
                    {
                        //Остановим воспроизведение
                        MediaPlayer.Stop();
                        //Воспроизведенм звук 1 с громкостью, равной 30% от
                        //текущей громкости
                        MySound1.Play(0.3f, 0f, 0f);
                    }
                }
            }
            message = MediaPlayer.State.ToString();
            base.Update(gameTime);
        }

        /// <summary>
        /// Вызывается, когда игра отрисовывается.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // ЗАДАЧА: добавьте здесь код отрисовки
            spriteBatch.Begin();
            spriteBatch.DrawString(MyFont, message, new Vector2(0, 0), Color.Red);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

Рассмотрим код. Для работы с WAV-звуками мы применяем объекты типа SoundEffect. Обратите внимание на то, что по умолчанию WAV-файлы считаются звуковыми эффектами, при их добавлении в проект, рис. 15.2, их свойство Обработчик контента устанавливается в значение Звуковой эффект – XNA Framework.

(рис 15.2) Свойства для WAV-файла, добавленного в проект

Добавляя в проект MP3-файл, мы видим следующие свойства, рис. 15.3. Эти файлы считаются, по умолчанию, композициями, мы работаем с ними, используя объекты типа Song.

(рис 15.3) Свойства для MP3-файла, добавленного в проект

В процедуре Initialize мы загружаем необходимые ресурсы. Для воспроизведения композиций мы пользуемся статическим классом MediaPlayer. Это очень мощный инструмент, помимо воспроизведения отдельных композиций он может работать с плейлистами, обладает многими другими возможностями. В частности, мы устанавливаем его свойство IsRepeating в значение True – это обеспечит циклическое воспроизведение композиции, и, после загрузки ресурса gameMusic, передаем этот ресурс для воспроизведения.

В процедуре Update мы наблюдаем за действиями пользователя, и, ориентируясь на них, управляем воспроизведением.

Так, если пользователь выполняет жест двойного касания экрана, мы останавливаем воспроизведение (но только в том случае, если оно производится в данный момент, то есть, свойство State объекта MediaPlayer равно MediaState.Playing). При этом мы воспроизводим звуковой эффект 1, уменьшив до 30% его громкость по отношению к общей громкости.

При обнаружении жеста горизонтального перетаскивания мы приостанавливаем воспроизведение (ставим "на паузу"), делая это только в том случае, если воспроизведение производится в данный момент, и, кроме того, разрешаем воспроизведение звука при простом касании экрана. Если зафиксирован жест вертикального перетаскивания, мы, в том случае, если до этого воспроизведение было приостановлено, начинаем его с момента, когда была осуществлена приостановка, если же воспроизведение было остановлено – начинаем проигрывание композиции сначала.

В конце процедуры Update мы записываем в переменную message состояние объекта MediaPlayer для вывода этого состояния на экран, которое осуществляем в методе Update. На рис. 15.4 вы можете видеть игровой экран приложения в эмуляторе.

(рис 15.4) Экран программы

15.2. Выводы

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

15.3. Задание

Выясните с помощью библиотеки MSDN, можно ли использовать для озвучивания игр звуковые файлы форматов, отличных от WAV и MP3. Если можно – узнайте – как это сделать.

15.4. Дополнительные материалы

К данной лабораторной работе прилагается видеоурок

и демонстрационный проект.

Страницы:

Цель работы: Ознакомиться с методологией озвучивания игр

15.1. Озвучивание игр

Создадим новый игровой проект P9_1. Реализуем в нём следующую функциональность. Мы собираемся использовать два звука в формате .WAV, и одну .MP3-композицию для фонового проигрывания. Для этого проекта мы использовали звуковые материалы, распространяемые бесплатно, с ресурсов http://www.freeloopsdownload.com, http://www.koumis.com.

Надо отметить, что инструменты XACT при разработке для Windows Phone не используются. Звуковые эффекты и фоновую музыку для игры можно добавить в состав ресурсов проекта, как и другие файлы ресурсов.

На рис. 15.1 вы можете видеть экран Обозреватель решений.

(рис 15.1) Обозреватель решений, проект P9_1

Мы собираемся реализовать в этом проекте следующую функциональность. Игра начинается, начинает играть фоновая музыка, повторяемая циклично. Для того, чтобы приостановить воспроизведение фоновой музыки, используется жест HorizontalDrag.

Приостановить воспроизведение можно только из состояния проигрывания. Для прекращения воспроизведения используется жест DoubleTap. Прекратить воспроизведение можно только из состояния проигрывания. Для продолжения воспроизведения – либо – из состояния полной остановки, либо – из состояния приостановки – применяется жест VerticalDrag. При остановке воспроизведения проигрывается звуковой сигнал, который звучит тише, чем основное звуковое сопровождение. Если воспроизведение музыки приостановлено, касание экрана вызывает воспроизведение другого звукового сигнала.

В листинге 15.1 приведен код проекта, реализующего эту функциональность.

using System;
using System.Collections.Generic;
using System.Linq;
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.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace P9_1
{
    /// <summary>
    /// Это главный тип игры
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        //Звуковые эффекты
        SoundEffect MySound1, MySound2;
        //Фоновая музыка
        Song gameMusic;
        //Разрешено ли воспроизведение звукового эффекта
        //при касании экрана
        bool fireIsAllowed = false;
        //Сообщение
        string message;
        //Шрифт
        SpriteFont MyFont;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            //Разрешим использовать жесты
            TouchPanel.EnabledGestures = GestureType.HorizontalDrag | GestureType.VerticalDrag|GestureType.DoubleTap;
            // Частота кадра на Windows Phone по умолчанию — 30 кадров в секунду.
            TargetElapsedTime = TimeSpan.FromTicks(333333);
            // Дополнительный заряд аккумулятора заблокирован.
            InactiveSleepTime = TimeSpan.FromSeconds(1);
        }

        /// <summary>
        /// Позволяет игре выполнить инициализацию, необходимую перед запуском.
        /// Здесь можно запросить нужные службы и загрузить неграфический
        /// контент.  Вызов base.Initialize приведет к перебору всех компонентов и
        /// их инициализации.
        /// </summary>
        protected override void Initialize()
        {
            //Включим повторение проигрываемой композиции
            MediaPlayer.IsRepeating = true;
            //Загрузим музыкальную композици.
            gameMusic= Content.Load<Song>("Music");
            //Запустим проигрывание
            MediaPlayer.Play(gameMusic);
            //Загрузим звуковые эффекты
            MySound1 = Content.Load<SoundEffect>("SoundFx1");
            MySound2 = Content.Load<SoundEffect>("SoundFx2");

            base.Initialize();
        }

        /// <summary>
        /// LoadContent будет вызываться в игре один раз; здесь загружается
        /// весь контент.
        /// </summary>
        protected override void LoadContent()
        {
            // Создайте новый SpriteBatch, который можно использовать для отрисовки текстур.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            //Шрифт
            MyFont = Content.Load<SpriteFont>("MyFont");
        }

        /// <summary>
        /// UnloadContent будет вызываться в игре один раз; здесь выгружается
        /// весь контент.
        /// </summary>
        protected override void UnloadContent()
        {
            // ЗАДАЧА: выгрузите здесь весь контент, не относящийся к ContentManager
        }

        /// <summary>
        /// Позволяет игре запускать логику обновления мира,
        /// проверки столкновений, получения ввода и воспроизведения звуков.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        protected override void Update(GameTime gameTime)
        {
            // Позволяет выйти из игры
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            //Если разрешено воспроизведение звука при касании
            if (fireIsAllowed)
            {
                TouchCollection touchLocations = TouchPanel.GetState();


                foreach (TouchLocation touchLocation in touchLocations)
                {
                    //Если было касание
                    if (touchLocation.State == TouchLocationState.Pressed)
                    {
                        //Воспроизведем звук 2
                        MySound2.Play();
                    }
                }

            }
            //До тех пор, пока жесты разрешены
            while (TouchPanel.IsGestureAvailable)
            {
                //прочитаем жест
                GestureSample gs = TouchPanel.ReadGesture();
                 //Если обнаружен жест вертикального перетаскивания
               if (gs.GestureType == GestureType.VerticalDrag)
                {
                   //Если в настоящий момент плеер ничего не проигрывает
                    if (MediaPlayer.State != MediaState.Playing)
                    {
                        //Если проигрывание "на паузе"
                        if (MediaPlayer.State == MediaState.Paused)
                        {
                            //Возобновим проигрывание
                            MediaPlayer.Resume();
                        }
                        //Если проигрывание остановлено
                        if (MediaPlayer.State == MediaState.Stopped)
                        {
                            //Начнём проигрывание с начала композиции
                            MediaPlayer.Play(gameMusic);
                        }
                    }
                   //Запретим воспроизводить звук 2 при касании экрана
                    fireIsAllowed = false;
                }
                //Если обнаружен жест горизонтального перетаскивания
                if (gs.GestureType == GestureType.HorizontalDrag)
                {
                    //Если медиаплеер что-то проигрывает
                    if (MediaPlayer.State == MediaState.Playing)
                    {
                        //Приостановим проигрывание (поставим "на паузу")
                        MediaPlayer.Pause();
                        //Разрешим воспроизведение звука 2
                        fireIsAllowed = true;
                    }
                }
                //Если обнаружен жест двойного касания
                if (gs.GestureType == GestureType.DoubleTap)
                {
                    //Если медиаплеер что-то проигрывает
                    if (MediaPlayer.State == MediaState.Playing)
                    {
                        //Остановим воспроизведение
                        MediaPlayer.Stop();
                        //Воспроизведенм звук 1 с громкостью, равной 30% от
                        //текущей громкости
                        MySound1.Play(0.3f, 0f, 0f);
                    }
                }
            }
            message = MediaPlayer.State.ToString();
            base.Update(gameTime);
        }

        /// <summary>
        /// Вызывается, когда игра отрисовывается.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // ЗАДАЧА: добавьте здесь код отрисовки
            spriteBatch.Begin();
            spriteBatch.DrawString(MyFont, message, new Vector2(0, 0), Color.Red);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

Рассмотрим код. Для работы с WAV-звуками мы применяем объекты типа SoundEffect. Обратите внимание на то, что по умолчанию WAV-файлы считаются звуковыми эффектами, при их добавлении в проект, рис. 15.2, их свойство Обработчик контента устанавливается в значение Звуковой эффект – XNA Framework.

(рис 15.2) Свойства для WAV-файла, добавленного в проект

Добавляя в проект MP3-файл, мы видим следующие свойства, рис. 15.3. Эти файлы считаются, по умолчанию, композициями, мы работаем с ними, используя объекты типа Song.

(рис 15.3) Свойства для MP3-файла, добавленного в проект

В процедуре Initialize мы загружаем необходимые ресурсы. Для воспроизведения композиций мы пользуемся статическим классом MediaPlayer. Это очень мощный инструмент, помимо воспроизведения отдельных композиций он может работать с плейлистами, обладает многими другими возможностями. В частности, мы устанавливаем его свойство IsRepeating в значение True – это обеспечит циклическое воспроизведение композиции, и, после загрузки ресурса gameMusic, передаем этот ресурс для воспроизведения.

В процедуре Update мы наблюдаем за действиями пользователя, и, ориентируясь на них, управляем воспроизведением.

Так, если пользователь выполняет жест двойного касания экрана, мы останавливаем воспроизведение (но только в том случае, если оно производится в данный момент, то есть, свойство State объекта MediaPlayer равно MediaState.Playing). При этом мы воспроизводим звуковой эффект 1, уменьшив до 30% его громкость по отношению к общей громкости.

При обнаружении жеста горизонтального перетаскивания мы приостанавливаем воспроизведение (ставим "на паузу"), делая это только в том случае, если воспроизведение производится в данный момент, и, кроме того, разрешаем воспроизведение звука при простом касании экрана. Если зафиксирован жест вертикального перетаскивания, мы, в том случае, если до этого воспроизведение было приостановлено, начинаем его с момента, когда была осуществлена приостановка, если же воспроизведение было остановлено – начинаем проигрывание композиции сначала.

В конце процедуры Update мы записываем в переменную message состояние объекта MediaPlayer для вывода этого состояния на экран, которое осуществляем в методе Update. На рис. 15.4 вы можете видеть игровой экран приложения в эмуляторе.

(рис 15.4) Экран программы

15.2. Выводы

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

15.3. Задание

Выясните с помощью библиотеки MSDN, можно ли использовать для озвучивания игр звуковые файлы форматов, отличных от WAV и MP3. Если можно – узнайте – как это сделать.

15.4. Дополнительные материалы

К данной лабораторной работе прилагается видеоурок

и демонстрационный проект.

Вернуться к учебному плану