Невозможно пройти тесты, в окне с вопросами пусто |
Опубликован: 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
На каждом шаге игрового цикла объект-преследователь сравнивает свои координаты и координаты объекта игрока и проводит необходимую коррекцию своей позиции.
Как мы уже отмечали, наш объект-преследователь не умеет обходить препятствия. Рассмотрим реализацию алгоритма преследования с обходом препятствий.