Планирование движения

Планирование движение поможет Вам перемещать определённые образцы объекта от одной позиции к другой, избегая столкновений с другими образцами объекта (например, стенами). Планирование Движения является трудной задачей. Невозможно даже предоставить общих функций, которые будут работать удовлетворительно во всех ситуациях. Также, обработка столкновения свободных движений является трудоёмкой операцией. Итак, будьте осторожными, применяя это. Пожалуйста, держите эти замечания в уме, когда Вы будете использовать любую из следующих функций.

Различные формы планирования движения предусмотрены в Game Maker. Самая простая форма позволяет, чтобы образец объекта отправился к конкретной целевой позиции, пытаясь по возможности перемещаться прямо. При этом беря другое направление, если первоначальный способ перемещения невозможен. Эти функции должны использоваться в событии шага образца объекта. Они должны соответствовать движениям планированных действий, которые также доступны:

mp_linear_step(x,y,stepsize,checkall) Позволяет образцу объекта перемещаться прямо к указанной позиции (x,y). Размер шага указывается stepsize. Если образец объекта уже в позиции, то он не переместится дальше. Если checkall - истина, то образец объекта остановится при контакте с образцом любого объекта. Если - ложь, то он остановиться только при контакте с твёрдыми образцами объекта. Отметьте, что эта функция не предусматривает "объездов", если образец встречает препятствие. В этом случае это просто терпит неудачу. Функция возвращает, если была достигнута целевая позиция.
mp_linear_step_object(x,y,stepsize,obj) Также как и функция выше, но на этот раз, только образцы obj считаются как препятствия. obj может быть объектом или идентификатором образца.
mp_potential_step(x,y,stepsize,checkall) Подобно предшествующей функции, но эта функция позволяет, чтобы образец объекта перемещался к конкретной позиции. Но в этом случае, он пытается избегать препятствий. Когда образец объекта должен встретить твёрдый образец объекта (или любой образец объекта, когда checkall - истина), то он изменит направление движения, пытаясь избежать столкновения с другим образцом и переместиться вокруг него. Метод не гарантируется, чтобы использовать его всё время, но в большинстве простых случаев - это эффективно переместит образец объекта к нужной цели. Функция возвращает, если была достигнута цель.
mp_potential_step_object(x,y,stepsize,obj) Также как и функция выше, но на этот раз, только образцы obj считаются как препятствия. obj может быть объектом или идентификатором образца.
mp_potential_settings(maxrot,rotstep,ahead,onspot) Предшествующая функция делает свою работу, используя множество параметров, которые могут быть изменены, используя эту функцию. Глобально, метод работает следующим образом. Сначала пытается переместить образец прямо к цели. Это предусматривается множеством шагов вперёд, которые могут быть установлены параметром ahead (3 по умолчанию). Уменьшение этого значения означает, что образец объекта запустится с изменённого направления позже. Увеличение значения, означает, что образец объекта будет запущен с изменённого направления раньше. Если проверяется столкновение, то образец "начнёт смотреть", куда ему лучше повернуть - налево или направо. Это происходит в шагах размера rotstep (10 по умолчанию). Уменьшая это значение, мы предоставляем образцу объекта больше возможностей перемещения, но это будет медленней. Параметр maxrot - немного трудней объяснить. Образец объекта имеет текущее направление maxrot (30 по умолчанию), которое указывает, сколько раз позволяется изменять своё текущее направление в шаге. Даже если бы образец мог переместиться, например, прямо в цель, то это завершилось бы только в том случае, если бы были не нарушены максимальные изменения направления. Если Вы делаете maxrot большим, то образец объекта может измениться много раз в каждом шаге. Это позволяет легче найти кратчайший путь, но путь при этом будет беспорядочным. Если Вы делаете значение меньшим, то путь будет более гладким, но образец может при этом выбрать более длинные отклонения (и иногда даже не обнаруживать цель). Когда никакой шаг не выполняется, поведение будет зависеть от значения параметра onspot. Если onspot - истина (значение по умолчанию), образец объекта возвращается в свою точку указанной суммы maxrot. Если - ложь, то образец объекта не переместится совсем. Устанавливать значение "ложь" иногда полезно, например, автомобили будут иметь быстрейший шанс обнаружения пути.

