Обнаружение столкновений

В зависимости от типов сущностей которые сталкиваются друг с другом, используются два различных метода обнаружения столкновений (collision detection). Для этого каждая сущность имеет Bounding Box (габаритный куб) и имеющий форму коробки Корпус (Hull). Корпус используется для столкновений перемещающейся сущности с сущностями карты или уровня. Этот вид столкновений проверяет каждый полигон сущности-цели. Для всех других типов столкновений габаритные кубы (Bounding Boxes) двух сущностей проверяют друг друга. Как габаритный куб, так и корпус не будет вращаться вместе с сущностью, они всегда выровнены по осям xyz.

В то время как bounding box может иметь произвольный размер, есть только три возможных корпуса hull: широкий, узкий и точечный. Сущности с точечным bounding box могут проходить сквозь все невидимые блоки (но не блоки, которые являются видимыми, но имеют невидимые поверхности, установленные флагом None). Узкий корпус — куб размером граней 32 кванта вокруг центра сущности. Широкий корпус — куб размером 48 квантов по вертикали и 64 кванта по горизонтали, перемещенный вверх на 8 квантов. Эти размеры соответствуют большинству требований, но для некоторых специальных случаев они могут быть изменены. В отличие от bounding box, они не назначаются отдельно каждой сущности, а являются общими для всего уровня. Они могут быть изменены при компилировании уровня, вводом в строке опций при сборке WED:
-narrow hsize vsize voffset
-fat hsize vsize voffset
Первое число (hsize) — горизонтальный размер корпуса, следующее (vsize) — вертикальный размер, и третье (voffset) — вертикальное смещение корпуса относительно центра сущности. Например, -narrow 32 32 0 -fat 64 48 8 определяет корпус, заданный по умолчанию. Все сущности карты (используемые на уровне) должны быть построены с теми же самыми размерами корпуса как уровень. 4 предопределенных вектора содержат размеры корпуса текущего уровня для использования в функциях: hull_narrowmin [3], hull_narrowmax [3], hull_fatmin [3], и hull_fatmax [3]. Они содержат x, y, z минимальные и максимальные значения тонких и широких корпусов.
Для сущностей спрайта, его центром является геометрический центр bitmap’ы. Для сущностей карты или модели центром служат координаты, данные редактором. Если Вы хотите, чтобы модель могла подниматься по лестнице, просто разместите ее центр в более высоком месте ее тела. Самая высокая ступень, на которую модель может подниматься, определяется разницей между нижней границей его корпуса (hull) и его ногами. Если Вы не хотите, чтобы модель не поднималась вообще — напр. автомобиль, — разместите его центр в нижнем положении. Но будьте осторожны — не размещайте его слишком низко, иначе его корпус может проникать через пол, и модель вообще не сможет двигаться. Центр также является центром вращения при поворотах модели. Следующие параметры влияют индивидуально на поведение столкновения сущностей.

min_x, min_y, min_z, max_x, max_y, max_z
Углы bounding box сущности относительно центра сущностей, используются для обнаружения столкновения с сущностью спрайта или модели (для обнаружения столкновения с сущностями уровня или карты используются не границы, а корпус — hull). Границы первоначально установлены в некоторые значения по умолчанию, но могут быть изменены. Заметьте что когда они увеличиваются и рядом находится другая сущность, последняя может застрять. Кроме того, они возвращают свои значения по умолчанию каждый раз при изменении модели или масштаба сущности. Таким образом они могут быть изменены не ранее чем через один framecycle после создания модели. Они часто используются в функциях, определяющих вертикальный размер сущностей (max_z — min_z).
Обратите внимание, что по умолчанию bounding box сущности получается из, но не идентичен реальному размеру. Он рассчитывается с учетом поведения актера при столкновении. Ось привязанная к bounding box не вращается, поэтому он симметричен по X и Y. Min_z и max_z взяты из реального размера, в то время как горизонтальный диаметр немного «урезан» чтобы позволить актерам проходить в двери.

