скрипты что это в играх

Скрипты что это в играх

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

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

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

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

Поскольку моей целью было как можно быстрее предоставить вам работающий скриптовый движок, я выбрал использование второго типа скриптовой системы. Эта система, которую я назвал Mad Lib Scripting, работает используя набор предопределенных команд, называемых действия (actions), с каждым из которых связана игровая функция. Возьмем, для примера, действия из таблицы 10.1 — у каждого действия есть конкретная выполняемая функция.

Таблица 10.1. Примеры команд действий

ДействиеФункция
PrintПечатает строку текста на экране.
EndЗавершает выполнение скрипта.
Move CharacterПеремещает указанный персонаж в заданном направлении.
Play SoundВоспроизводит указанный звуковой эффект.

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

Для примера скажем, что действию Play Sound соответствует номер 4, и действие требует единственного параметра — номера воспроизводимого звука. В скрипте вам потребуется сохранить только два числа: одно для действия, и одно, представляющее звук. Использование чисел для представления действий (вместо текста) делает обработку скриптов такого типа быстрой и простой.

Источник

Игровое программирование. Уроки скриптописания

Для многих начинающих игростроевцев, которые уже собирают свою команду, чтобы слепить на коленке очередной шедевр, программирование часто видится жутким монстром, с которым непонятно как бороться. Вроде и в 3D уже рисовать умеют, и в Photoshop кисточкой сноровисто работают, и другие полезные программы неплохо знают. Но как только дело доходит до кода, начинается паника и неразбериха: “ Кто спрограммирует? Кто напишет заветные строчки? А если и напишет, то как в них потом разобраться?! ”.

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

Установка среды разработки

Классы игры и иерархия

Распаковка игровых скриптов

Настройка среды разработки

В ООП существуют три основных принципа, на которых строятся практически все логические манипуляции с объектами.

Инкапсуляция — объединение внутри объекта данных с методами для их обработки. Например, если рассматривается класс “Лампочка”, то у него должны быть методы “включить свет” и “выключить свет”.

Наследование — создание класса объектов на основе уже существующего класса. При этом создаваемый класс будет не только содержать все данные и методы базового класса, но и обладать своими собственными. Методы базового класса могут быть переопределены. Примеры наследования и переопределения: если класс “Пегас” наследуется от класса “Лошадь”, то у первого появляется новое свойство — “крылья” и соответствующий метод “махать крыльями”. Все остальное у этих двух классов одинаковое. Если мы рассмотрим класс “Русалка”, основанный на классе “Человек”, то в данном случае будет иметь место переопределение свойства “ноги” на “рыбий хвост”, а метод “двигаться” будет вместо движения ног отвечать за перемещение хвоста.

Полиморфизм — что это такое, проще всего рассмотреть на конкретном примере. Рассмотрим два класса объектов — “Пегас” и “Лошадь”. Полиморфизм заключается в том, что мы можем рассматривать любого пегаса как лошадь и, например, у обоих объектов выполнять метод “кушать траву” или “бежать галопом”.

Многие начинающие программисты не различают понятия “класс” и “объект”. Но при этом эти два понятия различаются примерно так же, как и, скажем, чертеж устройства и готовое устройство в магазине. В жизни их спутать трудно.

Создание проекта

К сожалению, в UDE кнопка “Создать новый проект” отсутствует. Поэтому создаем в корневой папке UT2004 файл CreateNewClass.bat с командами:

echo class %pkg% extends //base class>> %pkg%\Classes\%pkg%.uc

Значение переменной pkg — это имя нашего проекта (в данном случае — Megakiller ). Остальные строки генерируют “пустой” скрипт.

Идея модификации

Перед изучением нижеследующей информации настоятельно рекомендуется изучить текстовый блок “ Анатомия Unreal-класса ”.

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

Класс оружия

Рис. 1. Диалог создания дерева классов и архивов.

Класс альтернативной стрельбы

Рис. 2. Окна с деревом классов и списком архивов.

