Game guardian скрипты

Подскажите принцип работы простого бота для браузерки.

Не могу понять прицип -какие данные обычно берут и как ими управляют? То есть заставляют персонажа имитировать деятельность.

Если есть статьи на эту тему-буду рад ссылке.

Содержание

Серия контента:

Этот контент является частью # из серии # статей: 30 игровых скриптов, которые можно написать на языке PHP

Следите за выходом новых статей этой серии.

Начало работы

В качестве гейммастера/ведущего и разработчика игр мне часто приходится писать небольшие утилиты и скрипты, которые помогают мне при руководстве играми, а также при планировании игр и при непосредственном участии в них. Иногда мне необходима быстрая подсказка. В другой раз мне может потребоваться большое количество имен для NPC-персонажей (Non-Player Character – персонаж, не управляемый игроком). Время от времени мне приходится работать с числами, подсчитывать некоторые шансы или интегрировать в игру те или иные головоломки. Реализация многих из этих задач существенно упрощается, если заблаговременно приложить определенные усилия к написанию соответствующего скрипта.

В этой статье анализируется 10 фундаментальных скриптов, которые могут применяться в играх различного типа. Прилагаемый к данной статье архив программного кода (далее – Архив) содержит полный исходный текст для каждого описываемого в ней скрипта. Кроме того, вы можете увидеть все эти скрипты «в действии» на Web-сайте: chaoticneutral.

Мы «пробежимся» по этим скриптам достаточно быстро. Такие темы как поиск хостинга или настройка сервера в данной статье рассматриваться не будут. Сегодня существует множество Web-хостов, которые предлагают PHP-дистрибутивы; в частности, инсталлятор XAMPP удобен в том случае, если вы хотите сформировать свою собственную среду. Мы не будем тратить много времени на разговоры о наилучших методиках PHP-разработки или о принципах проектирования игр. При создании рассматриваемых скриптов к ним предъявлялись несколько иные требования – эти скрипты должны были быть простыми для понимания, легкими в использовании и быстрыми в усвоении.

Базовый «кидатель кубика» (die roller)

Для многих игр и игровых систем необходима игральная кость (так называемый «кубик»). Давайте начнем с самого простого варианта: с кидания одного шестигранного кубика. По существу, между киданием шестигранного кубика и выбором случайного числа в промежутке от 1 до 6 нет никаких различий. В PHP эта операция реализуется достаточно просто: echo rand(1,6); .

Во многих случаях этого будет вполне достаточно. Но если мы имеем дело с азартными играми, то нам нужно что-либо получше. PHP предоставляет более эффективный генератор случайных чисел: mt_rand() . Не вдаваясь в детальные различия между этими двумя генераторами скажем, что генератор случайных чисел mt_rand() работает быстрее и лучше: echo mt_rand(1,6); . Конечно, нужно оформить это в виде функции (листинг 1).

Листинг 1. Использование функции с генератором случайных чисел mt_rand()

Далее, тип кубика, который мы собираемся кинуть, можно передать в эту функцию в виде параметра (листинг 2).

Листинг 2. Передача типа кубика как параметра

Теперь, в зависимости от наших потребностей, мы сможем реализовать бросание нескольких кубиков одновременно (возвращая массив результатов) или же бросание нескольких кубиков разного типа. Для большинства подобных задач мы сможем воспользоваться нашим простым скриптом.

Генератор случайных имен

Если вам приходится руководить играми, сочинять сюжеты или одновременно создавать группу персонажей, то иногда у вас могут возникать трудности с придумыванием новых имен. Рассмотрим простой генератор случайных имен, который вы сможете использовать для решения этой задачи. Для начала создадим два простых массива — один с именами, другой с фамилиями (листинг 3).

Листинг 3. Два простых массива с именами и с фамилиями

После этого мы сможем выбирать случайным образом по одному элементу из каждого массива: echo $male . ‘ ‘ . $last; . Чтобы за один прием сформировать группу из нескольких персонажей, мы можем просто перемешать содержимое массивов и выбрать необходимое количество имен (листинг 4).

Листинг 4. Перемешивание массивов имен и фамилий

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

Листинг 5. Создание текстовых файлов для имен и фамилий

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

Генератор сценариев