Пожалуйста, отметьте, что потенциальный метод использует только локальную информацию. Итак, образец только обнаружит путь в том случае, если эта локальная информация достаточно полная, чтобы определить правильное направление движения. Например, образец объекта не найдёт путь (выход) из лабиринта (в большинстве случаях).

Второй тип функций вычисляет длину от столкновения свободного "пробега" для образца объекта. Как только этот путь будет вычислен, Вы сможете назначить его образцу объекта, чтобы переместить его к цели. Вычисление пути занимает некоторое время, но после этого, выполнение пути будет быстрым. Конечно, это всё будет правильно, если ситуация между тем не изменится. Например, если препятствия изменяются, то Вам, возможно, понадобиться вычислить путь заново. Снова обратите внимание, что эти функции могут потерпеть неудачу. Эти функции доступны только в Pro издании Game Maker.

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

mp_linear_path(path,xg,yg,stepsize,checkall) Вычисляет прямолинейную траекторию для образца объекта из своей текущей позиции в позицию (xg,yg), используя указанный размер шага. Это использует шаги подобно функции mp_linear_step(). Указанный путь должен уже существовать, и он будет переписан новым путем. Функция возвращает, если путь был обнаружен. Функция остановит и сообщит о неудаче, если никакая прямолинейная траектория не существует между началом и целью. Если это терпит неудачу, то путь всё ещё будет создан, при запуске до той позиции, где образец объекта будет заблокирован.
mp_linear_path_object(path,xg,yg,stepsize,obj) Также как и функция выше, но на этот раз, только образцы obj считаются как препятствия. obj может быть объектом или идентификатором образца.
mp_potential_path(path,xg,yg,stepsize,factor,checkall) Вычисляет путь для образца объекта из своей текущей позиции в позицию (xg,yg), используя размер указанного шага, чтобы избегать столкновения с препятствиями. Это использует потенциальные шаги области подобно функции mp_potential_step() и также параметры, которые могут быть установлены mp_potential_settings(). Указанный путь должен уже существовать, и он будет переписан новым путем. (Смотрите последующую главу о том, как создавать и уничтожать пути.) Функция возвращает, если путь был обнаружен. Чтобы избегать функций, продолжающих непрерывную обработку, Вам нужно установить длину показателя больше чем 1. Функция остановится и сообщит о неудаче, если она не сможет найти путь короче, чем время показателя расстояния между началом и целью. Показатель 4 - нормальный и достаточно хороший, но если Вы ожидаете длинные отклонения, то Вы можете сделать его дольше. Если это терпит неудачу, то путь всё ещё будет создан при запуске до начала целевой позиции, но её образец не достигнет.
mp_potential_path_object(path,xg,yg,stepsize,factor,obj) Также как и функция выше, но на этот раз, только образцы obj считаются как препятствия. obj может быть объектом или идентификатором образца.

Другие функции используют более сложный механизм, используя базирующийся метод сетки (иногда названной A* алгоритм). Это будет более успешным действием в обнаружении путей (хотя это всё ещё может потерпеть неудачу) и найдёт пути быстрее, но для этого потребуется от Вас дополнительной работы. Основная идея выглядит следующим образом. Прежде всего, мы помещаем сетку в (важную часть) комнату. Вы можете использовать тонкую сетку (медленней) или грубую сетку. Затем, для всех важных объектов, мы определяем ячейки сетки, которые перекрывают сетку (или используя bounding box или точную проверку) и отмечаем эти ячейки как запрещённые. Такая клетка будет выделена как полностью запрещённая, даже если бы она была частично перекрыта препятствиями. Наконец, мы определяем начало и целевую позицию (которая должна быть размещена в свободных клетках), и функция вычисляет самый короткий путь (действительно близкий к самому короткому) между ними. Путь будет работать между центрами свободных клеток. Если ячейки достаточно большие, то образец объекта, установленный в своем центре, будет полностью в нём размещён, что будет иметь успех. Этот путь Вы можете теперь назначить образцу объекта.