В начале файла объявляем несколько новых свойств для объектов класса ( строки 2-5 ): визуальный тип взрыва ( ExplosionClass ), визуальный тип следа от взрыва, например на стенах ( ExplosionDecalClass ). Тип луча при альтернативной стрельбе ( BeamEffectClass ) и радиус поражения при взрыве ( DamageRadius ).

Рис. 3. Диалог создания подкласса.

Классы повреждения

Рис. 4. Окно компиляции.

Класс игрового мутатора

— просто лежать на карте ( строка 15 ). Тут нам помогает класс WeaponPickup ( строка 15 ). Подмена осуществляется функцией ReplaceWith ( строка 19 ).

Рис. 5. Сообщение об ошибке и справка.

Дуэли на «Мегакиллерах» иногда превращают обычный бой в феерическое зрелище.

Чернокожий стрелок пытается безуспешно подстрелить «античную» мадам.

Местные леди способны просто-таки заряжать вас энергией!

Каждый Чебурашка мечтает о большой пушке!

Компиляция и тестирование

Для того чтобы вы сразу могли оценить действие мутатора и поиграть в него, мы выкладываем полную версию “Мегакиллера” на наш диск.

Принципы объектно-ориентированного программирования

Класс игры имеет унифицированную архитектуру. Структура файла следующая.

— Заголовок, содержащий объявление класса:

class ClassName extends BaseClass config(user); где ClassName — название нашего класса, BaseClass — базовый класс, на основе которого создается новый класс, config(user) — пример параметра в объявлении класса — указывает, что используются конфигурационные параметры из файла User.ini. Все игровые классы имеют в качестве родительского класс Object или любой из его классов-потомков. Лексемы class и extends являются зарезервированными обязательными атрибутами объявления игрового класса. Важно запомнить, что корректным является только тот uc-файл, имя которого совпадает с названием объявленного в нем класса. И в одном uc-файле должен быть описан только один класс.

— Объявления новых переменных (свойств класса) в следующем формате:

PropertyName; или var() SimpleType PropertyName; где PropertyClass — название класса создаваемого свойства, SimpleType — элементарный тип, такой как byte (байтовое значение от 0 до 255), int (знаковый целый тип), bool (логический тип), float (знаковый вещественный тип), string (символьная строка) и т.д. (полный список элементарных типов можно посмотреть в справке UDE), PropertyName — имя нового свойства.

— Объявления новых методов или переопределение унаследованных от базового класса имеют следующий вид:

— Задание параметров (свойств) по умолчанию класса:

defaultproperties где defaultproperties — лексема, указывающая начало блока свойств, Variable1Name — название свойства, представляющего собой некоторый другой объект класса ClassName, содержащегося в u-файле с именем Package. Параметр Variable2Name имеет элементарный тип, поэтому и присваиваемое значение Variable2Value должно иметь тот же тип. Символ «=» означает операцию присвоения значения справа переменной слева. Фигурные скобки обособляют в коде блок присвоений.

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

Источник

Что такое скрипты и с чем их едят — Lua & C++

Добрый день, Хабрахабр!
Решил написать этот топик на тему скриптов

скрипты что это в играх. image loader. скрипты что это в играх фото. скрипты что это в играх-image loader. картинка скрипты что это в играх. картинка image loader. При создании игры скрипты используются во многом так же, как кинорежиссер использует сценарий — для контроля каждого аспекта вашего «произведения». Игровые скрипты подобны программному коду, который вы пишете, когда создаете игру, за исключением того, что скрипты являются внешними по отношению к игровому движку. Поскольку они внешние, вы можете быстро изменить скрипт не компилируя заново весь игровой движок. Вообразите себе проект, в котором больше миллиона строк кода, и вам надо компилировать весь этот проект заново только для того, чтобы изменить одну строку в диалоге!

Что нужно знать?

Но есть способ, на голову выше — использование скриптов.

Решение проблемы

