Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 1: Программирование на Visual C# искусственного интеллекта

Валерий Алексеевич Жарков

В серии книг «Справочник Жаркова по проектированию и программированию искусственного интеллекта» собрано лучшее программирование искусственного интеллекта (ИИ) в двух- и трёхмерных играх и приложениях, разработанных как автором, так и накопленных за многие годы в Интернете, для настольных компьютеров, ноутбуков, планшетов, смартфонов и Xbox. Даны инструкции по программированию ИИ с текстами программ, а также адреса в Интернете, где можно загрузить программы, графические и звуковые файлы.

Оглавление

* * *

Приведённый ознакомительный фрагмент книги Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 1: Программирование на Visual C# искусственного интеллекта предоставлен нашим книжным партнёром — компанией ЛитРес.

Купить и скачать полную версию книги в форматах FB2, ePub, MOBI, TXT, HTML, RTF и других

Часть II. Учебная методология программирования игр и приложений с подвижными объектами

Глава 4. Методика анимации и управления подвижными объектами

4.1. Методика добавления объекта в проект

Разработаем общую обучающую методику создания типичной и широко распространённой игры, когда в качестве летающих игровых объектов используются продукты питания, следуя статье с сайта microsoft.com: Rob Miles. Games Programming with Cheese: Part One. Так как эта статья написана по программированию игры на смартфоне и, к тому же, при помощи устаревшей версии Visual Studio, то автор данной книги переработал статью для программирования игры на настольном компьютере и, к тому же, при помощи новейшей версии Visual Studio.

Общие требования к программному обеспечению для разработки этой игры приведены выше. Методично и последовательно начнём решать типичные задачи (с подробными объяснениями) по созданию данной базовой учебной игры и всех подобных игр типа аркады (arcade).

Первым летающим объектом, используемом в игре, является, например, какой-либо продукт питания, например, маленький кусочек сыра (cheese). Так как на экране должно размещаться большое количество игровых объектов, то размер изображения сыра также должен быть небольшим, например, 25 x 32 пикселей. Если необходимо уменьшить объем файла любого изображения, то можно воспользоваться каким-либо графическим редактором, например, Paint, который поставляется с любой операционной системой Windows.

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

Создаём базовый учебный проект по обычной схеме: в VS в панели New Project в окне Project types выбираем тип проекта Visual C#, Windows, в окне Templates выделяем шаблон Templates, Visual C#, Windows Classic Desktop, Windows Forms App (.NET Framework), в окне Name записываем (или оставляем по умолчанию) имя проекта и щёлкаем OK. Важно отметить, что, так как, в отличие от приведённой выше статьи, имя этого проекта мы будем определять далее в коде программы, то в окне Name можно записать любое имя. Создаётся проект, появляется форма Form1 (рис. 4.1) в режиме проектирования. Проектируем (или оставляем по умолчанию) форму, как подробно описано в параграфе «Методика проектирования формы». Например, если мы желаем изменить фон формы с серого на белый, то в панели Properties (для Form1) в свойстве BackColor устанавливаем значение Window.

Добавляем в проект (из отмеченной выше статьи или из Интернета) файл изображения сыра cheese.jpg по стандартной схеме, а именно: в меню Project выбираем Add Existing Item, в этой панели в окне «Files of type» выбираем «All Files», в центральном окне находим и выделяем имя файла и щёлкаем кнопку Add (или дважды щёлкаем по имени файла).

В панели Solution Explorer мы увидим этот файл (рис. 4.2).

Теперь этот же файл cheese.jpg встраиваем в проект в виде ресурса по разработанной выше схеме, а именно: в панели Solution Explorer выделяем появившееся там имя файла, а в панели Properties (для данного файла) в свойстве Build Action (Действие при построении) вместо заданного по умолчанию значения Content (Содержание) или None выбираем значение Embedded Resource (Встроенный ресурс).

Для написания программы, в самом верху файла Form1.cs записываем пространство имён System.Reflection для управления классом Assembly:

using System.Reflection; //For the Assembly class.

