Глава 49. Методика создания компьютерных игр и мультфильмов

Листинг 49.1.Объявление члена интерфейса и глобальных переменных.

//Объявляем персонаж Джина (Genie) и путь к его файлу:

static AgentObjects.IAgentCtlCharacterEx myGenie;

static String DATAPATH_1 = "Genie.acs";

//Объявляем член интерфейса Agent:

private AgentObjects.Agent myAgentController;

//Глобальная переменная для любого текста персонажа:

static String mySpeech;

//Объявляем общую для персонажей объектную переменную:

Object myObject = null;

Теперь необходимо написать нашу часть кода в шаблон главного метода Form1_Load, чтобы после загрузки Form1 на ней автоматически появился Джин, произносил тексты, перелетал на другое место за заданное нами время (например, з 15000 миллисекунд или 15 секунд) и выполнял анимации нашего мультфильма (пояснения даны в программе). Для этого дважды щелкаем по Form1 в режиме проектирования (или в панели Properties с заголовком Form1 на вкладке Events дважды щелкаем по имени события Load). Появляется файл Form1.cs с шаблоном (метода Form1_Load), который после записи нашего кода (согласно постановке задачи для персонажа Genie) принимает следующий вид.

Листинг 49.2.Загрузка персонажа, его речей и анимаций.

private void Form1_Load(object sender, EventArgs e)

{

//Загружаем персонаж в элемент управления axAgent1:

axAgent1.Characters.Load("Genie", DATAPATH_1);

myGenie = axAgent1.Characters.Character("Genie");

//Чтобы он выполнял голосовые команды на англ. яз.:

myGenie.LanguageID = 0x409;

//Чтобы персонаж произносил речь через динамики,

//задаем ему следующие свойства:

myAgentController = new AgentObjects.Agent();

myAgentController.Connected = true;

myAgentController.Characters.Load(

"genie", "genie.acs");

myGenie =

myAgentController.Characters.Character("genie");

//От начала координат в вехнем левом углу Form1

//задаем координаты "x, y" _

//места расположения персонажа:

myGenie.MoveTo(

Convert.ToInt16(this.Location.X + 250),

Convert.ToInt16(this.Location.Y + 100), 1000);

//Показываем персонаж:

myGenie.Show(0);

//Персонаж выполняет анимацию Announce:

myGenie.Play("Announce");

//Произносит записанную нами речь:

mySpeech =

"Здравствуйте, меня зовут Джин. " +

"Спасибо за Ваше внимание ко мне.";

myGenie.Speak(mySpeech, myObject);

//Выполняет анимацию GestureRight:

myGenie.Play("GestureRight");

//Произносит речь:

mySpeech = "Попросите меня сказать " +

"текст из этого окна...";

myGenie.Speak(mySpeech, myObject);

//Перемещается к переключателям с именами анимаций

//за заданное нами время, равное,

//например, 15000 мс (или 15 с.):

myGenie.MoveTo(

Convert.ToInt16(this.Location.X + 540),

Convert.ToInt16(this.Location.Y + 300), 15000);

//Выполняет анимацию GestureRight:

myGenie.Play("GestureRight");

//Произносит записанную нами речь:

mySpeech = "... или выберите, пожалуйста, " +

"вид моей анимации..";

myGenie.Speak(mySpeech, myObject);

}

Теперь, следуя алгоритму в первом параграфе, мы записываем такой код, чтобы:

если мы щелкнем кнопку на форме, но ничего не запишем в окно TextBox, то персонаж попросит нас записать текст в это окно;

когда мы запишем в окно TextBox текст на русском языке и щелкнем кнопку на форме, то персонаж произнесет по-русски записанный нами текст.

Дважды щелкаем эту кнопку в режиме редактирования (или в панели Properties с заголовком button1 на вкладке Events дважды щелкаем по имени события Click).

Появляется файл Form1.cs с шаблоном (метода button1_Click), который после записи нашего кода принимает следующий вид.

Листинг 49.3.Метод для кнопки.

private void button1_Click(object sender, EventArgs e)

{

//Персонаж произносит текст из окна TextBox

//при условии:

//Если окно TextBox не заполнено:

if (textBox1.TextLength == 0)

{

mySpeech =

"Запишите, пожалуйста, в окно слова, " +

"которые я должен произнести.";

myGenie.Speak(mySpeech, myObject);

}

else

//иначе, если окно TextBox заполнено,

//персонаж произносит слова из этого TextBox:

{

mySpeech = textBox1.Text;

myGenie.Speak(mySpeech, myObject);

}

}

