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