Используя те же базовые принципы, на которых построен генератор имен, мы можем создать так называемый генератор сценариев. Такой генератор полезен в ролевых играх и в других ситуациях, где необходимо придумать псевдослучайный набор обстоятельств, который может использоваться для разыгрывания ролей, импровизации, написания сюжета и т.д. Одна из моих любимых игр, Paranoia, сопровождается пакетом GM Pack, в состав которого входит инструмент Mission Blender. Инструмент Mission Blender позволяет быстро скомпоновать полную миссию по результатам «кидания кубика». Давайте создадим свой собственный генератор сценариев.

За основу примем следующий сценарий: Вы просыпаетесь и обнаруживаете себя заблудившимся в лесу. Вы знаете, что вам необходимо добраться до Нью-Йорка, но не знаете почему. Неподалеку вы слышите лай собак и звуки враждебной погони. Вам холодно, вы дрожите, и у вас нет оружия. Каждое предложение в этом сценарии представляет его определенный аспект:

  • «Вы просыпаетесь и обнаруживаете себя заблудившимся в лесу» – установка исходного состояния.
  • «Вы знаете, что вам необходимо добраться до Нью-Йорка» – описание цели.
  • «Вы слышите лай собак» – представление противника.
  • «Вам холодно, вы дрожите, и у вас нет оружия» – добавление осложняющих факторов.

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

Листинг 6. Генерация сценария

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

Построитель карточной колоды и тасователь карточной колоды

Если вы играете в карточные игры и интересуетесь созданием соответствующих скриптов, мы можем соединить «построитель» карточной колоды со встроенным «тасователем» этой колоды. Для начала построим базовую колоду из стандартных игральных карт. Мы должны создать два массива, один из которых предназначен для хранения мастей, а второй – для хранения достоинств карт. Это обеспечит нам необходимую гибкость впоследствии, если мы захотим добавить другие масти или типы карт (листинг 7).

Листинг 7. Построение базовой карточной колоды

Теперь построим массив, который будет содержать все карты колоды. Мы можем сделать это достаточно просто – с использованием двух циклов foreach foreach (листинг 8).

Листинг 8. Построение массива карточной колоды

После того как мы построили массив карточной колоды, мы можем легко перетасовать колоду и вытянуть карту случайным образом (листинг 9).

Листинг 9. Перемешивание карточной колоды и вытаскивание случайной карты

Теперь мы можем с легкостью составлять наборы из заданного количества карт или строить комплекты из нескольких карточных колод.

Калькулятор шансов: вытягивание карты

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

Листинг 10. Комплектование двух рук по пяти карт в каждой

Затем мы можем посмотреть на колоду, чтобы определить, сколько карт осталось и каковы шансы на вытягивание определенной карты. Определение количества оставшихся карт не составляет никаких трудностей: это количество элементов в массиве $deck . Для вычисления шансов на вытягивание определенной карты нам необходима функция, позволяющая перебрать всю колоду и оценить оставшиеся карты на соответствие (листинг 11).

Листинг 11. Вычисление шансов на вытягивание определенной карты

Теперь мы можем выбрать карту, которую мы пытаемся вытянуть. Для упрощения этой задачи создадим массив, представляющий определенную карту. Таким образом мы можем искать любую нужную нам карту (листинг 12).

Листинг 12. Поиск определенной карты

Мы также можем искать карту с определенным достоинством или определенной масти (листинг 13).

Листинг 13. Поиск карты с определенным достоинством или определенной масти

Простой дилер для игры в покер

Теперь, когда у нас есть построитель карточной колоды и механизмы для определения шансов на вытягивание определенных карт, мы можем создать простого дилера (раздатчика карт), чтобы попрактиковаться в наборе руки. В этом примере мы построим дилера для варианта покера с пятью картами и заменой (так называемый Five Card Draw Poker). Дилер сдает игроку пять карт из колоды. Вы указываете, от каких карт хотите отказаться (по номеру карты), после чего дилер заменяет эти карты другими картами из колоды. В данном примере мы не будем устанавливать пределы на количество заменяемых карт или правила взаимоотношений между участниками игры, хотя для вас это может оказаться полезным упражнением.

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

Листинг 14. Использование флажков (checkbox) для указания на заменяемые карты