В панели Properties (для Form1) на вкладке Events дважды щёлкаем по имени события Paint. Появившийся шаблон метода Form1_Paint после записи нашего кода принимает следующий вид.

Другие варианты вывода изображения, например, на элемент управления PictureBox и после щелчка по какому-либо элементу управления уже приводились ранее.

Рис. 4.1. Форма. Рис. 4.2. Файл рисунка в SE (слева) и в Properties (справа).

Листинг 4.1. Метод для построения изображения.

//We declare the object of class System.Drawing.Image

//for a product:

Image cheeseImage;

//We load into the project the image files according

//to such scheme:

//We create an object myAssembly of the Assembly class

//and appropriate to it

//the link to the executed assembly of our application:

static Assembly myAssembly = Assembly.GetExecutingAssembly ();

//We create the myAssemblyName object of

//the System.Reflection.AssemblyName class and appropriate to

//it the assembly name, which consists of a project name,

//Version, Culture, PublicKeyToken:

static AssemblyName myAssemblyName = myAssembly.GetName ();

//From the assembly name by means of the Name property

//we select a string project name:

static string myName_of_project = myAssemblyName.Name;

private void Form1_Paint (object sender, PaintEventArgs e)

{

//We load into object of the System.Drawing.Image class

//the image file of the set format, added to the project,

//by means of ResourceStream:

cheeseImage =

new Bitmap(myAssembly.GetManifestResourceStream (

myName_of_project +».» +"cheese.JPG»));

//We draw the image on the Form1:

e.Graphics. DrawImage (cheeseImage, 10, 20);

}

Строим и запускаем программу на выполнение обычным образом:

Build, Build Selection; Debug, Start Without Debugging.

Появляется форма Form1 с изображением типа встроенного нами рисунка сыра cheese.jpg (рис. 4.1).

Верхний левый угол изображения по отношению к верхнему левому углу экрана (где находится начало координат) расположен в соответствии с заданными нами координатами в строке кода (e.Graphics. DrawImage (myBitmap, 10, 20);).

4.2. Методика анимации объекта

Программа может рисовать теперь сыр на экране. Затем она должна перемещать сыр, неоднократно рисуя и перерисовывая изображение сыра в различных позициях. Если программа делает это достаточно быстро, создаётся иллюзия движения (анимация).

Следующий пример кода создаёт метод updatePositions, который перемещает сыр. На данной стадии проектирования сыр будет только двигаться вправо и вниз (по осям координат «x» и «y»). Таким образом, добавляем в данный (или новый) проект такой код.

Листинг 4.2. Изменение координат продукта.

//Current abscissa of an object:

int cx = 50;

//Current ordinate of an object:

int cy = 100;

private void updatePositions ()

{

cx++; //or cx = cx +1;

cy++; //or cy = cy +1;

}

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

В процессе игры, для вызова метода updatePositions через одинаковые промежутки времени, целесообразно использовать таймер. С панели инструментов Toolbox размещаем на форме компонент Timer (Таймер). В панели Properties (для данного компонента Timer) в свойстве Enabled оставляем булево значение False, а свойству Interval задаём значение 40 (миллисекунд, что соответствует 25 кадрам в секунду по стандарту телевещания России; 1000 миллисекунд равно 1 секунде).

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

Кроме того, таймер не должен быть включенным, пока программа не загрузит изображение. Поэтому в приведённый выше метод Form1_Paint дописываем в самом низу:

//We turn on the timer:

timer1.Enabled = true;

Окончательно, код в теле метода Form1_Paint должен иметь такой вид.

Листинг 4.3. Метод для рисования изображения.

private void Form1_Paint (object sender, PaintEventArgs e)

{

//We load into object of the System.Drawing.Image class

//the image file of the set format, added to the project,

//by means of ResourceStream:

cheeseImage =

new Bitmap(myAssembly.GetManifestResourceStream (

myName_of_project +».» +"cheese.JPG»));

//We draw the image on the Form1:

e.Graphics. DrawImage (cheeseImage, cx, cy);

//We turn on the timer:

timer1.Enabled = true;

}

Теперь всякий раз, когда вызывается метод Form1_Paint, программа рисует сыр на экране с соответствующими координатами cx и cy.

Дважды щёлкаем по значку для компонента Timer (ниже формы в режиме проектирования). Появляется шаблон метода timer1_Tick, который после записи нашего метода updatePositions и библиотечного метода Invalidate (или Refresh) для перерисовки изображения на экране принимает следующий вид.

Листинг 4.4. Метод для смены кадров на экране и перемещения фигуры.

private void timer1_Tick (object sender, EventArgs e)

{

//We call the method:

updatePositions ();

//We redraw the screen:

Invalidate ();

}

Строим и запускаем программу на выполнение обычным образом:

Build, Build Selection; Debug, Start Without Debugging.

В ответ Visual C# выводит форму Form1 в режиме выполнения, на которой изображение типа встроенного нами рисунка сыра cheese.jpg перемещается из верхнего левого угла по диагонали сверху вниз (в нижний правый угол) и скрывается (рис. 4.3).

Рис. 4.3. Объект перемещается по диагонали сверху вниз. Рис. 4.4. Отскок объекта.

Изображение объекта мерцает, что в дальнейшем будет исправлено применением двойной буферизации.

Таким образом, мы разработали методику анимации, по которой можно перемещать любые объекты на экране.

4.3. Методика проектирования отскока объекта от границы

Разработаем методику решения задачи по отскоку заданного нами объекта от заданных нами границ, например, от границ экрана. В качестве предмета и замкнутого пространства могут быть, например:

резиновый мяч, металлический или пластмассовый шар, который с большой силой бросил человек в каком-то помещении; предмет летает внутри помещения и отскакивает от пола, потолка и стен этого помещения;

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

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

Мы также введём большое число допущений, после чего задачу формулируем таким образом:

решаем плоскую задачу, т.е. предмет изображаем в виде его проекции на плоскость «x, y»; в качестве примера предмета выбираем кусочек сыра cheese.jpg, проекция которого на плоскость имеет вид прямоугольника;

на этой плоскости «x, y» замкнутое пространство изображаем в виде задаваемой нами замкнутой линии; в качестве примера замкнутой линии выбираем прямоугольник границы экрана;

предмет перемещается в этой плоскости «x, y» до столкновения с границей (линией), а после удара о границу должен отскочить от границы под определённым углом и перемещаться до следующего столкновения с границей, и так далее перемещаться и отражаться от линии;

принимаем обычное допущение, что до столкновения с границей предмет перемещается (летит) по прямой линии;

на основании допущения о том, что угол падения равен углу отражения, принимаем, что после столкновения с линией прямоугольника предмет отскакивает от этой линии под тем же углом; величину угла падения и угла отражения предмета от прямой линии принимаем равной 45 градусам;

перемещение предмета осуществляется поэтапно за интервал времени, который мы установим с помощью компонента Timer (Таймер);

интервал времени устанавливаем по значению свойства Interval компонента Timer; таким образом скорость перемещения объекта можно изменять за счёт изменения свойства Interval;

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

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

Таким образом, в данном проекте приведённый выше метод updatePositions заменяем на следующий.

Листинг 4.5. Отскок объекта от границ.

//Movement on an axis «x» to the right:

bool goingRight = true;

//Movement on an axis of «y» to the down:

bool goingDown = true;

private void updatePositions ()

{

if (goingRight)

{

cx++;

}

else

{

cx — ;

}

if ((cx + cheeseImage. Width)> = this.ClientSize. Width)

Конец ознакомительного фрагмента.

Оглавление

* * *

Приведённый ознакомительный фрагмент книги Справочник Жаркова по проектированию и программированию искусственного интеллекта. Том 1: Программирование на Visual C# искусственного интеллекта предоставлен нашим книжным партнёром — компанией ЛитРес.

Купить и скачать полную версию книги в форматах FB2, ePub, MOBI, TXT, HTML, RTF и других

Смотрите также

а б в г д е ё ж з и й к л м н о п р с т у ф х ц ч ш щ э ю я