«Окей, для таких дел хватает обычного файла с описанием характеристиков игрока. Но что делать, если в бурно развивающемся проекте почти каждый день приходится немножко изменять логику главного игрока, и, следовательно, много раз компилировать проект?»
Хороший вопрос. В этом случае нам на помощь приходят скрипты, держащие именно логику игрока со всеми характеристиками либо какой-либо другой части игры.
Естественно, удобнее всего держать, логику игрока в виде кода какого-нибудь языка программирования.
Первая мысль — написать свой интерпретатор своего скриптового языка, выкидывается из мозга через несколько секунд. Логика игрока определенно не стоит таких жутких затрат.
К счастью, есть специальные библиотеки скриптовых языков для С++, которые принимают на вход текстовый файл и выполняют его.

Об одном таком скриптовом языке Lua пойдет речь.

Как это работает?

Прежде чем начать, важно понимать, как работает скриптовый язык. Дело в том, что в скриптовых языках есть очень мало функций, при наличии конструкций for, while, if, прочих.
В основном это функции вывода текста в консоль, математические функции и функции для работы с файлами.
Как же тогда можно управлять игроком через скрипты?

Мы в С++-программе делаем какие-либо функции, «регистрируем» их под каким-нибудь именем в скрипте и вызываем в скрипте. То есть если мы зарегистрировали функцию SetPos(x,y) для определения позиции игрока в С++-программе, то, встретив эту функцию в скрипте, «интерпретатор» из библиотеки скриптового языка вызывает эту функцию в С++-программе, естественно, с передачей всех методов.
Удивительно, да? 🙂

UPD: Внимание! Один юзер обратился мне с мейлом, что, когда я заливал код, я не полностью устранил все ошибки — habrahabr.ru/post/196272/#comment_6850016
В коде с позволения хабра проникли жучки
Замените участки кода вроде

И еще вместо lua_CFunction проскакивает lua_cfunction
Спасибо!

Я готов!

Когда вы поняли преимущества скриптовых языков программирования, самое время начать работать!
Скачайте из репозитория на гитхабе (низ топика) lib’у и includ’ы Lua, либо возмите их на официальном сайте.

Создаем консольный проект либо Win32 (это неважно) в Visual Studio (у меня стоит версия 2012)

Заходим в Проект->Свойства->Свойства конфигурации->Каталоги VC++ и в «каталоги включения» и «каталоги библиотек» добавьте папку Include и Lib из репозитория соответственно.

Теперь создаем файл main.cpp, пишем в нем:

Как вы догадались, у меня консольное приложение.

Теперь переходим к кодингу

Обещаю, что буду тщательно объяснять каждый момент

У нас за скрипты будет отвечать класс Script. Я буду объявлять и одновременно реализовывать функции в Script.h/.cpp
Создаем Script.cpp и пишем в нем

Создаем Script.h и пишем в нем

После 2 строчки и перед #endif мы определяем класс скриптов
Этот код пишется для предотвращения взаимного включения файлов. Допустим, что файл Game.h подключает Script.h, а Script.h подключает Game.h — непорядок! А с таким кодом включение выполняется только 1 раз

Теперь пишем внутри этого кода вот это

Первая строчка подключает сам lua.lib из архива.
Для чего нужен extern «C»? Дело в том, что lua написан на С и поэтому такой код необходим для подключения библиотек.

Дальше идет подключение хорошо известных многим файлов для работы с консолью

Теперь приступим к определению класса

Самый главный объект библиотеки Lua для C++ — lua_State, он необходим для выполнения скриптов

Дальше идут публичные функции

Эта функция инициализирует lua_State

Его определение в Script.cpp

Первой строчкой мы инициализируем наш lua_State.
Потом мы объявляем список «подключенных библиотек». Дело в том, что в «чистом» виде в луа есть только функция print(). Для математических и прочих функций требуется подключать специальные библиотеки и потом вызывать их как math.foo, base.foo, io.foo. Для подключения других библиотек добавьте в lualibs, например, <«math», luaopen_math>. Все названия библиотек начинаются с luaopen_. в конце lialibs должен стоять

Просто используем lua_close()

