Скриптинг в SS - Статья 1. Основы. Дверь с ключом.


Скрипты в играх - одно из лучших достижений игроиндустрии. Ведь с ними игроков можно отправлять куда подальше с их просьбами отдать исходники! © Неизвестный

 

 

!!! ВНИМАНИЕ !!! ATTENTION !!!

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

 


Поехали. Что еще за скрипты?


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

 

Начнём с основ. Скрипты в Serious Engine 2, 3, 3.5 и 4 представлены в виде файлов с кодом, написанным на языке Lua. В игру они подключаются через энтити Script. Выглядит она как оранжевый куб и находится в категории Logic Entity List'a.

Script entity

 


Разберемся со свойствами скрипта.


 

Script entity properties

Script - сам Lua файл скрипта. По умолчанию local, т.е. локальный. Это означает, что скрипт сохраняется в файле уровня. Это неправильно, и движок будет вас предупреждать об этом. Обязательно сохраняйте каждый скрипт. Чтобы это сделать нажмите на local, выберите Save as, и уйдите в папку со своим проектом.

Auto run - способ запуска вашего скрипта. По умолчанию установлено On host, что означает - ваш скрипт будет запускать только у сервера. Однако объекты, нуждающиеся в синхронизации, будут синхронизированы у клиентов (например, динамическое создание энтитей). Если же скрипт не нуждается в синхронизации, можно ставить Always. Never убирает возможность выполнения скрипта, делается для тестов (может можно вызывать скрипт, поправьте если что).

Variables - здесь содержатся все переменные, назначенные вами (кроме worldInfo - эта энтитя назначается в каждый скрипт автоматически). Это свойство заполняется автоматически, но при необходимости можно создать свою переменную (например, записать расположение файла). К примеру, захотели мы сохранить расположение звука анализа Нетриксы, нажимаем на желтый плюсик, раскрываем список, в Var name вписываем имя нашей переменной, в Var value заходим в Implementation, выбираем Resource, нажимем на Resource => Browse, выбираем наш звук. В итоге:

Manually set up variable

Spawn flags, Name, Parent, Platforms, ID (SE4 only) - стандартно для всех энтитей, описывать тут не буду.

 


Давайте же наконец писать скрипт!


Придержи коня, сударь!

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

Чтобы написать любой скрипт, необходимо сначала продумать алгоритм (можно и в процессе думать, но я же не только для профессионалов пишу? :P). Итак, игрок пытается открыть дверь. У него не выходит, т.к. у него нет ключа. Проигрывается звук неудачной попытки открытия двери. Игрок может пробовать сколько угодно раз, не выйдет. И вот он подобрал ключ, радостно подходит к двери и она БАЦ! - открывается. Замечательно, браво! Проведем небольшую подготовку.

И дверь, и ключ будут Static model (НЕ Simple), в свойствах которых нужно указать "Game scripting" в параметре "Controlled from script".

Звук, естественно, - Static Sound. В параметрах уберите галочку с Autoplay, а во Flags уберите looping (чтобы не повторялся). В Controlled from script ставим Game scripting. В качестве звука возьмем этот:

Content\SeriousSam3\Sounds\Door\StoneDoorHit_01.wav

С моделькой ключа я особо заморачиваться не стал.

Ну а дверь - просто прямоугольник. К двери также нужно приделать Animated Mover с анимацией открывания. Назовем анимацию "Open" (если хотите узнать, как делать анимации с помощью Animated Mover'a - вам сюда).

 


Ты надоел, скрипт будем писать?


Что-то я  и впрямь затягиваю. Начнем же писать, наконец, чертов скрипт.

Энтити приготовлены, руки тоже, мозг работает. Начнем редактировать скрипт. Для этого сделайте двойной клик по энтите скрипта (либо выделите и нажмите E). Слева откроется окно редактирования.

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

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

Структура цикла while:

while <условие> do
   <тело цикла>
end

Условие - обычно переменная типа boolean (т.е., способная принимать только 2 значения - true или false, т.е. истина или ложь).

Тело цикла - операторы, которые будут повторяться.

В условие вписываем слово true. Это означает, что цикл будет повторяться ВСЕГДА.


Внимание! Цикл, выполняющий повторение без каких-либо задержек будет отвергнут редактором и работать не станет. Во избежание этого можно использовать Wait(Delay(0.05)), что задержит повторение тела цикла на одну двадцатую часть секунды.


Для двери необходимо включить возможность использования. Для этого используется функция EnableUsage(). Вписываем в тело цикла: Door:EnableUsage(). Однако переменная двери еще пуста. Чтобы это исправить, выделите свою дверь в редакторе, зажмите Ctrl+Shift+Alt и перетащите её прямо в редактор скрипта на слово Door. Оно позеленеет - это означает, что переменная является энтитей и успешно назначена.

Дальнейшие действия с дверью нам нужно выполнять только после использования двери. Поэтому после разрешения на использование вписываем Wait(Event(Door.Used)).


Для любой энтити через двоеточие вызываются функции, а через точку - события.



Теперь скрипт остановится, пока вы не используете дверь. Можете протестировать. Дверь используется, но! - ничего не происходит.

Далее необходимо сделать проверку на то, подобран ли ключ. Для этого в самое начало скрипта (еще перед while) Впишите local keyPicked = false. Эта переменная определится как boolean. Мы присвоим ей значение "ложь", т.к. ключ еще не подобран.


local позволяет вводить переменные, существующие только в контексте данного скрипта. Чтобы ввести глобальную переменную, используйте worldGlobals. К примеру, worldGlobals.keyPicked = false



Теперь используем нововведенную переменную для произведения проверки. Для этого используется конструкция if:

if <условие> then
   <тело if>
else
    <тело else>
end

Если условие - истина, то выполняется тело if. Если же ложь, то выполняется тело else. На место условия вписываем слово keyPicked - нашу переменную.

В тело if пишем:

DoorMover:PlayAnimWait("Open")
Door:DisableUsage()
break

Здесь AnimatedMover проигрывает анимацию открытия двери, затем возможность использовать дверь отключается и мы выходим из цикла с помощью break. Все просто.

К DoorMover нужно присвоить AnimatedMover вашей двери. Действуйте по аналогии с самой дверью.


Else может быть заменено на elseif, тогда можно произвести еще одну проверку. Также блок else может отсутствовать вовсе. Вне зависимости от этого, в конструкции if должен быть только один end.


В тело else пишем DoorSound:PlayOnce(). К DoorSound присваиваем наш звук, как это сделали ранее с дверью и мувером.

Конечный код у меня:

First stage of script writing.


Ну, теперь я могу без остановки долбить по двери. Что с ключом делать?


Верно, мы не сделали ничего с ключом. Вернемся в начало.

Впишем строчку Key:EnableUsage(), уже знаете для чего.

Тут я использую приём, зовущийся "многопоточностью". Я запущу ответвление от этого скрипта, чтобы код выполнялся параллельно. Делается это так:

RunAsync(function()
  <тело функции>
end)

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


Конечно, излишне говорить, что использовать это слишком много не стоит. Однако, скажу по секрету, в одном моём скрипте одновременно существует более 14 раздельных потоков, и на моем довольно слабом железе это не влияет на производительность. Но всё-таки. Не стоит.


Вписываем в тело функции:

  Wait(Event(Key.Used))
  Key:Disappear()
  keyPicked = true

Мы ждём, пока игрок использует ключ. После этого моделька исчезает, а переменная keyPicked получает значение "истина", т.к. теперь ключ подобран. 

На всякий случай скажу, - присваиваем слову Key модельку ключа.

Ну и на этом всё, теперь мы имеем полностью рабочую дверь, открывающуюся с помощью ключа. При желании можно добавить также звук открытия.


Также для скачивания доступен пример того, что должно получиться. ДЛЯ SS3!

https://yadi.sk/d/a5rHKqYSxzX2f



Комментарии   

№ 1  |  10.02.2017  |  0  
Вопрос такой: зачем сохранять КАЖДЫЙ скрипт на карте? Мне прочих ресурсов в файлах игры мало?
А так, статья полезная, спасибо!
Ответ Цитата

№ 2  |  13.02.2017  |  0  
а) Синхронизация.
б) Производительность.