Записываем код, чтобы после нашего щелчка мышью (или после нажатий двух клавиш, например, для первого переключателя: Alt+1) по первому переключателю с именем анимации Announce, персонаж:

произносил речь;

показывал выбранную нами анимацию.

Для этого дважды щелкаем первый переключатель в режиме редактирования (или в панели Properties с заголовком radioButton1 на вкладке Events дважды щелкаем по имени события CheckedChanged).

Появляется файл Form1.cs с шаблоном (метода radioButton1_CheckedChanged), который после записи нашего кода принимает такой вид.

Листинг 49.4.Метод для переключателя.

private void radioButton1_CheckedChanged(

object sender, EventArgs e)

{

//Останавливаем все предыдущие действия персонажа:

myGenie.StopAll(myObject);

//Перед анимацией персонаж произносит фразу:

mySpeech = "Охотно выполняю эту анимацию.";

myGenie.Speak(mySpeech, myObject);

//Показываем выбранную нами анимацию персонажа:

myGenie.Play("Announce");

//Показываем анимацию персонажа в покое:

myGenie.Play("RestPose");

}

Аналогично последовательно дважды щелкаем по каждому последующему переключателю в режиме редактирования и в каждый шаблон метода записываем такой же (как на предыдущем листинге) код, только строку с именем предыдущей анимации заменяем на соответствующую строку из следующих девяти строк (по числу оставшихся переключателей) с именами новой анимации:

myGenie.Play("Congratulate");

myGenie.Play("Congratulate_2");

myGenie.Play("DontRecognize");

myGenie.Play("Explain");

myGenie.Play("GetAttention");

myGenie.Play("Suggest");

myGenie.Play("Surprised");

myGenie.Play("Wave");

myGenie.Play("Write");

Аналогично можно записать код для решения любой подобной задачи согласно разработанному нами алгоритму.

Выполнение программы

Cтроим программу и запускаем на выполнение обычным образом: Build, Build Solution; Debug, Start Without Debugging. В ответ Visual C# запускает программу и на рабочий стол выводит форму Form1 в режиме выполнения.

После загрузки Form1 на ней начинается показ нашего маленького мультфильма в следующей последовательности эпизодов.

Автоматически появляется Джин, выполняет первую анимацию и произносит (через динамики компьютера) первый текст (при этом губы персонажа шевелятся в такт с текстом), согласно приведенному выше нашему коду:

//Персонаж выполняет анимацию Announce:

myGenie.Play("Announce");

//Произносит записанную нами речь:

mySpeech =

"Здравствуйте, меня зовут Джин. " +

"Спасибо за Ваше внимание ко мне.";

myGenie.Speak(mySpeech, myObject);

Одновременно над головой персонажа выводится динамическая подсказка, и внутри этой подсказки анимационно (в динамике) буква за буквой выводится текст, согласовано с движениями губ персонажа (рис. 49.2).

Глава 50. Пример Интернет-магазина на основе Microsoft Agent

На основе программ Visual C#, разработанных нами в предыдущих главах, теперь мы можем проектировать сложные интерактивные компьютерные игры, мультфильмы, Интернет-магазины и другие практические приложения.

Такое сложное приложение мы рассмотрим на примере реального интернет-магазина под названием “Peedy’s Pizza Palace”, в котором уже известный нам Попугай (Peedy) продает пиццу. Этот пример разработан самой корпорацией Microsoft на базе своей же мультимедийной программной технологии (платформы) Microsoft Agent версии 2.0.

Данный магазин создан по сценарию (постановке), который состоит из следующих основных эпизодов.

Эпизод 1. После загрузки браузера Internet Explorer в его окне автоматически появляются интерфейс магазина и его продавец в виде Попугая (Peedy).

Эпизод 2. Попугай объясняет нам, как пользоваться данным Интернет-магазином, и предлагает сделать выбор вида пиццы и дополнительной начинки.

Эпизод 3. При помощи элементов управления или голосовых команд мы выбираем какой-либо вид пиццы и дополнительной начинки и даем команду сделать нам расчет.

Эпизод 4. Попугай делает расчет, сообщает нам стоимость пиццы, перелетает на новое место и сообщает, что готов принять от нас новый заказ.

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