А эта функция выполняет файл. На вход она принимает название файла, например, «C:\\script.lua».
Почему она возвращает int? Просто некоторые скрипты могут содержать return, прерывая работу скрипта и возвращая какое-нибудь значение.

Как вы видите, я выполняю скрипт и возвращаю int. Но возращать функция может не только int, но еще и bool и char*, просто я всегда возвращаю числа (lua_toboolean, lua_tostring)

Теперь мы сделаем функцию, регистрирующую константы (числа, строки, функции)

Мы действуем через шаблоны. Пример вызова функции:
Ее определение

Для каждого возможного значения class T мы определяем свои действия.
*Капитан* последнее определение — регистрация функции
Функции, годные для регистрации, выглядят так:

Где n — количество возвращаемых значений. Если n = 2, то в Луа можно сделать так:

Читайте мануалы по Луа, если были удивлены тем, что одна функция возвращает несколько значений 🙂

Следующая функция создает таблицу для Луа. Если непонятно, что это значит, то тамошная таблица все равно что массив

Следующая функция регистрирует элемент в таблице.

Если вы не знаете Lua, вы, наверное, удивлены тем, что в один массив помещается столько типов? 🙂
На самом деле в элементе таблицы может содержаться еще и таблица, я так никогда не делаю.

Наконец, заполненную таблицу нужно зарегистрировать

Ничего особенного нет

Следующие функции предназначены в основном только для функций типа int foo(lua_State*), которые нужны для регистрации в Луа.

Первая из них — получает количество аргументов

Эта функция нужна, например, для функции Write(), куда можно запихать сколь угодно аргументов, а можно и ни одного
Подобную функцию мы реализуем позже

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

Можно получить все типы, описывавшиеся ранее, кроме таблиц и функций
index — это номер аргумента. И первый аргумент начинается с 1.

Наконец, последняя функция, которая возвращает значение в скрипт

Боевой код

Пора что-нибудь сделать!
Изменяем main.cpp

Компилируем. Теперь можно приступить к тестированию нашего класса

Помните, я обещал сделать функцию Write? 🙂
Видоизменяем main.cpp

А в папке с проектом создаем файл script.lua

скрипты что это в играх. image loader. скрипты что это в играх фото. скрипты что это в играх-image loader. картинка скрипты что это в играх. картинка image loader. При создании игры скрипты используются во многом так же, как кинорежиссер использует сценарий — для контроля каждого аспекта вашего «произведения». Игровые скрипты подобны программному коду, который вы пишете, когда создаете игру, за исключением того, что скрипты являются внешними по отношению к игровому движку. Поскольку они внешние, вы можете быстро изменить скрипт не компилируя заново весь игровой движок. Вообразите себе проект, в котором больше миллиона строк кода, и вам надо компилировать весь этот проект заново только для того, чтобы изменить одну строку в диалоге!

Компилируем и запускаем проект.

скрипты что это в играх. image loader. скрипты что это в играх фото. скрипты что это в играх-image loader. картинка скрипты что это в играх. картинка image loader. При создании игры скрипты используются во многом так же, как кинорежиссер использует сценарий — для контроля каждого аспекта вашего «произведения». Игровые скрипты подобны программному коду, который вы пишете, когда создаете игру, за исключением того, что скрипты являются внешними по отношению к игровому движку. Поскольку они внешние, вы можете быстро изменить скрипт не компилируя заново весь игровой движок. Вообразите себе проект, в котором больше миллиона строк кода, и вам надо компилировать весь этот проект заново только для того, чтобы изменить одну строку в диалоге!

Теперь изменяем script.lua

Теперь программа будет выводить по 2 строки («\n» — создание новой строки), ждать нажатия Enter и снова выводить строки.

скрипты что это в играх. image loader. скрипты что это в играх фото. скрипты что это в играх-image loader. картинка скрипты что это в играх. картинка image loader. При создании игры скрипты используются во многом так же, как кинорежиссер использует сценарий — для контроля каждого аспекта вашего «произведения». Игровые скрипты подобны программному коду, который вы пишете, когда создаете игру, за исключением того, что скрипты являются внешними по отношению к игровому движку. Поскольку они внешние, вы можете быстро изменить скрипт не компилируя заново весь игровой движок. Вообразите себе проект, в котором больше миллиона строк кода, и вам надо компилировать весь этот проект заново только для того, чтобы изменить одну строку в диалоге!