Базирующийся метод сетки - очень мощный элемент (и используется в основном в профессиональных играх), но он требует, чтобы Вы проделывали всё это, мысля очень осторожно. Вы должны определить, какая область и размер ячейки будет соответствовать оптимальному решению для Вашей игры. Также Вы должны определить, какие объекты должны быть аннулированы и иметь точную проверку столкновений, это важное значение. Все эти параметры сильно влияют на эффективность метода.

В целом, размер ячеек важен. Помните, что ячейки должны быть достаточно велики, так что движущийся объект установленный в начале центра клетки, должен быть размещён полностью в ячейке. (Будьте осторожными с начальной позицией объекта. Также поймите, что Вы можете сдвинуть путь, если начало объекта - не в своём центре!) С другой стороны, меньшие ячейки предоставляют больше возможностей существующих путей. Если Вы делаете ячейки слишком большими, то расстояние между препятствиями может закрыться, поскольку все ячейки пересекут препятствие. Следующие фактические функции для базирующего метода сетки доступны.

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

mp_grid_create(left,top,hcells,vcells,cellwidth,cellheight) Создаёт сетку. Это возвращает идентификатор, который должен быть использован во всех других вызовах. Вы можете создать и поддерживать многочисленные структуры сетки в том же моменте. left и top указывают позицию левого верхнего угла сетки. hcells и vcells указывают число горизонтальных и вертикальных ячеек. Наконец, cellwidth и cellheight указывают размер ячеек.
mp_grid_destroy(id) Уничтожает указанную структуру сетки и освобождает используемую память. Не забывайте использовать это, если Вам больше не нужна структура.
mp_grid_clear_all(id) Маркирует все освобождаемые ячейки сетки.
mp_grid_clear_cell(id,h,v) Очищает указанную ячейку. Ячейка 0,0 - верхняя левая ячейка.
mp_grid_clear_rectangle(id,left,top,right,bottom) Очищает все ячейки, что пересекает указанный прямоугольник (в координатах комнаты).
mp_grid_add_cell(id,h,v) Выделяет указанную ячейку как запрещённую. Ячейка 0,0 - верхняя левая ячейка.
mp_grid_add_rectangle(id,left,top,right,bottom) Выделяет все ячейки, что пересекает указанный прямоугольник как запрещённый.
mp_grid_add_instances(id,obj,prec) Выделяет все ячейки, что пересекает образец указанного объекта как запрещёный. Вы можете использовать индивидуальный образец объекта, создавая obj для идентификатора образца. Также Вы можете использовать ключевое слово all, чтобы указывать все образцы всех объектов. prec - указывает, что независимо точной проверки, столкновение должна быть осуществлено (будет работать только в том случае, если точная проверка проверена для спрайта используемого образцом объекта).
mp_grid_path(id,path,xstart,ystart,xgoal,ygoal,allowdiag) Вычисляет путь через сетку. path - должен указать существующий путь, который будет заменён путём, задаваемым компьютером. xstart и ystart - указывают начало пути, и xgoal и ygoal - цель. allowdiag - указывает, что допускаются диагональные перемещения вместо обычных горизонтальных и/или вертикальных. Функция возвращает, если путь успешно обнаружен. (Отметьте, что путь не зависит от текущего образца объекта; это путь через сетку - не путь для специфического образца объекта.)
mp_grid_draw(id) Рисует сетку с зелёными свободными ячейками и красными ячейками - запрещёнными. Эта функция очень медленная и предусмотрена только как отладочное средство.