Опубликован: 14.08.2012 | Уровень: специалист | Доступ: платный
Самостоятельная работа 12:

Искусственный интеллект в играх

Листинг 18.4. содержит код класса Me.

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 P12_1.GameObjects
{
    /// <summary>
    /// Это игровой компонент, реализующий интерфейс IUpdateable.
    /// </summary>
    public class Me : gBaseClass
    {

        public Me(Game game, ref Texture2D _sprTexture,
             Vector2 _sprPosition, Rectangle _sprRectangle, SpriteFont _myFont)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, _myFont)
        {
            sprSpeed = 2;
        }

        public void IsCollideWithAny()
        {
            //Заводим переменную для временного хранения
            //ссылки на объект, с которым столкнулся игровой объект
            gBaseClass FindObj = null;
            //Проверка на столкновение с объектами Enemy
            foreach (gBaseClass spr in Game.Components)
            {
                if (spr.GetType() == (typeof(Enemy)))
                {
                    if (IsCollideWithObject(spr))
                    {
                        FindObj = spr;
                    }
                }
            }

            if (FindObj != null)
            {

                this.Dispose();
            }
        }

        /// <summary>
        /// Позволяет игровому компоненту выполнить необходимую инициализацию перед\r\запуском.  
        Здесь можно запросить нужные службы и загрузить контент.
        /// 
        /// </summary>
        public override void Initialize()
        {
            // ЗАДАЧА: добавьте здесь код инициализации

            base.Initialize();
        }

        //Перемещение объекта
        void Move(int Direction)
        {

            //Вверх
            if (Direction == 1)
            {

                MoveUp(sprSpeed);
                //При прыжке проводится проверка на контакт со стеной
                //Которая может быть расположена над объектом
                //при необходимости его координаты корректируются
                while (IsCollideWithWall())
                {
                    MoveDown((sprSpeed / 10));
                }

            }
            //Вниз
            //Происходит обычная процедура перемещения
            //объекта с проверкой
            if (Direction == 2)
            {
                MoveDown(sprSpeed);
                while (IsCollideWithWall())
                {
                    MoveUp((sprSpeed / 10));
                }
            }
            //Точно так же обрабатывается
            //движение Влево
            if (Direction == 3)
            {


                MoveLeft(sprSpeed);
                while (IsCollideWithWall())
                {
                    MoveRight((sprSpeed / 10));
                }
            }
            //Аналогично - перемещение вправо
            if (Direction == 4)
            {

                MoveRight(sprSpeed);
                while (IsCollideWithWall())
                {
                    MoveLeft((sprSpeed / 10));
                }
            }

        }
        //Обработка сенсорного ввода
        void TouchInput()
        {
            //Реализуем управление объектом
            //Получаем коллекцию объектов, содержащих информацию о касаниях экрана
            TouchCollection touchLocations = TouchPanel.GetState();
            //Перебираем коллекцию, присваивая объекту координаты касания
            foreach (TouchLocation touchLocation in touchLocations)
            {
                if (touchLocation.State == TouchLocationState.Pressed || touchLocation.State == TouchLocationState.Moved)
                {
                    //Стрелка "Влево"
                    if (touchLocation.Position.X > 500 && touchLocation.Position.X < 600
                        && touchLocation.Position.Y > 380 && touchLocation.Position.Y < 480)
                    {
                        Move(3);
                    }
                    //Стрелка "Вправо"
                    if (touchLocation.Position.X > 700 && touchLocation.Position.X < 800
                        && touchLocation.Position.Y > 380 && touchLocation.Position.Y < 480)
                    {
                        Move(4);
                    }
                    //Стрелка "Вниз"
                    if (touchLocation.Position.X > 600 && touchLocation.Position.X < 700
                        && touchLocation.Position.Y > 380 && touchLocation.Position.Y < 480)
                    {
                        Move(2);
                    }
                    //Стрелка "Вверх"
                    if (touchLocation.Position.X > 600 && touchLocation.Position.X < 700
                        && touchLocation.Position.Y > 280 && touchLocation.Position.Y < 380)
                    {
                        Move(1);
                    }
                }

            }
        }

        /// <summary>
        /// Позволяет игровому компоненту обновиться.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        public override void Update(GameTime gameTime)
        {
            //Обработаем касания экрана для реализации перемещения объекта
            TouchInput();
            //Проверим, не вышел ли он за границы экрана, если надо
            //исправим его позицию
            Check();
            //Применим к объекту "силу тяжести"
            //Проверим на другие столкновения
            IsCollideWithAny();

            message = "Try to escape!";

            base.Update(gameTime);
        }


    }
}
Листинг 18.4. Код класса Me