Итак, чтобы изучить пример интернет-магазина под названием “Peedy’s Pizza Palace”, в котором Попугай (Peedy) продает пиццу, выполняем следующее.

1. Если мы не загрузили (бесплатно) компоненты Microsoft Agent версии 2.0, то делаем это, как описано в первой главе данной части книги.

2. Подключаемся к Интернету (если мы не подключились) при помощи браузера Internet Explorer и открываем пример по адресу:

agent.microsoft.com/agent2/sdk/samples/html/peedypza.htm

Глава 51. Построение графика по точкам эксперимента и интеграция с мульти­пликационными персонажами MS Agent

Листинг 51.1.Объявление членов интерфейса и глобальных переменных.

//Объявляем персонаж Джина (Genie) и путь к его файлу:

static AgentObjects.IAgentCtlCharacterEx myGenie;

static String DATAPATH_1 = "Genie.acs";

//Объявляем персонаж Мага (Merlin) и путь к его файлу:

static AgentObjects.IAgentCtlCharacterEx myMerlin;

static String DATAPATH_2 = "Merlin.acs";

//Объявляем персонаж Попугая (Peedy) и путь к его файлу:

static AgentObjects.IAgentCtlCharacterEx myPeedy;

static String DATAPATH_3 = "Peedy.acs";

//Объявляем персонаж Робота (Robby) и путь к его файлу:

static AgentObjects.IAgentCtlCharacterEx myRobby;

static String DATAPATH_4 = "Robby.acs";

//Объявляем член интерфейса Agent:

private AgentObjects.Agent myAgentController;

//Глобальная переменная для любого текста персонажа:

static String mySpeech;

//Объявляем общую для персонажей объектную переменную:

Object myObject = null;

А в шаблон (метода Form1_Load) записываем наш код (согласно постановке задачи для всех персонажей), и метод Form1_Load принимает такой вид.

Листинг 51.2.Загрузка персонажей в элементы управления.

private void Form1_Load(object sender, EventArgs e)

{

//Загружаем персонаж в элемент управления axAgent1:

axAgent1.Characters.Load("Genie", DATAPATH_1);

myGenie = axAgent1.Characters.Character("Genie");

//Чтобы он выполнял голосовые команды на англ. яз.:

myGenie.LanguageID = 0x409;

//Загружаем персонаж в элемент управления axAgent2:

axAgent2.Characters.Load("Merlin", DATAPATH_2);

myMerlin = axAgent2.Characters.Character("Merlin");

//Чтобы он выполнял голосовые команды на англ. яз.:

myMerlin.LanguageID = 0x409;

//Загружаем персонаж в элемент управления axAgent3:

axAgent3.Characters.Load("Peedy", DATAPATH_3);

myPeedy = axAgent3.Characters.Character("Peedy");

//Чтобы он выполнял голосовые команды на англ. яз.:

myPeedy.LanguageID = 0x409;

//Загружаем персонаж в элемент управления axAgent4:

axAgent4.Characters.Load("Robby", DATAPATH_4);

myRobby = axAgent4.Characters.Character("Robby");

//От начала координат в вехнем левом углу Form1

//задаем координаты "x, y" персонажа:

myGenie.MoveTo(

Convert.ToInt16(this.Location.X + 0),

Convert.ToInt16(this.Location.Y - 130), 1000);

//Показываем персонаж в заданном месте:

myGenie.Show(0);

//Чтобы персонажи произносили речи через динамики,

//задаем им следующие свойства:

myAgentController = new AgentObjects.Agent();

myAgentController.Connected = true;

myAgentController.Characters.Load(

"genie", "genie.acs");

myGenie =

myAgentController.Characters.Character("genie");

myAgentController.Characters.Load(

"merlin", "merlin.acs");

myMerlin =

myAgentController.Characters.Character("merlin");

myAgentController.Characters.Load(

"peedy", "peedy.acs");

myPeedy =

myAgentController.Characters.Character("peedy");

myAgentController.Characters.Load(

"robby", "robby.acs");

myRobby =

myAgentController.Characters.Character("robby");

//Первый персонаж произносит текст mySpeech

//и показывает этот текст в виде подсказки:

mySpeech = "Сидите за монитором прямо, " +

"как пианист.";

myGenie.Speak(mySpeech, myObject);

}