fat, narrow
Флаги, используемые для обнаружения столкновения с сущностями уровня или карты. Определяет какой корпус, если таковые вообще имеются, используется сущностью. Если сущность больше чем 64 кванта, ее флаг fat(широкий) автоматически установлен в on в начале игры. Иначе установлен его флаг narrow(узкий). Если сущность меньше 8 квантов, подобно пуле, ни один из флагов не установлен — тогда используется точечный корпус. Вы можете задавать или перезадавать fat и narrow вручную, чтобы менять корпус столкновений, используемый сущностью. В некоторых случаях Вы захотите чтобы сущность выбрала узкий корпус вместо широкого например для прохода через маленькие двери. Fat и narrow никогда не должны быть установлены одновременно. Они устанавливаются автоматически при изменении масштаба сущностей или при морфинге (morphed). Пример явного назначения игроку узкого корпуса чтобы он мог пройти через двери:
my.fat = off;
my.narrow = on;

passable
Если флаг passable сущности установлен в on, обнаружение столкновений для нее выключено. Она будет подобна призраку, проходящему сквозь стены, и другие сущности могут двигаться прямо через нее. События столкновения не вызываются.

push
Через значение push сущностей Вы можете более определенно чем с помощью флага passable определять будет ли сущность препятствием для других или нет. Сущность игрока, например, не должна быть препятствием для сущности лифта, иначе лифт с игроком внутри никогда бы не сдвинулся. Сущность с более высоким значением push (по умолчанию = 0) рассматривает сущность с более низким значением push НЕпрепятствием, и перемещается прямо через него. Обратите внимание, что сущности нельзя автоматически столкнуть с дороги. Толкание, если это необходимо, может быть выполнено событийными функцией (см. ниже). Значения push дверей и подъемников = 10 в функциях скрипта doors.wdl.

trigger_range
Данное значение в event_trigger сработает от проходящей мимо сущности, у которой trigger_range отличен от нуля. Значение по умолчание = 0.

Events (события)
Сущность может быть чувствительна к некоторым событиям игры, — столкновениям, стрельбе или клику мышью. Если это случается с сущностью, каждый раз вызывается ее событийная (event) функция.

event
Функция event может быть установлена главным действием (action) сущностей, например:
my.event = my_function;
Функция стартует как только случается некоторое событие, для которого соответствующий флаг enable = on. В начале событийной функции можно проверить предопределенную переменную event _type, чтобы определить, который вид события случился. Таким образом для каждого типа событий есть свой флаг enable, делающий сущность чувствительной для этого события, и некоторое значение переменной event _type. В зависимости от этого событийная функция может позволить сущности реагировать на событие, указывая путь, отстреливаясь, взрываясь и т.д.

Событийные функции фактически выполняются немедленно в течение инструкции другой сущности, которая вызвала событие, подобно инструкциям ent_move, scan или trace. Событийная функция обычно должна только передавать информацию главной функции сущности — она не должна выполнять инструкции, которые непосредственно могут вызывать события, перемещать сущности или изменять что-либо еще на уровне. Таким образом инструкции типа ent_move, ent_create, ent_remove, trace и т.д. здесь нужно избегать ! Иначе может случиться масса проблем,- например две сущности бесконечно вызывают события друг друга (игра зависнет в том случае). Если по некоторым причинам событийная функция должна выполнять такие ‘критические инструкции’, им должны предшествовать wait(1) для приостановки их до следующего фрейма, тогда это безопасно.

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

event_block — enable_block
Столкновение с поверхностью уровня в течение инструкции move. Сущность не должна быть passable и ее значение push должен быть 0 или меньше. При запуске событийной функции вектор normal установлен перпендикулярно к той поверхности, и вектор bounce установлен в направлении «отскока» сущности. Пример:
var angle[3];
function bounce_event()
{
if (event_type == event_block) {
play_entsound(my,whamm,50);
vec_to_angle(my.pan,bounce); // bounce off the surface
}
if (event_type == event_entity) {

}
// etc. …
}
action bounceball
{

my.enable_block = on; // make entity sensitive for block collisions
my.enable_entity = on; // make entity sensitive for entity collisions (see below)
my.event = bounce_event;

}

event_stuck — enable_stuck
Сущность зажата в углу в процессе функции move, неспособна двигаться дальше. Сущность не должна быть passable.

event_entity — enable_entity
Столкновение с другой сущностью в течение move. Сущность не должна быть passable, и ее значение push должно быть меньше или равно чем значение push другой сущности. Указатель you установлен на другую сущность, normal и bounce установлены как прежде.