Затем просмотрите входной массив array $_POST , чтобы увидеть, какие карты были отмечены для замены (листинг 15).

Листинг 15. Просмотр входного массива

С помощью этого скрипта вы сможете «набить руку» — намеренная игра слов — на оптимальные действия при определенных комбинациях карт.

Игра «Виселица»

Игра «Виселица» (или «Палач») – это, по существу, игра в отгадывание слов. Ведущий («палач») задумывает слово определенной длины, а игрок должен отгадать это слово, поочередно предлагая по одной букве (ограниченное число раз). Если игрок предложил букву, которая встречается в загаданном слове, то ведущий заполняет все местоположения этой буквы. После заданного количества неправильных догадок (как правило, шести), игрок проигрывает. Чтобы скомпоновать шаблон для игры в «Виселицу», мы сначала должны создать список слов. Сделаем этот список его в виде простого массива (листинг 16).

Листинг 16. Создание списка слов

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

Теперь, когда у нас есть список слов, мы должны выбрать одно из них по случайному закону, отобразить пустую позицию для каждой буквы этого слова и приступить к приему догадок. На всем протяжении игры мы должны отслеживать правильные и неправильные догадки. Мы решим эту задачу максимально просто – посредством сериализации массивов догадок и продвижения их вместе с каждой очередной догадкой. Если бы мы захотели воспрепятствовать мошенничеству посредством просмотра исходного текста страницы, то нам следовало бы сделать нечто более защищенное.

Создайте массив для хранения букв и правильных/неправильных догадок. Для правильных догадок мы будем заполнять массив буквами в качестве идентификаторов и точками в качестве значений (листинг 17).

Листинг 17. Построение массивов для хранения букв и догадок

Теперь нам нужно написать небольшой фрагмент программного кода для оценки догадок и демонстрации слова по ходу игры (листинг 18).

Листинг 18. Оценка догадок и демонстрация хода игры

В Архиве демонстрируется сериализация массивов догадок и их продвижение от догадки к догадке.

Помощник для разгадывания кроссвордов

Я прекрасно знаю, что подобный помощник – это дурной тон, но иногда он все же может потребоваться. Например, при разгадывании кроссворда вы зашли в тупик, пытаясь отыскать пятибуквенное слово, которое начинается с буквы C и заканчивается буквой T. Используя список слов, который мы создали ранее для игры в «Виселицу», мы можем легко находить слова, соответствующие определенному шаблону. Во-первых, определите способ передачи слов. Для упрощения этой задачи замените недостающие буквы точками: $guess = «c. t»; . Поскольку регулярные выражения рассматривают точку как одиночный символ, мы можем с легкостью пройти по списку слов в поисках совпадения (листинг 19).

Листинг 19. Прохождение по списку слов

При условии достаточно высокого качества нашего списка слов и достаточной точности наших догадок мы сможем получить приемлемый список слов для последующей проверки на возможные совпадения. После этого вам останется решить, какое из слов – «chest» (грудная клетка) и «cheat» (жульничество) – лучше подходит на роль слова из пяти букв, означающего «нарушение правил игры».

Механизм для игры Mad Libs

Mad Libs – это игра в слова, в которой игрок берет короткий рассказ и заменяет ключевые типы слов другими словами того же типа, чтобы создать новую, более глупую версию той же истории. Возьмем следующий текст: «I was walking in the park when I found a lake (Я шел по парку и нашел озеро). I jumped in and swallowed too much water (Я нырнул в озеро и проглотил слишком много воды). I had to go to the hospital (Мне пришлось пойти в больницу)». Начните заменять типы слов различными токенами. Начинайте и завершайте каждый токен подчеркиванием, чтобы предотвратить случайные совпадения строк (листинг 20).

Листинг 20. Замена типов слов символами слов

После этого создайте несколько списков базовых слов. В этом примере мы не будем давать большую волю своей фантазии (листинг 21).

Листинг 21. Создание нескольких списков базовых слов

Теперь мы можем многократно оценивать текст на предмет возможной замены токенов по мере необходимости (листинг 22).

Листинг 22. Оценка текста