Экспериментируйте со скриптами!

Вот пример main.cpp с функциями и пример script.lua

Полезные советы
Вопросы и ответы

Источник

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

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

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

скрипты что это в играх. image loader. скрипты что это в играх фото. скрипты что это в играх-image loader. картинка скрипты что это в играх. картинка image loader. При создании игры скрипты используются во многом так же, как кинорежиссер использует сценарий — для контроля каждого аспекта вашего «произведения». Игровые скрипты подобны программному коду, который вы пишете, когда создаете игру, за исключением того, что скрипты являются внешними по отношению к игровому движку. Поскольку они внешние, вы можете быстро изменить скрипт не компилируя заново весь игровой движок. Вообразите себе проект, в котором больше миллиона строк кода, и вам надо компилировать весь этот проект заново только для того, чтобы изменить одну строку в диалоге!

То есть в первом случае пользователи через череду однотипных действий приходят к конечному результату и уходят на следующий круг. Игра же — это рандомный хаос в центре которого находится игровой мир, на который игроки постоянно оказывают воздействие, меняют внутриигровые данные, оказывая непосредственное влияние как на себя, так и на других игроков. Также игроки могут общаться, объединяться в гильдии и рубиться PvP.

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

Проблема релевантных данных

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

Одна из главных проблем при разработке скриптов для игры — это сложность самого слежение (трекинга) изменений, которые произошли до данного конкретного момента, перед выполнением команды. Информация об изменённом состоянии объектов, ресурсов, юнитов и пр. может прийти в любой момент, даже после выполнения не связанных с конкретными данными действий. Если пропустить данное обновление, то виртуальный пользователь (VU, тред в Jmeter) будет рассинхронизован с игрой и начнет генерить ошибки аля “недостаточно ресурсов” или «нет места на карте» и превращать нагрузочный тест в нечто бесполезное. Конечно всегда есть вероятность того, что всё же скрипт выдаст что-то типа “нельзя атаковать союзника”, если он секунду назад стал таковым, но то же самое произойдет и в настоящем клиенте.

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

Forge of Empires

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

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

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

Само незанятое поле и объекты разбиты на квадраты, в зависимости от размера приходится считаться с размером самого здания и свободного места на карте. Здания делятся на типы: жилые, производственные, военные, культурные, дороги и прочее. Разные здания производят разные ресурсы: жилые — население и деньги, производственные — товары и ресурсы, культурные — счастье и так далее. При постройке каждого здания необходимо учитывать те же самые ресурсы и если их не хватает нужно либо ждать, либо, например, построить новый дом, чтобы восполнить население. Чувствуете куда я клоню? Это не бухгалтерские проводки эмулировать 🙂

Строительство

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

После нескольких часов раздумий пришла идея простого алгоритма, я назвал его “строительство слоями”. Суть его в следующем. Как вы могли заметить на скриншоте сверху, ГЗ прижато к краю карты за которым уже ничего строить нельзя и это сыграло на руку. Каждый VU после логина первым делом строит дорогу по контуру карты и самого главного здания, а уже потом строит необходимые здания, возле этой дороги, пока есть место. Таким образом все здания построенные у дороги будут связаны с ГЗ. Далее мы строим следующий “слой” дороги уже по контуру построенный зданий. Таким образом, первоначальную дорогу мы строим, исходя из условия: например если слева граница карты, справа — пусто, а сверху и снизу от проверяемого квадрата пусто или что-то есть, то мы вероятно можем построить дорогу.

Примерно так (зеленый квадрат — ГЗ, жёлтый — дорога, черный — какое-либо здание):