Чтобы следующий персонаж, например, Маг (Merlin) появился через заданное нами время, щелкаем по значку для первого компонента Timer и в панели Properties для этого компонента в свойстве Interval записываем данное время, например, 5000 миллисекунд (или 5 секунд) и запускаем таймер (в свойстве Enabled выбираем True).

Теперь дважды щелкаем по значку для этого компонента Timer (или в панели Properties на вкладке Events дважды щелкаем по имени единственного там события Tick). Появляется файл Form1.cs с шаблоном (метода timer1_Tick), который после записи нашего кода принимает следующий вид.

Листинг 51.3.Метод для вызова персонажа через Interval времени.

private void timer1_Tick(object sender, EventArgs e)

{

//Показываем следующий персонаж рядом:

myMerlin.MoveTo(

Convert.ToInt16(this.Location.X + 200),

Convert.ToInt16(this.Location.Y - 130), 1000);

myMerlin.Show(0);

//Текущий персонаж произносит текст mySpeech

//и показывает этот текст в виде подсказки:

mySpeech = "Держите глаза от монитора " +

"на расстоянии вытянутой руки.";

myMerlin.Speak(mySpeech, myObject);

//Останавливаем генерирование события Tick:

timer1.Enabled = false;

}

Чтобы следующий персонаж, например, Попугай (Peedy) появился через заданное нами время, щелкаем по значку для второго компонента Timer и в панели Properties для этого компонента в свойстве Interval записываем данное время, например, 10000 миллисекунд (или 10 секунд) и запускаем таймер (в свойстве Enabled выбираем True). Теперь дважды щелкаем по значку для этого компонента Timer (или в панели Properties на вкладке Events дважды щелкаем по имени единственного там события Tick). Появляется файл Form1.cs с шаблоном (метода timer2_Tick), который после записи нашего кода принимает следующий вид.

Листинг 51.4.Метод для вызова персонажа через Interval времени.

private void timer2_Tick(object sender, EventArgs e)

{

//Показываем следующий персонаж рядом:

myPeedy.MoveTo(

Convert.ToInt16(this.Location.X + 400),

Convert.ToInt16(this.Location.Y - 130), 1000);

myPeedy.Show(0);

//Текущий персонаж произносит текст mySpeech

//и показывает этот текст в виде подсказки:

mySpeech = "Поднимите монитор, чтобы глаза были " +

"на уровне верхней кромки экрана.";

myPeedy.Speak(mySpeech, myObject);

//Останавливаем генерирование события Tick:

timer2.Enabled = false;

}

Чтобы следующий персонаж, например, Робот (Robby) появился через заданное нами время, щелкаем по значку для третьего компонента Timer и в панели Properties для этого компонента в свойстве Interval записываем данное время, например, 15000 миллисекунд (или 15 секунд) и запускаем таймер (в свойстве Enabled выбираем True). Теперь дважды щелкаем по значку для этого компонента Timer (или в панели Properties на вкладке Events дважды щелкаем по имени единственного там события Tick). Появляется файл Form1.cs с шаблоном (метода timer3_Tick), который после записи нашего кода принимает следующий вид.

Листинг 51.5.Метод для вызова персонажа через Interval времени.

private void timer3_Tick(object sender, EventArgs e)

{

//Показываем следующий персонаж рядом:

myRobby.MoveTo(

Convert.ToInt16(this.Location.X + 600),

Convert.ToInt16(this.Location.Y - 130), 1000);

myRobby.Show(0);

//Текущий персонаж произносит текст mySpeech

//и показывает этот текст в виде подсказки:

mySpeech = "Работайте на клавиатуре всеми пальцами.";

myRobby.Speak(mySpeech, myObject);

//Останавливаем генерирование события Tick:

timer3.Enabled = false;

}

Мы записали код для вывода на экран всех четырех персонажей. Чтобы один из этих персонажей, например, Джин (Genie) периодически (с заданным нами интервалом времени в компоненте Timer) повторял инструкцию пользователю (например, о том, как строить график на данной форме), щелкаем по значку для четвертого компонента Timer и в панели Properties для этого компонента в свойстве Interval записываем данный интервал времени, например, 18000 миллисекунд (или 18 секунд) и запускаем таймер (в свойстве Enabled выбираем True). Теперь дважды щелкаем по значку для этого компонента Timer (или в панели Properties на вкладке Events дважды щелкаем по имени единственного там события Tick). Появляется файл Form1.cs с шаблоном (метода timer4_Tick), который после записи нашего кода принимает следующий вид.

