Но сначала, конечно же, поговорим о событиях в ГМ. Все они происходят в определённый момент - по достижению неких условий, событий. Создаем объект - выполняется событие Create и вместе с ним весь код определённый в этом событий, наступил момент обновления вызываем событие Step, наступил момент рисования - Draw, нажали кнопку Keyboard_press и т.д. Т.е. мы не постоянно выполняем код и не постоянно опрашиваем объект:
- Игра: Ты обновился?
- Интерфейс: Нет.
- Игра: Ты обновился?
- Интерфейс: Нет!
- Игра: Ты обновился?
- Интерфейс: Да нет ещё! Я скажу когда я обновлюсь.
С этого момента, программистам пришла идея ввести так называемые Callback-функций. Мы не будем смотреть как они конкретно работают, т.к. нам потребуются знания не входящие в ГМ, но рассмотрим просто схему работы.
Когда наступают некие условия или необходимость, то вызывается функция по указателю. Происходит callback вызов: мы говорим что нам нужно это, т.с. заказываем и нам это присылают. Заказываем на то что указал наш палец в меню. Где палец - указатель, а выбор в меню это функций. Теперь переговоры выглядят так:
- Игра: Интерфейсу необходимо обновление.
- Интерфейс: Есть обновление!
Выявляются 2 действующих лица. Первый (в списке, верхний) - раздающий событие, второй (нижний) - слушающий. Раздающий всегда один, точнее одно событие раздает один слушающий. В то время как слушающих может быть сколько угодно. Это как вечеринка в клубе: DJ - один, слушающих много. Т.е. теперь список может выглядеть так:
- Событие Draw: Необходимо обновление.
- Карта: Есть обновление!
- Инвентарь: Есть обновление!
- Персонаж: Есть обновление!
- ...
- Враг №N: Есть обновление!
В ГМ уже есть много событий, но некоторые не подходят и нам необходимо определить свои и тут-то приятно осознавать что мы умеем это делать. Как именно, рассмотрим далее. А пока затронем тему, когда это нужно? Это нужно тогда, когда вы хотите уменьшить кол-во вызовов. Некоторые из вас уже наверняка пробовали имитировать создание событий. Например, обновление пути для персонажа. Если использовать этот код в событий Step, то код может выполняться чаще чем нужно. Вы подумали, а что если код выполнять не так часто? И вы старательно запихивали этот код в событие alarm и выполняли код каждые N step'ов. Этот приём и есть эмулирование работы событий. Но по сути, в чем минус этого события? В том что обновление пути может быть чаще, а может быть реже чем нужно. Т.е. вы выполняете код тогда когда прошли N игровых циклов, а не тогда когда путь нуждается в обновлений.
Плавно переходим к тому что надо сделать. А надо путь изменить тогда когда путь может измениться, т.е. когда произойдет событие "изменение обстановки" - onChangePath (при изменений). Пихнем код обновления пути в функцию onChangePath и будем вызывать тогда, когда наш путь может измениться. Теперь, изменение пути будет столько сколько необходимо, а не столько сколько пройдёт ваш персонаж и уж тем более не меньше чем нужно, дабы избежать глюков. Допустим, создали кубик который может повлиять на путь, то вызываем onChangePath у слушающих образцов. В этом случае, кубик - раздающий, тому кому надо путь изменить - слушающий.
Чтобы вызвать код обновления пути необходимо написать след. конструкцию (в Create кубика):
with(object)onChangePath();
Где object - объекты в которых нужно обновить пути. Помнить нужно одно, что событие onChangePath принадлежит только одному объекту - object, выполнив этот код в object2, все может закончится плачевно. Т.к. в ГМ такие конструкций не безопасны, безопасность ложится на ваши плечи.
Теперь когда создается кубик, меняется структура карты и некоторые пути могут пересекать этот кубик, поэтому мы вызываем код у нужных объектов. Callback - называется так потому что этот код выполняется помимо основных функций объекта, мы как бы вызываем вновь этот объект.
Перейдем к примером, где этот прием может понадобится:
- UI (User Interface, пользовательский интерфейс) - здесь эта техника используется очень часто. Т.е. интерфейс "работает" только тогда когда пользователь с ним взаимодействует, иначе трата сил впустую. Пользователь нажал кнопку мышки, вызываем событие нажатие мышки и обработку. Если курсор находился над кнопкой открытия инвентаря - выполняем onInventoryOn, в нем рисуем инвентарь. Нажали кнопку в инвентаре, то выполняем событие onChange и снова рисуем. Заметьте, инвентарь отрисуется за 150 степов только сколько раз он изменился + 1 на создание, а не 150 раз.
- Обмен данными по сети. Нет смысла передавать одни и те же данные.
- Искусственный Интеллект - передаем сообщения между объектами, обновляем ИИ только по событию изменения, если обстоятельства не изменились, то нечего заново решать ту же задачу.
- Поиск пути
- др. области
Сам приём достаточно прост, но в то же время и мощен. С его помощью вы можете вызывать действия с такой частотой насколько это требуется, а не каждый шаг. Это упростит разработку и ускорит выполнение программы.
Примерчик по случаю. Прочитайте информацию внутри для помощи. Смысл примера в том чтобы увидеть разницу выполнения кода. При событийном вызов функций обновления идет всего на единицы, а не на кол-во игровых циклов в секунду. Это особенно эффективно сказывается на отрисовке, т.е. на тяжёлых для выполнения операциях. Моя реализация может отличаться от вашей.
Комментариев нет:
Отправить комментарий