скрипты что это в играх. image loader. скрипты что это в играх фото. скрипты что это в играх-image loader. картинка скрипты что это в играх. картинка image loader. При создании игры скрипты используются во многом так же, как кинорежиссер использует сценарий — для контроля каждого аспекта вашего «произведения». Игровые скрипты подобны программному коду, который вы пишете, когда создаете игру, за исключением того, что скрипты являются внешними по отношению к игровому движку. Поскольку они внешние, вы можете быстро изменить скрипт не компилируя заново весь игровой движок. Вообразите себе проект, в котором больше миллиона строк кода, и вам надо компилировать весь этот проект заново только для того, чтобы изменить одну строку в диалоге!

Поехали

Так как данная игра общается с клиентом исключительно посредством http с JSON`ами, я использую в Jmeter дополнительную библиотеку org.json для работы и парсинга запросов/ответов в post- и pre- процессорах.

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

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

Первый POST-запрос StaticData_getData возвращает огромный JSON весом в 1-2 мегабайта. Распарсим его, создадим структуру, например HashMap и заполним её объектами Entity с ключами id, чтобы впоследствии обращаться к этому хэш-мапу за информацией о каждом конкретном здании:

Теперь каждый виртуальный пользователь знает всю необходимую информацию о зданиях. Далее необходимо “запомнить” территорию, её размеры и текущее расположение зданий в самом городе. Я использовал также HashMap, в котором в качестве ключей используются объекты класса java.awt.Point с координатами X, Y, а в качестве значений String с названием типа здания в данной координате.

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

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

Строим

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

Добавляем в HTTP Sampler jsr223 pre-processor и формируем запрос. Перебираем каждую квадратик, ищем пустой и тот, которого окружает хоть один (из 8) занятый другим объектом (включая границу) квадрат. Таким образом, мы “обведём” дорогой любой объект, включая границу территории (здесь есть большой простор для оптимизаций, надеюсь кто-нибудь подскажет более лучший алгоритм):

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

скрипты что это в играх. image loader. скрипты что это в играх фото. скрипты что это в играх-image loader. картинка скрипты что это в играх. картинка image loader. При создании игры скрипты используются во многом так же, как кинорежиссер использует сценарий — для контроля каждого аспекта вашего «произведения». Игровые скрипты подобны программному коду, который вы пишете, когда создаете игру, за исключением того, что скрипты являются внешними по отношению к игровому движку. Поскольку они внешние, вы можете быстро изменить скрипт не компилируя заново весь игровой движок. Вообразите себе проект, в котором больше миллиона строк кода, и вам надо компилировать весь этот проект заново только для того, чтобы изменить одну строку в диалоге!

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

На самом верхнем уровне тест-плана Jmeter добавляем Post-processor который, будет реагировать на каждый входящий респонс от игры, парсить его и обновлять объекты, так как нам необходимо трекать изменение ресурсов, а также обновлять виртуальную карту новыми зданиями:

Как итого после одного 12-часового нагрузочного теста можно увидеть реально построенный город с различными зданиями, которые соединены с главным зданием, а значит вполне себе неплохо функционируют:
скрипты что это в играх. image loader. скрипты что это в играх фото. скрипты что это в играх-image loader. картинка скрипты что это в играх. картинка image loader. При создании игры скрипты используются во многом так же, как кинорежиссер использует сценарий — для контроля каждого аспекта вашего «произведения». Игровые скрипты подобны программному коду, который вы пишете, когда создаете игру, за исключением того, что скрипты являются внешними по отношению к игровому движку. Поскольку они внешние, вы можете быстро изменить скрипт не компилируя заново весь игровой движок. Вообразите себе проект, в котором больше миллиона строк кода, и вам надо компилировать весь этот проект заново только для того, чтобы изменить одну строку в диалоге!

Спасибо за внимание, я решил не сваливать всё в кучу и разбить тему на несколько частей. Следующая часть будет посвящена решению той же самой проблемы, но в более жёстких условиях, когда клиент игры использует HTTP-протокол с protobuf, а обновления получает через web-сокет с STOMP.

Оставлю ссылку на наш гитхаб, может найдете что-то интересное.

Источник

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Анатомия Unreal-класса