Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming / GameProg / RPG_Programming_2ed.pdf
Скачиваний:
240
Добавлен:
12.02.2016
Размер:
12.06 Mб
Скачать

Джим Адамс

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

Срабатывание триггеров

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

ПРИМЕЧАНИЕ Вы увидите, как выполняется каждая проверка

столкновений в последующем разделе «Создание класса триггера».

Что делать, когда вы обнаружите, что триггер сработал? Поскольку каждому триггеру назначен идентификационный номер, вы можете использовать этот номер, чтобы определить, какое действие выполнять. Вы можете исполнить соответствующий скрипт или выполнить другую жестко закодированную функцию. Фактически, в последующем разделе «Использование триггеров» вы увидите, как с пользой применять триггеры.

Создание класса триггера

Придерживаясь техники объектно-ориентированного программирования, создадим класс, который будет поддерживать список триггеров и определять какого из них (если такой есть) коснулся персонаж. Класс использует структуру для хранения информации о каждом триггере — координаты, тип и т.д. Каждому триггеру также назначен идентификационный номер,

netlib.narod.ru

615

Глава 13. Работа с картами и уровнями

который используется для ссылки на него. Весь набор триггеров хранится как связанный список структур.

Класс cTrigger может загружать и сохранять файл триггеров, что

упрощает редактирование списка триггеров. Этот файл является текстовым и его просто читать и редактировать. Для каждого триггера на карте используется отдельная строка текста, записанная в следующем порядке: идентификационный номер, тип триггера (0 — сферический, 1 — кубический, 2 — цилиндрический, 3 — треугольный) и состояние триггера по умолчанию (будет ли триггер взведен после загрузки). Значение 0 означает, что триггер отключен, а значение 1 означает, что триггер включен.

В описание триггера входит еще несколько значений, зависящих от типа описываемого триггера. Сфере требуются координаты X, Y и Z и радиус, как показано ниже:

ID 0 ENABLED X Y Z RADIUS

Для параллелепипеда необходимы координаты противоположных углов:

ID 1 ENABLED X1 Y1 Z1 X2 Y2 Z2

Цилиндр вы определяете, задавая координаты центра нижней грани, плюс радиус и высоту:

ID 2 ENABLED X Y Z RADIUS HEIGHT

И, наконец, треугольник вы определяете по координатам X и Z трех углов, упорядочивая их по часовой стрелке, когда на треугольник смотрят по оси Y (точно так же, как треугольные грани определялись в главе 2, «Рисование с DirectX Graphics»). Завершают определение триггера общая координата Y всех трех точек и его высота:

ID 3 ENABLED X1 Z1 X2 Z2 X3 Z3 Y HEIGHT

Через минуту я вернусь к файлу данных триггеров. А сейчас взгляните на определение класса триггера. Класс (его заголовок объявлен в файле Trigger.h, а полный исходный код класса находится в файле Trigger.cpp) начинается с перечисления, в котором определены типы форм триггеров, которые вы можете использовать:

// Перечисление типов триггеров

enum TriggerTypes { Trigger_Sphere = 0, Trigger_Box, Trigger_Cylinder, Trigger_Triangle };

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

616

netlib.narod.ru

Джим Адамс

typedef struct sTrigger {

Сфера, куб и т.д.

long Type;

//

long ID;

//

ID триггера

BOOL Enabled;

//

Флаг активности

float x1, y1, z1; //

Координаты 1

float x2, y2, z2; //

Координаты 2

float x3, z3;

//

Координаты 3

float Radius;

//

Радиус границ

sTrigger *Prev, *Next; // Связанный список триггеров

sTrigger() { Prev = Next = NULL; } ~sTrigger() { delete Next; Next = NULL }

} sTrigger;

Заметьте, что структура sTrigger содержит набор указателей

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

Для работы со структурой sTrigger вы используете класс триггера,

который управляет связанным списком триггеров и позволяет вам сохранять и загружать список этих триггеров. Взгляните на объявление класса триггера:

class cTrigger

{

private:

long m_NumTriggers; // Кол-во триггеров в связанном списке sTrigger *m_TriggerParent; // Родитель связанного списка

long GetNextLong(FILE *fp);

//

Получаем

следующее

long

float GetNextFloat(FILE *fp); //

Получаем

следующее

float

// Функция, добавляющая триггер к связанному списку sTrigger *AddTrigger(long Type, long ID, BOOL Enabled);

public:

cTrigger();

~cTrigger();

// Функции для загрузки/сохранения списка триггеров

BOOL Load(char *Filename);

BOOL Save(char *Filename);

// Функции для добавления определенного триггера к списку

BOOL AddSphere(long ID, BOOL Enabled,

float XPos, float YPos, float ZPos, float Radius);

BOOL AddBox(long ID, BOOL Enabled,

float XMin, float YMin, float ZMin, float XMax, float YMax, float ZMax);

BOOL AddCylinder(long ID, BOOL Enabled,

float XPos, float YPos, float ZPos, float Radius, float Height);

netlib.narod.ru

617

Глава 13. Работа с картами и уровнями

BOOL AddTriangle(long ID, BOOL Enabled, float x1, float z1, float x2, float z2, float x3, float z3,

float YPos, float Height);

//Удаление триггера с указанным ID

BOOL Remove(long ID);

//Освобождение всех триггеров

BOOL Free();

//Поиск первого триггера в заданном месте

//(возвращает 0 если нет)

long GetTrigger(float XPos, float YPos, float ZPos);

//Получение состояния триггера с указанным ID

BOOL GetEnableState(long ID);

//Включение/отключение триггера с указанным ID

BOOL Enable(long ID, BOOL Enable);

//Возвращает количество триггеров

//и родителя связанного списка

long GetNumTriggers(); sTrigger *GetParentTrigger();

};

Большинство функций имеют дело только со связанным списком структур sTrigger — добавляют структуру, удаляют структуру, ищут

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

cTrigger::cTrigger и cTrigger::~cTrigger

Как и каждый класс С++, cTrigger имеет конструктор и деструктор, которые инициализируют и освобождают содержащиеся внутри класса данные. Единственными данными, которые отслеживаются классом триггера и не содержатся в связанном списке, являются текущее количество триггеров в связанном списке и указатель на этот связанный список. Конструктор и деструктор гарантируют, что класс подготовит для использования эти две переменные и данные класса будут освобождены при удалении объекта (вызовом функции Free), что показано ниже:

cTrigger::cTrigger() { m_NumTriggers = 0; m_TriggerParent = NULL;

}

cTrigger::~cTrigger()

{

Free();

}

618

netlib.narod.ru

Соседние файлы в папке GameProg