Вполне очевидно, что это простой и достаточно сырой пример. Чем точнее будут наши списки слов и чем больше времени мы потратим на создание нашего базового текста, тем лучше будут наши результаты. Мы уже использовали текстовые файлы для создания списков имен и списков базовых слов. Используя тот же самый принцип, мы можем создавать списки слов, разбитые по типам, и использовать их для создания более разнообразных игр типа Mad Libs.

Механизм для игры в лото

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

(Отказ от ответственности. Этот скрипт не поможет вам выигрывать в лото, так что не тратьте деньги на билеты. Он предназначен исключительно для развлечения).

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

Листинг 23. Сохранение выигрышных номеров лото в текстовом файле

Вполне очевидно, что этого недостаточно для выявления статистических закономерностей. С другой стороны, этого вполне достаточно для иллюстрации основных принципов.

Создайте базовый массив для хранения диапазона выбираемых чисел. Например, если мы выбираем числа в диапазоне от 1 до 40 (т. е. $numbers = array_fill(1,40,0); , то затем будем перебирать выигрышные номера и увеличивать значения соответствующих элементов массива (листинг 24).

Листинг 24. Прохождение по выпавшим значениям

И, наконец, отсортируйте массив по возрастанию значений. В результате наименее выбираемые числа должны попасть в начало массива (листинг 25).

Листинг 25. Сортировка чисел по частоте их выпадения

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

Эта статья является полезным ресурсом для всех, кто хотел бы приступить к использованию языка PHP для обогащения своих игровых возможностей. Во второй статье серии под названием «30 игровых скриптов, которые можно написать на языке PHP» мы на базе описанного в этой статье кода создадим более совершенные скрипты, которые предоставят нам дополнительные возможности.

Ресурсы для скачивания

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

Современный интернет немыслим без скриптов. Учимся писать на JavaScript.

Если бы для интернета писали Библию, она начиналась бы так:

Сначала была почта. И увидели инженеры, что это хорошо. И создали они WWW с гиперссылками. И увидели инженеры, что это тоже хорошо. И создали они тогда язык JavaScript для оживления страничек.

Примерно так происходило в реальности. JavaScript придумали, чтобы «оживить» HTML. Скрипты JavaScript пишутся непосредственно в текст HTML или хранятся в отдельных файлах, как и стили CSS. Они выполняются сразу после загрузки страницы в браузер.

Даже сам язык в первое время назывался LiveScript. Потом его переименовали в JavaScript, потому что планировали как-то увязать с языком общего назначения Java. Но сейчас у них нет практически ничего общего, а JavaScript — совершенно независимый язык программирования со своей четкой спецификацией ECMAScript.

Формально JavaScript является торговой маркой Oracle, а этот язык — «расширение» ECMAScript, наряду с JScript от Microsoft и ActionScript, но это скорее заморочки владельцев торговых марок. Главное, что свободный ECMAScript никому не принадлежит.

Со временем сфера влияния JavaScript значительно расширилась. Его начали использовать не только для скриптов на странице HTML, но и для серьезных больших веб-приложений и целых программ, которые работают в браузере. Есть инструменты, чтобы специальным образом «упаковать» эти программы и выполнять их отдельно от браузера. Это компиляторы и интерпретаторы, которые более подробно рассматриваются на обучающих курсах «Java-разработчик» и «Веб-разработчик».

Приложения JavaScript выполняются в любой среде, где есть соответствующий интерпретатор.

Нас пока интересуют только браузеры и HTML-странички.

Как сделать JavaScript? Написать элементарный скрипт не сложнее, чем простую HTML-страничку, ведь скрипты JavaScript пишутся обычным текстом, то есть их можно создавать буквально в том же «Блокноте», сохраняя потом в отдельных файлах или вставляя в тело HTML-документа. Самые простые вещи на JavaScript делаются действительно просто.

Как написать JavaScript

Для примера сделаем простой скрипт для выполнения сервером сценариев Windows. Этот скрипт можно написать прямо в «Блокноте» и выполнить без браузера.

WScript. echo (» Привет, Skillbox!»)

Пишем этот текст в «Блокноте», затем сохраняем файл под именем skillbox.js и запускаем в «Проводнике» Windows.

Аналогичный скрипт можно записать прямо в коде страницы HTML между тегами . Там уже можно использовать обычные методы JavaScript, а не метод echo специфического объекта WScript. Рассмотрим некоторые из стандартных методов для ввода и вывода данных в браузере.

alert()

Метод alert() отображает окошко с кнопкой «OK». В окне выводится сообщение, которое указано в скобках. Например, «Привет, Skillbox!». То есть в данном случае браузер делает ровно то же самое, что перед этим делал сервер сценариев Windows.

Эти примеры тоже можно писать в «Блокноте», только сохранять в файлах с расширением HTML. Например, skillbox.htm.

В качестве аргумента alert() можно указать не только конкретный текст, но и результат каких-либо вычислений или обработки других данных. Например, alert(x), где x вычисляется отдельно.

confirm()

Метод confirm() выводит такое же окно с сообщением, но уже с двумя кнопками — «ОК» и «Отмена». В зависимости от того, какую кнопку щелкнет пользователь, метод возвращает либо значение true, либо false. Сервер получает это возвращаемое значение от пользователя и выполняет какое-то действие, в зависимости от ответа.

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

prompt()

Метод prompt() выводит диалоговое окно с сообщением и текстовым полем, куда пользователь вводит данные. Здесь тоже предусмотрены две кнопки «ОК» и «Отмена». По нажатию первой кнопки метод возвращает на сервер введенный текст, а по нажатию второй кнопки возвращает логическое значение false.

Синтаксис здесь такой:

prompt ( сообщение, значение_поля_ввода_данных)

Значение поля ввода необязательно. Туда можно вписать текст, который изначально введен в поле для удобства пользователя.

Возможности современного JavaScript выходят далеко за рамки примитивного ввода-вывода данных через формы. Эти методы мы привели только в качестве самых простых примеров. Кроме этого, JavaScript позволяет реагировать на действия пользователя. Например, на движения мышкой или нажатие определенных клавиш. JavaScript часто используется для обеспечения асинхронной работы ( Технология AJAX), когда информация на странице обновляется без ее перезагрузки. В этом режиме данные отправляются на сервер и загружаются оттуда в интерактивном режиме. Кроме того, JavaScript способен манипулировать с HTML-элементами на странице (создавать и прятать теги и т.д.) и делать многое другое.

Полезные инструменты

Консоль разработчика

Во всех популярных браузерах есть специальная консоль разработчика. Она показывает код скриптов на странице, а также выводит другую полезную информацию. В Chrome, Firefox и IE консоль разработчика открывается по нажатию горячей клавиши F12, в Safari — Ctrl+Shift+I или Ctrl+Alt+C. На скриншоте скрипты отображаются справа вверху, вместе с другими элементами веб-страницы.

Редакторы кода

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

Для начала можно рекомендовать один из легких редакторов:

В будущем есть смысл присмотреться к IDE:

Инструкторы на курсе «JavaScript с нуля» посоветуют лучшие инструменты и помогут разобраться с любыми вопросами. Это практический 4-месячный курс для тех, кто хочет научиться основам языка сценариев с индивидуальным наставником, разработать фронтенд для интерактивного веб-проекта и положить кейс к себе в портфолио.

Курс идеально подойдет дизайнерам-разработчикам и начинающим программистам, кто уже знаком и умеет разрабатывать страницу на HTML и CSS, но не намерен останавливаться в изучении программирования. Преподаватели практически «на пальцах» объяснят базовые основы синтаксиса JavaScript, научат создавать визуальные интерактивные элементы и помогут разработать первый веб-проект на JavaScript.

Как работают скрипты

Каждый игрок должен знать свою роль назубок!
И не надо бестолково гонять по сцене.
Играть надо головой!
И не надо грубить, а то я вас выведу с поля.
«Берегись автомобиля»,
режиссёр — Е. Евстигнеев.

Да, удивительно неорганизованный народ эти актеры! То реплики свои забудут, то начнут галдеть хором, перебивая друг друга, так что ничего не разберешь, то перестанут двигаться, или наоборот, двигаются не туда куда нужно. Глаз да глаз за ними нужен! Если мы продолжим нашу аналогию с театром, то можем заметить, что в театре есть человек, который непосредственно управляет актерами, так сказать, в реальном времени, прямо во время спектакля. Это суфлер! Он и реплики подскажет, и укажет, куда и как должен двигаться актер, и вовремя напомнит актеру, что пора закругляться и уходить со сцены. Есть такой «суфлер» и в нашей Мафии, назовем его условно скрипт-супервайзер (script-supervisor) или надсмотрщик за скриптами, если по-русски. Фактически, это подсистема движка игры, которая отвечает за правильное, корректное выполнение скриптов всех актеров занятых в текущей сцене.

Давайте немного разберемся, как работают скрипты и как ведут себя наши актеры. Во время игры нам кажется, что несколько актеров исполняют свои роли одновременно, например, водитель ведет машину, пассажиры поливают встречных копов из автоматов, копы отстреливаются, не забывая при этом дуть в свистки, по улицам хотят пешеходы, ездят машины и т.д. Вот сколько актеров задействовано. Но, тут есть очень существенный нюанс! Дело в том, что в компьютерных операционных системах типа Windows не существует реальной многозадачности – в каждый момент времени выполняется только одна задача, иными словами действует только один актер. То, что несколько актеров действуют одновременно, нам только кажется! Нужно запомнить и четко понимать, что многозадачность в Windows, и, как следствие, во всех виндовс-приложениях виртуальная. Существует много принципиально разных способов реализации многозадачности, например, по времени, по готовности или по запросу, по прерываниям и т.д. Не буду сейчас все эти способы рассматривать, тем более, что в Мафии многозадачность для скриптов реализована все-равно иначе

В движке Mafia реализовано покомандное выполнение скриптов. В каждый момент времени выполняется только одна команда и только для одного актера! В следующий момент выполняется команда для другого актера и так далее.

Представьте, если говорить очень упрощенно, что у нас есть три актера – один шагает по тротуару, второй стреляет из автомата, третий ведет машину. Тогда эти три скрипта будут выполняться таким образом – первый человек делает шаг, второй выстрел, третий проезжает несколько сантиметров, управление передается первому актеру, и он делает еще шаг, второй актер делает еще выстрел, третий проезжает еще немного и т.д. по кругу. Если мы будем смотреть на этот спектакль, то нам покажется, что первый актер непрерывно шагает, второй без остановки стреляет, а третий плавно ведет машину, хотя в определенный момент времени активен только один актер, а другие его ждут. Это очень важный момент! Его нужно понять! Ведь тогда получается, что актер не будет продолжать свою роль, пока не отыграют свои реплики (команды) другие актеры, занятые в сцене. А если у нас тысяча актеров? Кстати, это вполне реальное число актеров в игровой сцене! Не будет ли действие каждого из них слишком заторможено ожиданием своей очереди? Тут-то нам и поможет наш супервайзер, одна из основных задач которого как раз и состоит в оптимизации работы скриптов.

Как же работает супервайзер скриптов? Выглядит это примерно следующим образом, после загрузки скриптов (если мы загружаем миссию с нуля, а не сохраненку!) супервайзер берет первую команду первого скрипта и передает ее обработчику команд. Обратите внимание, супервайзер не обрабатывает команды сам, он только строит последовательность из команд для обработчика! Передав первую команду, супервайзер запоминает, что следующая команда для выполнения в первом скрипте будет вторая, для этого он помечает ее специальной меткой, назовем её указателем. А сам переходит к первой команде второго скрипта и т.д. до обработки последнего скрипта в сцене. После этого супервайзер переходит опять к первому скрипту, только уже ко второй команде, и все повторяется со сдвигом указателей и, естественно, с запоминанием их положения. Таким образом, всегда активной, т.е. выполняемой в данный момент, является только одна команда из всех скриптов сцены, а остальные ждут своей очереди.

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

Синяя стрелка, это указатель на текущий скрипт, из которого берется очередная команда. Зеленые метки указывают на текущие команды, готовые в исполнению в каждом скрипте и ожидающие своей очереди. А что означают красные флажки? Не догадываетесь? Программисты наверняка сообразили, а остальным (ведь для них я и пишу эту статью) поясню, это флаг готовности скрипта к выполнению, он показывает нужно ли выполнять конкретный скрипт в этом цикле или пропустить его. Я говорил, что супервайзер, выполнив команду одного скрипта, переходит к следующему, это верно. Но, перейдя к следующему скрипту супервайзер первым делом проверяет флаг готовности и, если этот флаг не установлен, то скрипт пропускается и супервайзер переходит к следующему скрипту и так далее. На самом деле, это может показаться сложным, хотя ничего сложного в этом нет и чтобы писать хорошие скрипты нужно четко в этом разобраться. Вот простой пример, все, кто пробовал разбираться в работе скриптов или писать что-то свое, встречали команду wait , она означает, что скрипт должен подождать (т.е. стать неактивным) указанное время. Так вот, эта команда просто снимает флаг готовности с этого скрипта на заданное время. Как только время истечет, флаг готовности появится, НО скрипт (вернее команда скрипта следующая за командой wait) не сразу начнет выполняться, а только тогда, когда до этого скрипта дойдет указатель (синяя стрелка на схеме). То есть, команда wait будет иметь небольшую задержку, обычно в пределах нескольких миллисекунд.

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

Давайте посмотрим на несколько команд для примера:

findactor
let flt = 10
enemy_changeanim
enemy_vidim

Эти команды выполняются практически мгновенно (несколько микросекунд, в зависимости от производительности компьютера) и не сбрасывают флаг готовности, следующая из ними команда будет выполняться в следующем цикле выполнения скриптов. Условно пометим такие команды зеленым цветом.

enemy_usecar
enemy_car_moveto
enemy_move_to_frame

Эти команды (правильнее называть их функциями) требуют времени на исполнение: первая ждет пока человек не сядет в машину, вторая – пока машина не доедет до указанного места, третья – пока актер не дойдет до пункта назначения пешком. На время выполнения указанных действий (т.е. пока не сел, не доехал, не дошел) флаг готовности со скрипта снимается, т.е. никаких команд из скрипта этого актера выполняться не будет! Фактически актер перестанет реагировать на все игровые события! А представьте, что получится, если актер не может сесть в машину, допустим, что дверь заблокирована другой машиной, или не может доехать до цели, т.к. попал в пробку, что тогда? Тогда актер будет тупо бегать вокруг машины или гудеть в пробке, пытаясь растолкать бампером другие машины. И как долго они будут этим заниматься? Часами? К счастью, движок Мафии гораздо «умнее» чем многие думают Проанализировав ситуацию, движок через какое-то время даст команду актерам прекратить бесполезные старания. Например, водитель, попавший в пробку, может вылезти из машины и продолжить свой путь пешком и т.п. В общем, нужно быть очень осторожным, использую эти команды, поэтому условно помечаю их красным цветом.

enemy_playanim
enemy_talk

Эти команды не снимают флаг готовности, но, по своей сути, требуют времени на исполнение! Первая команда заставляет актера выполнять какую-то анимацию, делать какие-то жесты или просто замереть в определенной позе. По второй команде актер должен произнести какую-то заданную фразу. Если не дать дополнительного времени на анимацию или фразу, то выглядеть будет довольно забавно, но не всегда так как требуется. Допустим, что за командой enemy_talk сразу следует команда enemy_move_to_frame, тогда актер начнет от нас (от Томми) уходить, бубня что-то нечленораздельное себе под нос. Нам этого, скорее всего, не нужно. А чтобы актер сказал фразу Тому, а потом удалился нужно вставить после enemy_talk команду wait со временем задержки равным или немного больше времени длины фразы. То есть, получается, что мы командой wait принудительно сбрасываем флаг готовности, т.к. команда enemy_talk сама этого делать не умеет. На самом деле, можно рассматривать такое ограничение не как минус, а как плюс! Ведь мы можем более гибко использовать готовые анимации и фразы, «нарезая» из них нужные куски и комбинируя. Эту группу команд помечаю желтым цветом, т.к. серьезных багов она не вызовет, однако работать с ней нужно все-таки аккуратно.

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

Если вы поняли логику, по которой супервайзер расставляет флаги готовности, то наверняка уже поняли и за счет чего происходит оптимизация скорости работы всей игровой сцены – из нее просто временно исключаются ненужные в данном цикле скрипты актеров. В результате, доступ к каждому активному актеру происходит значительно быстрее. Есть еще несколько «фокусов», которые супервайзер выполняет с флажками, это тоже весьма важный момент! Вспомните, когда мы движемся по Lost Heaven`у, то нам кажется, что весь город живой, везде ездят машины и ходят люди, это то, что мы называем городским трафиком. Однако, как совершенно справедливо рассудили разработчики Mafia, зачем трафик пускать там, где Томми (или игрок, как угодно) видеть его не способен! Например, Том находится в Маленькой Италии, зачем же машинам ездить в Хобокене? Их ведь там все-равно никто не увидит! Только никчемная затрата компьютерных ресурсов. В результате решили сделать так (и это правильно!), что трафик присутствует и движется только вокруг камеры с помощью которой мы видим Lost Heaven. Камера является как бы центром круга с радиусом примерно 300-400 метров, в котором и происходит вся городская жизнь Этот «круг» сопровождает Тома, куда бы тот ни двигался, так как камера «привязана» к нему, вот нам и кажется, что все районы города живые, а на самом деле, если там нет Томми, то нет и жизни Вы наверняка видели в игре как машина или пешеход внезапно исчезают или наоборот появляются из неоткуда, это значит, что вам удалось приблизиться к краю круга, значит супервайзер за вами не уследил

Важный момент! Если актер-человек убит, то есть его здоровье стало равно нулю, то скрипт этого актера исключается из последовательности обрабатываемых скриптов и восстановить его нельзя!

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

И напоследок еще несколько слов о логике работы супервайзера скриптов. Большую часть работы по управлению скриптами он делает автоматически, используя те принципы, о которых сказано выше. Но! Программисту дается возможность управлять логикой супервайзера, чтобы более эффективно и корректно работать со скриптами. Для управления супервайзером существует специальный набор команд, он не очень большой и его нужно просто запомнить. Разумеется, прежде чем запоминать команды необходимо четко понять что они делают. Многие мафиозные скриптеры используют эти команды направо и налево, совершенно не понимая для чего они нужны, что приводит к различным глюкам и трудно устранимым багам в игре!

Несколько примеров таких команд:

end — удаляет скрипт из последовательности обрабатываемых скриптов, вернуть скрипт обратно нельзя(!!!), для актеров-людей выполнение такой команды приведет к тому, что человек превратится в «привидение» — замрет в той позе, в которой его застало выполнение команды и станет «прозрачным». Применяйте эту команду с большой осторожностью, только для актеров, которые уже вам не нужны, и, желательно, выведены за пределы игровой сцены. А лучше вообще не применяйте

act_setstate xx, active|inactive — соответственно, устанавливает или снимает флаг готовности, скрипт актера будет или не будет обрабатываться. Установить снятый этой командой флаг готовности можно с помощью других команд.

enemy_forcescript nn — принудительно выставляет флаг готовности! Действует, даже если актер в данный момент выполняет одну из сложных функций, например, ведет машину и т.п.

commandblock 1 — принуждает супервайзер выполнять подряд несколько команд из скрипта одного актёра, не переходя к следующему актёру (т.е. без сдвига синей стрелки, см. рисунок) до момента получения отменяющей блок команды commandblock 0.

Командный блок, это одна из наиболее полезных и часто используемых команд. Например, вы хотите добавить Тому немного денег, считываете текущую сумму, прибавляете нужно количество и записываете результат Тому в кошелек, т.е. вы должны выполнить три коротких (зеленых) команды. Представьте, что в каком-то из следующих скриптов Тому тоже добавляют денег, тогда получится, что в следующем цикле вы запишите неверную сумму, ведь она была изменена уже после того как вы ее сохранили! Тут нам и поможет блок команд, мы выполним все три команды без переходов к другим скриптам, запишем правильную сумму, а потом пусть другие скрипты меняют количество денег, нам это уже не страшно. Второй вариант использования блока, это когда нам нужно выполнить несколько действий очень быстро, так, чтобы игрок не заметил «дергания» в игре, чтобы игра двигалась плавно, например, переместить человека или машину в нужное место, или заменить одного персонажа другим. При работе с блоками никогда не забывайте, что другие скрипты не выполняются, пока вы не закрыли блок! Это одна из наиболее частых ошибок, приводящая к труднонаходимым багам! Используйте в блоках только «зеленые» короткие команды, никогда не пытайтесь вставить «красные».

Ну, вроде всё про супервайзер

Разве что еще раз упомянуть, что понимание этого материала имеет решающее значение при написании хороших, интересных и безглючных скриптов!

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