event_impact — enable_impact
Сущность получила удар от другой сущности, которая выполняла move и имела более низкий или равный параметр push. Ни одна из сущностей не должна быть passable. You установлен на другую сущность. Векторы normal and bounce также установлены в направлении перпендикулярном перемещающейся поверхности и направлении «отскока» сущности.

event_push — enable_push
Сущность получила удар от другой сущности с более высоким параметром push. Ни одна из сущностей не должна быть passable. You установлен на толкающую сущность. Normal и bounce установлены как обычно. Event_impact в этом случае не вызывается. Событийная функция может теперь определять направление движения сущностей. Если толкаемая сущность теперь выполняет инструкцию move, это не вызовет столкновения с толкачом снова, потому что сущность you исключена из обнаружения столкновения инструкции move. Если две сущности сталкиваются, у каждой вызывается событийная функция: движущаяся сущность с event_entity, неподвижная сущность с event_impact или event_push. Если обе сущности перемещались, каждая может получить два различных события в неопределенном порядке.

event_click — enable_click
Был левый клик мыши на сущности.

event_rightclick — enable_rightclick
Был правый клик мыши на сущности.

event_touch — enable_touch
Касание мышью.

event_release — enable_release
Мышь была удалена от поверхности сущности. События мыши вызываются только если сущность в пределах расстояния, данного предопределенной переменной mouse_range (по умолчанию 1000 квантов) от положения камеры.

event_scan — enable_scan
Сущность просканирована инструкцией scan_entity. Если scan_entity выполнялось сущностью, на нее установливается указатель you. Result содержит расстояние до центра конуса сканирования.

event_detect — enable_detect
Выполнена инструкция scan_entity и обнаружена сущность с enable_scan=on в пределах конуса просмотра. You установлен на эту сущность, и result содержит расстояние до этой сущности. Для каждой найденной сущности вызывается отдельное событие.

event_trigger — enable_trigger
Другая сущность выполнила инструкцию move в пределах границы срабатывания. You установлен на перемещающуюся сущность. Событие случается, когда границы срабатывания обеих сущностей пересекаются. Границы срабатывания — куб с радиусом trigger_range вокруг центра перемещающейся сущности, и вокруг bounding box сработавшей (triggered) сущности. Если trigger_range обеих сущностей — ноль, никакое событие не вызывается.

event_shoot — enable_shoot
Сущность поражена инструкцией trace с activate_shoot. You установлен на трассирующую сущность, если есть.

event_sonar — enable_sonar
Сущность поражена инструкцией trace с activate_sonar. You установлен на трассирующую сущность, если есть.

event_disconnect — enable_disconnect
Клиент сущности отсоединился и оставил сетевую игру. Событийная функция может использоваться чтобы удалить сущность. После старта событийной функции, все событийно-зависимые переменные и указатели, подобно normal и т.д., сохраняют свои значения только до следующей инструкции wait. В течение этой паузы они могут быть (и как правило будут) изменены другими функциями. Если Вы хотите сохранить их дольше, копируйте их в навыки сущности (skill). Для ясности, пусть главное действие сущности делает основную работы, а событийную функцию поддерживайте настолько короткой и простой насколько возможно, без любых wait инструкций.

Внутренние параметры

Следующие параметры не оказывают никакого влияния на вид или поведение при столкновении сущности непосредственно, но могут использоваться функциями:

client
В сетевой игре каждая сущность имеет уникальный параметр client. Если сущность была создана клиентом, параметр содержит номер этого клиента; иначе — 0. Это может использоваться, чтобы определить, были ли две сущности созданы тем же самым клиентом, или сервером. Если сущность была создана другой сущностью, она унаследует параметр client.

skill1 … skill48
Числовые переменные сущности общего назначения для использования в функциях. Первые навыки сущности могут быть установлены WED; их значение также зависит от действия сущностей. Остающиеся навыки могут использоваться для хранения внутренних числовых свойств сущности подобно скорости или положения цели. Каждые три последовательных навыка сущности могут использоваться вместе как вектор, который определяется заданием первого из этих трех навыков.

flag1 … flag8
Двоичные переменные сущностей и частиц общего назначения для использования в действиях. Могут также быть установлены в WED.

Добавить комментарий