Объект класса Me умеет перемещаться по командам, полученных от сенсорной панели, не выходя за границы игровой области экрана, останавливаться, "натыкаясь" на стену, а при столкновении с объектом-преследователем объект класса Me уничтожается. Алгоритм преследования реализован в коде класса Enemy (листинг 18.5).

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.Media;


namespace P12_1.GameObjects
{
    /// <summary>
    /// Это игровой компонент, реализующий интерфейс IUpdateable.
    /// </summary>
    public class Enemy : gBaseClass
    {
        Vector2 Direction;
        public Enemy(Game game, ref Texture2D _sprTexture,
            Vector2 _sprPosition, Rectangle _sprRectangle, SpriteFont _myFont)
            : base(game, ref _sprTexture, _sprPosition, _sprRectangle, _myFont)
        {
            sprSpeed = 1;
            Direction = new Vector2(0, 0);
        }

        /// <summary>
        /// Позволяет игровому компоненту выполнить необходимую инициализацию перед\r\запуском. 
         Здесь можно запросить нужные службы и загрузить контент.
        /// 
        /// </summary>
        public override void Initialize()
        {
            // ЗАДАЧА: добавьте здесь код инициализации

            base.Initialize();
        }
        //Вычисление направления на объект-игрока и передвижение в
        //этом направлении
        void SeekAndDestroy()
        {
            foreach (gBaseClass spr in Game.Components)
            {
                if (spr.GetType() == (typeof(Me)))
                {
                    //найдем разницу между координатами преследователя и
                    //игрока
                    Direction = (this.sprPosition - spr.sprPosition);
                    //Если разность по X положительная
                    //переместим преследователя влево
                    //с учетом того, что стены для него 
                    //непроницаемы.
                    if (Direction.X > 0)
                    {
                        MoveLeft(sprSpeed);
                        while (IsCollideWithWall())
                        {
                            MoveRight((sprSpeed / 10));
                        }
                    }
                    //При отрицательной разности по X
                    //переместим объект вправо
                    if (Direction.X < 0)
                    {
                        MoveRight(sprSpeed);
                        while (IsCollideWithWall())
                        {
                            MoveLeft((sprSpeed / 10));
                        }
                    }
                    //При положительной разности по Y
                    //переместим объект вверх
                    if (Direction.Y > 0)
                    {
                        MoveUp(sprSpeed);
                        while (IsCollideWithWall())
                        {
                            MoveDown((sprSpeed / 10));
                        }
                    }
                    //При отрицательной разности по Y переместим
                    //объект вниз
                    if (Direction.Y < 0)
                    {
                        MoveDown(sprSpeed);
                        while (IsCollideWithWall())
                        {
                            MoveUp((sprSpeed / 10));
                        }

                    }

                }
            }
        }

        /// <summary>
        /// Позволяет игровому компоненту обновиться.
        /// </summary>
        /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param>
        public override void Update(GameTime gameTime)
        {
            // Перемещение к объекту игрока
            SeekAndDestroy();
            //Проверка на столкновение с границами экрана
            Check();


            base.Update(gameTime);
        }
    }
}
Листинг 18.5. Код класса Enemy

На каждом шаге игрового цикла объект-преследователь сравнивает свои координаты и координаты объекта игрока и проводит необходимую коррекцию своей позиции.

Как мы уже отмечали, наш объект-преследователь не умеет обходить препятствия. Рассмотрим реализацию алгоритма преследования с обходом препятствий.

Гулич Анна
Гулич Анна
Невозможно пройти тесты, в окне с вопросами пусто
Сашечка Огнев
Сашечка Огнев
Россия, Красноярский край
Андрей Корягин
Андрей Корягин
Россия, Пенза, Вазерская средняя школа, 2001