Листинг 51.6.Метод для произнесения инструкции через Interval времени.

private void timer4_Tick(object sender, EventArgs e)

{

//Текущий персонаж произносит текст mySpeech

//и показывает этот текст в виде подсказки:

mySpeech = "Запишите координаты точек целыми числами, " +

"щелкните верхнюю кнопку, и Вы увидите график. " +

"Чтобы стереть график, щелкните нижнюю кнопку.";

myGenie.Speak(mySpeech, myObject);

}

Мы видим, что в последнем методе, в отличие от трех предыдущих методов, мы не останавливаем генерирование события Tick (тем самым, не выключаем таймер) и даем возможность персонажу говорить до тех пор, пока мы не щелкнем по нему правой кнопкой и не выберем команду Hide (Скрыть).

Чтобы при помощи кнопки “1. Построить график” появился график функциональной зависимости y = f(x), дважды щелкаем или эту кнопку в режиме проектирования (рис. 51.1), или имя события Click в панели Properties на вкладке Events. Появляется шаблон, который после записи нашего кода принимает такой вид.

Листинг 51.7. Метод для обработки щелчка кнопки с целью рисования графика.

private void button1_Click(object sender, EventArgs e)

{

//Объявляем локальные переменные:

float x1, y1, x2, y2, x3, y3, x4, y4;

float x_O, y_O, x_end, y_end;

//Координаты начальной точки O:

x_O = 20; y_O = 20;

//Считываем координаты точек из окон:

x1 = Convert.ToSingle(textBox1.Text) + x_O;

y1 = -Convert.ToSingle(textBox2.Text) +

pictureBox1.Height - y_O;

x2 = Convert.ToSingle(textBox3.Text) + x_O;

y2 = -Convert.ToSingle(textBox4.Text) +

pictureBox1.Height - y_O;

x3 = Convert.ToSingle(textBox5.Text) + x_O;

y3 = -Convert.ToSingle(textBox6.Text) +

pictureBox1.Height - y_O;

x4 = Convert.ToSingle(textBox7.Text) + x_O;

y4 = -Convert.ToSingle(textBox8.Text) +

pictureBox1.Height - y_O;

//Создаем графический объект g класса Graphics:

Graphics g;

//Связываем графический объект g класса Graphics

//с элементом управления pictureBox1:

g = pictureBox1.CreateGraphics();

//Создаем перо для осей координат:

Pen myPenAxes = new Pen(Color.Black, 1);

//Строим ось координат x:

x_end = pictureBox1.Width - y_O;

g.DrawLine(myPenAxes,

x_O, pictureBox1.Height - y_O,

x_end, pictureBox1.Height - y_O);

//Строим ось координат y:

y_end = y_O;

g.DrawLine(myPenAxes,

x_O, pictureBox1.Height - y_O,

x_O, y_O);

//Создаем перо для графика:

Pen myPen = new Pen(Color.Black, 3);

//Строим график:

g.DrawLine(myPen, x1, y1, x2, y2);

g.DrawLine(myPen, x2, y2, x3, y3);

g.DrawLine(myPen, x3, y3, x4, y4);

}

Чтобы при помощи кнопки “2. Удалить график” график функциональной зависимости y = f(x) был стерт, дважды щелкаем или эту кнопку в режиме проектирования (рис. 51.1), или имя события Click в панели Properties на вкладке Events. Появляется шаблон, который после записи нашего кода принимает такой вид.

Листинг 51.8. Метод для обработки щелчка по кнопке.

private void button2_Click(object sender, EventArgs e)

{

//Создаем графический объект g класса Graphics:

Graphics g;

//Связываем графический объект g класса Graphics

//с элементом управления pictureBox1:

g = pictureBox1.CreateGraphics();

//Очистить pictureBox1, заполнив белым цветом White:

g.Clear(Color.White);

}

Мы закончили часть книги, в которой разработали методологию написания программ на Visual С# с целью создания сложных интерактивных компьютерных игр, мультфильмов, Интернет-магазинов и других практических приложений на основе мультимедийной программной технологии (платформы) Microsoft Agent версии 2.0.

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

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


Наши рекомендации