Глава 1. Локальные и глобальные переменные. Читатель, если ты знаком с переменными, можешь пропустить этот абзац.
Ни один картостроитель, который хочет, чтобы в его карту играли, не может обойтись без переменных. Но что же это такое? В JASS, как и в любом языке программирования, есть переменные. Переменные, это ячейки, в которые можно записать ссылки на определённые объекты. Но нельзя путать сам ОБЪЕКТ и ССЫЛКУ на него. Это совершенно разные вещи! Например, у объекта есть куча разных свойств (они зависят от самого объекта), а у ссылки этих свойств нет. Переменные жизненно необходимы при создании карты. Самый простой пример. В начале игры мы триггерно (т.е. с помощью триггеров прямо в игре) создаём юнита, а потом в конце игры, нам требуется удалить этого юнита. Как же это сделать, если после создания этого юнита, мы насоздовали кучу новых? Да, записать его в переменную сразу после создания. И тогда его можно будет удалить в любой момент игры. Но в переменную нельзя помещать всё подряд. При создании переменной, нужно указать тип данных, на которые будет ссылаться эта переменная. Приведу некоторые типы из ВЕ:
Code |
Юнит (Unit) Целое число (Integer) Строка (String) Реальная (Real) Точка (Location) Спецэффект (Effect) Триггер (Trigger) |
Это лишь некоторые типы. Остальные можно увидеть в редакторе, во время создания переменной. В ВЕ есть такие типы, которых нет больше нигде (например - триггер).
Начнём с глобальных переменных. В редакторе WarCraft реализованы лишь глобальные переменные. Что это такое и чем они отличаются от обычных переменных? Это такие же переменные, но к ним добавлена приставка глобальные. Почему? Объясню на примере. Если мы триггерно создадим юнита и запишем его в глобальную переменную, мы сможем удалить его из любого триггера. Т.е. к этим переменным можно обращаться из любого триггера нашей карты. Такие переменные можно создать в редакторе триггеров. Но кроме глобальных переменных существуют локальные переменные. От глобальных они отличаются тем, что могут использоваться только в пределах одной функции (о функциях читай в главе второй). Той, в которой они были созданы. Такие переменные создаются командой:
Например:
local означает, что мы создаём локальную переменную, о типах ты уже знаешь, а имя трудностей вызывать не должно. В переменную, как уже было сказано ранее, можно записывать параметры. Представим себе такую переменную:
Локальная переменная типа целое число с названием
int.
Не забывай, что в JASS тщательно соблюдается регистр (т.е. большие буквы должны быть большими, а маленькие - маленькими). Как же записать в локальную переменную число? А просто! Для этого есть простой оператор
"set". Выглядеть всё это будет так:
Вместо 32 можно записать всё, что угодно (только чтобы это "всё, что угодно" было целым числом).
Самое удобное в локальных переменных то, что при каждом выполнении функции создаются новые переменные, никак не связанные со старыми.
Локальные переменные обязательно должны объявляться в самом начале функции или триггера.
О преимуществах таких переменных мы поговорим позже...
Глава 2: Функции в JASS. Их общий вид. Триггеры.
Читатель, если ты хочешь освоить JASS, то наверняка уже знаешь, что такое редактор триггеров в WarCraft'е и как его использовать. Триггеры в редакторе - не что иное, как переменные JASS, которые связывают события, условия и действия. Что же такое функция? Функция, это код, или точнее часть нашего кода. Эта часть имеет свои границы (начало и конец). В пределах этих границ мы можем вписывать свои действия. Как же она выглядит?
Code |
function name takes nothing returns nothing //локальные переменные //наш код endfunction |
Теперь разберём каждое слово.
1)
function - начало функции. Оно всегда должно быть одинаковым. Естествено изменять, удалять или выполнять другие аналогичные действия с этим словом нельзя.
2)
name - имя нашей функции. Имя можно придумать любое. Законный вопрос, А зачем функции имя? Функция содержит в себе те действия, которые должна выполнить. Но пока не ВЫЗВАТЬ эту функцию, она останется бесполезным кодом в дебрях нашей карты. Как же вызывать функцию? Для того, чтобы вызвать нашу функцию, нужна небольшая команда: call name(). Думаю, ничего непонятного в этой команде нет, кроме скобок. Но про них я напишу чуть позже (так как они тесно связаны с пониманием функции).
3)
takes - те параметры, что функция БЕРЁТ. Например, у нас есть две функции и нам понадобилось из первой функции передать ссылку на юнита во вторую. Что же делать? Создавать лишнюю глобальную переменную? Вот для этого в функцию можно передать параметр. Как это сделать я опять же расскажу позже.
4)
nothing - означает, что мы ничего не передаём.
5)
returns - те параметры, которые функция ВОЗВРАЩАЕТ. Функция может сделать какое-то вычисление (или проверку и т.д.) и вернуть результат туда, откуда фнкцию вызвали. Возвращают параметры действием return(наш параметр). Можно вернуть переменную, но тогда это будет выглядеть так: return переменная.
А теперь объединим пункты со 2 по 5. Функция может брать параметры. Но как же указать ей параметры? Для ответа на этот вопрос, вспомним, как вызывать функцию. Верно, командой
call name(). Но куда же здесь вводить параметры? Ответ простой - в скобки. Но, естественно, в скобки нельзя вводить всё подряд. Для начала, давай посмотрим на функцию, которая берёт параметр типа целое число (
Integer).
Code |
function name takes integer int returns nothing endfunction |
Читатель, как ты заметил, мы вместо
nothing (перед
takes) поставили
integer int. Это значит, что в нашу функцию будет передаваться параметр - целое число. А вызываться эта функция будет так:
В скобках я передал параметр 15 типа целое число. Естественно, вместо этого параметра можно было передать любое другое число. Функция может брать сколько угодно параметров. Это будет выглядеть так:
Code |
function name takes integer int, тип имя, тип имя returns nothing endfunction |
Тогда в скобках, в команде вызова функции, нужно передавать данные в ТОМ ЖЕ порядке и ТОГО ЖЕ типа, что функция берёт. Если функция берёт строку, нельзя передать ей юнита. А вот имя этого юнита можно.
Теперь о том, как использовать эти переданные данные. Представьте, что наши переданные параметры - переменные с собственным именем. Как же их использовать? Да так же, как и локальные переменны, только новое значение присваивать нельзя.
Что же такое обычные триггеры в редакторе триггеров? Это функции JASS, которые графически оформлены, это я уже говорил. Но теперь выдели пустой триггер и нажми Правка --- Конвертировать в текст. Ты увидишь что-то, вроде этого:
Code |
function Trig_____________________________________001_Actions takes nothing returns nothing endfunction //=========================================================================== function InitTrig_____________________________________001 takes nothing returns nothing set gg_trg_____________________________________001 = CreateTrigger( ) call TriggerAddAction( gg_trg_____________________________________001, function Trig_____________________________________001_Actions ) endfunction |
Крайне неудобно работать с таким кодом, верно? Мой триггер назывался Безымянный триггер 001. В коде он называется "
_____________________________________001". Редактор, прежде чем начать выполнение твоих триггеров, переводит их в JASS. И как ты заметил, переводит крайне не удобно. Давай разберём всё это.
Code |
function Trig_____________________________________001_Actions takes nothing returns nothing endfunction |
Это - действия нашего триггера. Так как триггер был пустой, функция пустая.
Code |
function InitTrig_____________________________________001 takes nothing returns nothing set gg_trg_____________________________________001 = CreateTrigger( ) call TriggerAddAction( gg_trg_____________________________________001, function Trig_____________________________________001_Actions ) endfunction |
Это - функция инициализации триггера. Она создаёт триггер и указывает ту функцию, которая содержит его действия. Теперь, ты знаешь, как выглядят твои триггеры на самом деле и, если тебе нужно узнать, как сделать то или иное действие, ты можешь сделать это действие в редакторе, а потом конвертировать.
Глава 3. Массивы переменных. Читатель, представь себе ситуацию, когда ты создаёшь триггерно кучу точек (например 360). А потом надо все эти точки удалить. Что ты сделаешь? Создашь 360 переменных типа точка? Нет, не пойдёт. Можно было бы скомпоновать все 360 переменных в одну строчку... А почему нельзя? Для этого существуют массивы переменных. Наверняка, ты не раз видел галочку массив, при создании переменной. Но если не знаешь, что она означает, стараешься не обращать внимания. Что же такое массив переменных? Это переменные, которые собраны в одну строчку. Эти переменные проиндексованы (т.е. у каждой есть свой номер) и каждую из них можно вызвать. В каждую такую переменную можно записывать любое значение нужного типа. Такие переменные просто незаменимы, например, при создании триггерных спеллов (заклинаний, которые реализованы на триггерах). Индекс таких переменных записывается в квадратные скобки:
Такие переменные очень хорошо могут сочетаться с циклами (о циклах ты узнаешь в следующей главе).
Но массивы могут быть локальными. Как же их создавать? Читатель, ты помнишь, как создавать локальные переменные? Верно:
А теперь, после типа переменной, добавь слово array. Это будет выглядеть так:
Что бы записать значение с одну из переменных, нужно добавить к имени индекс:
Code |
set имя[индекс] = значение |
В JASS числа начинаются с нуля, а не с единицы. Так, игроки отмечаются цифрами не с 1 до 12, а с 0 до 11. Значит, и индекс переменных можно начинать с нуля.
________________________________________
Глава 4. Блок [/]if/then/else[/i] и циклы.
Читатель, в редакторе триггеров ты неоднократно видел условие. Что же это такое? Представим себе триггер:
Code |
Событие: Юнит входит в регион Действие: Убить вошедшего юнита |
А что, если убить надо определённого юнита? Тогда нам понадобится условие и триггер будет выглядеть так:
Code |
Событие: Юнит входит в регион Условие: Вошедший юнит = нужный юнит Действие: Убить вошедшего юнита |
Теперь триггер убьёт лишь определённого юнита. Но может возникнуть ситуация, когда нужно что то проверить прямо во время выпонения триггера. Для этого есть блок if/then/else (Если/Тогда/Иначе). А какже выглядит это блок на JASS?
Code |
if наше условие then действие else действие endif (конец блока) |
Каждый открытый блок нужно закрывать, иначе с вероятностью 99% редактор вылетит, не сохранив вашу карту. Согласитесь, неприятно.
Чтобы проверить свой код, без непрятностей, скачайте себе внешний JASS редактор. Например программу CoolerJASS. Переходим к циклам.
У тебя наверняка были ситуации, когда одно и то же действие ты повторяешь много раз подряд. Например, ситуация, когда нужно создать разных крипов (random creeps) и заставить их куда то идти. Не создавать же два дествия 20 раз подряд? Но давай рассмотрим циклы. Цикл, это блок, который будет повторять указанные действия, пока не выполнится условие выхода из цикла. Что может быть условием выхода цикла? Чаще всего в качестве таких сравнений используются сравнение двух чисел (например выйти, когда переменная int будет больше 5). Вот, как выглядит цикл в JASS:
Code |
local integer int = 1 (создаём локальную переменную, которая будет отвечать за выход из цикла) loop (начало цикла, это словообязательно) exitwhen (условие выхода (выйти, когда...)) int > 5 (...наша переменная для выхода будет больше 5. Т.е. когда цикл выполнится 5 раз, он закончится) Действия, которые должны повторяться set int = int + 1 (чтобы условие выхода сработало, переменная int должна увеличиваться на 1 при каждом выполнении цикла) endloop (конец цикла) |
Цикл, выполняется как одно действие. Т.е. действия, которые идут за циклом, не будут выполняться, пока не закончится цикл.
Оставляйте комменты.
(Если их не будет, я падумаю что статья хорошая и возгордюсь! =)