Насчёт первого - это мне сказал Соляис пять минут назад :P

Насчёт второго - если не сохраняешь скрипт, он сохраняется в файле уровня => уровень грузится дольше и сам по себе будет больше тормозить.
Плюс скрипты бывают многоразовыми (например, открытие двери по нажатию на кнопку). Если просто копировать его, как локальный, он будет съедать еще больше. А так ты просто указываешь в новой энтити скрипта уже сохранённый файл, назначая переменными другую дверь и другую кнопку.
__________

Вообще, в SE2+ лучше сохранять ВСЁ, что помечено как local. Имеется в виду - модели, меши, скрипты, анимсеты, параметры в rsc. Ну, всякий мусор вроде Canvas Texture для Shader Modifier лучше наоборот оставить.
Ответ Цитата

№ 3  |  19.02.2017  |  0  
"Многоразовый"..."Открытие двери"... Ты прям мою ситуацию описал. И я скрипты для каждой двери писал по новой. Дурак, не правда-ли?
Ответ Цитата

№ 4  |  21.02.2017  |  0  
Хе-хе, я сначала тоже так делал, пока не заметил случайно, что скриптов в оригинальных картах сохранено намного меньше, чем у меня)
Ответ Цитата

Оставьте комментарий

Мини-профиль

Гость

Вы в группе: Гости
Ваш IP: 54.196.53.39

Информация

Прочее

Категории раздела

Croteam [3]
Материалы по студии разработчика игр CroTeam.
Интервью с разработчиками [9]
Интервью с разработчиками, а также их издателями.
Serious Sam 1 [10]
Статьи о Serious Sam 1
Serious Sam 2 [6]
Статьи о Serious Sam 2
Serious Sam HD [5]
Статьи о HD-серии, ремейков классических версий Сэма.
Serious Sam 3: BFE [9]
Статьи о Serious Sam 3: BFE
Уроки по Serious Editor 1 [54]
Уроки по Serious Editor 2 [2]
Самое серьёзное редактирование, на русском!
Уроки по Serious Editor 3 [33]
Уроки по работе с редактором.
Serious Engine [6]
Описание возможностей всех движков компании Croteam
Разное [25]
Всё что не подошло не под одну из вышеупомянутых категорий.
Serious Sam: Revolution [1]
Материалы по SS: Revolution, серьёзном обновлении классических Крутых Сэмов.
Serious Sam 1.05/1.07 SDK [10]
SDK - набор исходников для Serious Sam: The Second Encounter 1.05/1.07.

Голосование

С какой части Serious Sam началось ваше первое знакомство с серией?
1. Serious Sam: The First Encounter (2001)
2. Serious Sam: The Second Encounter (2002)
3. Serious Sam 2 (2005)
4. Serious Sam 3: BFE
5. Serious Sam HD: The First Encounter (2009)
6. Serious Sam HD: The Second Encounter (2010)
7. Serious Sam: Next Encounter (2004)
8. Serious Sam: Xbox (2002)
9. Serious Sam: Kamikaze Attack! (2011)
10. Serious Sam: Advance (2004)
11. Serious Sam: Double D (2011)
12. Serious Sam: The Random Encounter (2011)

Статистика



На сайте: 16
Гостей: 14
Пользователей: 2
BrandonWef, nesterdron