Сейчас 11:59:03 Четверг, 25 апреля, 2024 год
[ x ] Главная ⇒ Форум ⇐ RSS Файлы Cтатьи Картинки В о й т и   или   з а р е г и с т р и р о в а т ь с я


[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Модератор форума: PUVer, SirNikolas, Ty3uK  
Форум о Warcraft 3 » Раздел для картостроителей » GUI / Jass » [СТАТЬЯ] Ликбез для начинающих
[СТАТЬЯ] Ликбез для начинающих
VedunДата: Четверг, 19 Апреля 2007, 22:30:34 | Сообщение # 1
2 уровень
Группа: Проверенные
Сообщений: 39
Награды: 0
Репутация: 47
Блокировки:

  • Глава 1. Локальные и глобальные переменные.
  • Глава 2. Функции в JASS. Их общий вид. Триггеры.
  • Глава 3. Массивы переменных.
  • Глава 4. Блок if/then/else и циклы.
  • Глава 5. Полярные координаты.
  • Глава 6. Массивы, циклы и полярные координаты. Соединим приятное с полезным.
  • Глава 7. Локальные переменные. Преимущества программирования на JASS.



Глава 1. Локальные и глобальные переменные.

Читатель, если ты знаком с переменными, можешь пропустить этот абзац.
Ни один картостроитель, который хочет, чтобы в его карту играли, не может обойтись без переменных. Но что же это такое? В JASS, как и в любом языке программирования, есть переменные. Переменные, это ячейки, в которые можно записать ссылки на определённые объкты. Но нельзя путать сам ОБЪЕКТ и ССЫЛКУ на него. Это совершенно разные вещи! Например, у объекта есть куча разных свойств (они зависят от самого объекта), а у ссылки этих свойств нет. Переменные очень нужны при создании карты. Самый простой пример. В начале игры мы триггерно (т.е. с помощью триггеров прямо в игре) создаём юнита, а потом в конце игры, нам требуется удалить этого юнита. Как же это сделать, если после создания этого юнита, мы насоздовали кучу новых? Да, записать его в переменную сразу после создания. И тогда его можно будет удалить в любой момент игры. Но в переменную нельзя помещать всё подряд. При создании переменной, нужно указать тип данных, на которые будет ссылаться эта переменная. Приведу некоторые типы из ВЕ:

  • Юнит (Unit)
  • Целое число (Integer)
  • Строка (String)
  • Реальная (Real)
  • Точка (Location)
  • Спецэффект (Effect)
  • Триггер (Trigger)

Это лишь некоторые типы. Остальные можно увидеть в редакторе, во время создания переменной. В ВЕ есть такие типы, которых нет больше нигде (например триггер).
Начнём с глобальных переменных. В редакторе WarCraft реализованы лишь глобальные переменные. Что это такое и чем они отличаются от обчных переменных? Это такие же переменные, но к ним добавлена приставка глобальные. Почему? Объясню на примере. Если мы триггерно создадим юнита и запишем его в глобальную переменную, мы сможем удалить его из любого триггера. Т.е. к ним можно обращаться из любого триггера нашей карты. Такие переменные можно создать в редакторе триггеров. Но кроме глобальных переменных существуют локальные переменные. От глобальных они отличаются тем, что могут использоваться только в пределах одной функции (о функциях читай в главе второй). Той, в которой они были созданы. Такие переменные создаются командой:

Code
local тип имя

например:
Code
local unit u

local означает, что мы создаём локальную переменную, о типах ты уже знаешь, а имя трудностей вызывать не должно. В переменную, как уже было сказано ранее, можно записывать параметры. Представим себе такую переменную:
Code
local integer int

Локальная переменная типа целое число с названием int.

Не забывай, что в JASS тщательно соблюдается регистр (т.е. большие буквы должны быть большими, а маленькие - маленькими).

Как же записать в локальную переменную число? А просто! Для этого есть простая команда "set". Выглядеть всё это будет так:

Code
set int = 32

Вместо 32 можно записать всё, что угодно (только чтобы это "всё, что угодно" было целым числом).
Самое удобное в локальных переменных то, что при каждом выполнении функции создаются новые переменные, никак не связанные со старыми.

Локальные переменные обязательно должны бать в самом начале функциии или триггера.

О преимуществах таких переменных мы поговорим позже...

Добавлено (19-04-2007, 10:29 Pm)
---------------------------------------------

Глава 2: Функции в JASS. Их общий вид. Триггеры.
Читатель, если ты хочешь освоить JASS, то наверняка уже знаешь, что такое редактор триггеров в WarCraft'е и как его использовать. Триггеры в редакторе - не что иное, как функции JASS, которые оформлены и понятны. Что же это такое? Функция, это код, или точнее часть нашего кода. Эта часть имеет свои границы (начало и конец). В пределах этих границ мы можем вписывать свои действия. Как же она выглядит?

Code
function name takes nothing returns nothing <p> 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 <p> endfunction

Читатель, как ты заметил, мы вместо nothing (перед takes) поставили integer int. Это значит, что в нашу функцию будет передаваться параметр - целое число. А вызываться эта функция будет так:

Code
call name (15)

В скобках я передал параметр 15 типа целое число. Естественно, вместо этого параметра можно было передать любое другое число. Функция может брать сколько угодно параметров. Это будет выглядеть так:

Code
function name takes integer int, тип имя, тип имя returns nothing <p> endfunction

Добавлено (19-04-2007, 10:30 Pm)
---------------------------------------------

Тогда в скобках, в команде вызова функции, нужно передавать данные в ТОМ ЖЕ порядке и ТОГО ЖЕ типа, что функция берёт. Если функция берёт строку, нельзя передать ей юнита. А вот имя этого юнита можно.
Теперь о том, как использовать эти переданные данные. Представьте, что наши переданные параметры - переменные с собственным именем. Как же их использовать? Да так же, как и локальные переменны, только новое значение присваивать нельзя.
Что же такое обычные триггеры в редакторе триггеров? Это функции JASS, которые графически оформлены, это я уже говорил. Но теперь выдели пустой триггер и нажми Правка --- Конвертироватьв текст. Ты увидишь что то, вроде этого:

Code
function Trig_____________________________________001_Actions takes nothing returns nothing <br /> endfunction <p> //=========================================================================== <br /> function InitTrig_____________________________________001 takes nothing returns nothing <br /> set gg_trg_____________________________________001 = CreateTrigger( ) <br /> call TriggerAddAction( gg_trg_____________________________________001, function Trig_____________________________________001_Actions ) <br /> endfunction

Крайне неудобно работать с таким кодом, верно? Мой триггер назывался Безымянный триггер 001. В коде он называется "_____________________________________001". Редактор, прежде чем начать выполнение твоих триггеров, переводит их в JASS. И как ты заметил переводит крайне не удобно. Давай разберём всё это.

Code
function Trig_____________________________________001_Actions takes nothing returns nothing <br /> endfunction

Это - действия нашего триггера. Так как триггер был пустой, функция пустая.

Code
function InitTrig_____________________________________001 takes nothing returns nothing <br /> set gg_trg_____________________________________001 = CreateTrigger( ) <br /> call TriggerAddAction( gg_trg_____________________________________001, function Trig_____________________________________001_Actions ) <br /> endfunction

Это - функция инициализации триггера. Она создаёт триггер и указывает ту функцию, которая содержит его действия. Теперь, ты знаешь, как выглядят твои триггеры на самом деле и, если тебе нужно узнать, как сделать то или иное действие, ты можешь сделать это действие в редакторе, а потом конвертировать.

//-------------------------------------
"Это первые две части статьи. Остальные буду выкладывать в течении получаса (по причине полной неформатированности текста).

 

VedunДата: Четверг, 19 Апреля 2007, 22:42:43 | Сообщение # 2
2 уровень
Группа: Проверенные
Сообщений: 39
Награды: 0
Репутация: 47
Блокировки:
Глава 3. Массивы переменных.
Читатель, представь себе ситуацию, когда ты создаёшь триггерно кучу точек (например 360). А потом надо все эти точки удалить. Что ты сделаешь? Создашь 360 переменных типа точка? Нет, не пойдёт. Можно было бы скомпоновать все 360 переменных в одну строчку... А почему нельзя? Для этого существуют массивы переменных. Наверняка, ты не раз видел галочку массив, при создании переменной. Но если не знаешь, что она означает, стараешься не обращать внимания. Что же такое массив переменных? Это переменные, которые собраны в одну строчку. Эти переменные проиндексованы (т.е. у каждой есть свой номер) и каждую из них можно вызвать. В каждую такую переменную можно записывать любое значение нужного типа. Такие переменные просто незаменимы, например, при создании триггерных спеллов (заклинаний, которые реализованы на триггерах). Индекс таких переменных записывается в квадратные скобки:
Code
Переменная[индекс]

Такие переменные очень хорошо могут сочетаться с циклами (о циклах ты узнаешь в следующей главе).
Но массивы могут быть локальными. Как же их создавать? Читатель, ты помнишь, как создавать локальные переменные? Верно:
Code
local тип имя

А теперь, после типа переменной, добавь слово array. Это будет выглядеть так:
Code
local тип array имя

Что бы записать значение с одну из переменных, нужно добавить к имени индекс:
Code
set имя[индекс] = значение

В JASS числа начинаются с нуля, а не с единицы. Так, игроки отмечаются цифрами не с 1 до 12, а с 0 до 11. Значит, и индекс переменных можно начинать с нуля.



Глава 4. Блок if/then/else и циклы.
Читатель, в редакторе триггеров ты неоднократно видел условие. Что же это такое? Представим себе триггер:
Code
Событие: Юнит входит в регион <br /> Действие: Убить вошедшего юнита

А что, если убить надо определённого юнита? Тогда нам понадобится условие и триггер будет выглядеть так:

Code
Событие: Юнит входит в регион <br /> Условие: Вошедший юнит = нужный юнит <br /> Действие: Убить вошедшего юнита

Теперь триггер убьёт лишь определённого юнита. Но может возникнуть ситуация, когда нужно что то проверить прямо во время выпонения триггера. Для этого есть блок if/then/else (Если/Тогда/Иначе). А какже выглядит это блок на JASS?

Code
if наше условие then действие else действие endif (конец блока)

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

Добавлено (19-04-2007, 10:42 Pm)
---------------------------------------------

Чтобы проверить свой код, без непрятностей, скачайте себе внешний JASS редактор. Например программу CoolerJASS.[/color]

Переходим к циклам.
У тебя наверняка были ситуации, когда одно и то же действие ты повторяешь много раз подряд. Например, ситуация, когда нужно создать разных крипов (random creeps) и заставить их куда то идти. Не создавать же два дествия 20 раз подряд? Но давай рассмотрим циклы. Цикл, это блок, который будет повторять указанные действия, пока не выполнится условие выхода из цикла. Что может быть условием выхода цикла? Чаще всего в качестве таких сравнений используются сравнение двух чисел (например выйти, когда переменная int будет больше 5). Вот, как выглядит цикл в JASS:

Code
local integer int = 1 (создаём локальную переменную, которая будет отвечать за выход из цикла) <br /> loop (начало цикла, это словообязательно) <br /> exitwhen (условие выхода (выйти, когда...)) int > 5 (...наша переменная для выхода будет больше 5. Т.е. когда цикл выполнится 5 раз, он закончится) <br /> Действия, которые должны повторяться <br /> set int = int + 1 (чтобы условие выхода сработало, переменная int должна увеличиваться на 1 при каждом выполнении цикла) <br /> endloop (конец цикла)

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



Глава 5. Полярные координаты.
Итак, мы дошли до полярных координат. Читатель, если ты знаком с системой координат, пропусти этот абзац.
Что такое полярные координаты? Читатель, представь себе плоскую систему координат (т.е. такую систему, в которой точки вычисляются с помощью двух параметров – X и Y). Вот её график:

Это просто рисунок, но с его помощью можно вычислять определённые точки. Посмотрите на буквы X и Y. Это оси. Y – вертикальная, а X – горизонтальная. Посмотри в точку, где пересекаются две оси. Это – начало координат. Давай условно называть эту точку центром. Центр может находиться где угодно, и оттуда, где он находится, начинается отсчёт. Теперь давай разберёмся с градусами. Читатель, посмотри на рисунок и мысленно нарисуй поверх него круг. Не получается? Тогда я сам нарисую:

Получилось не очень ровно и красиво (всёж в паинте рисую =), но и так подойдёт. Видишь римские цифры? Это четверти. Осями Х и Y раздели круг на 4 части. У тебя получится тоже самое. Чем это может нам помочь? А тем, что это упрощает работу с градусами. Круг это 360 градусов. А теперь раздели 360 градусов на 4 (так как у нас 4 четверти). Получится 90. Т.е. в одной четверти 90 градусов. Давай начинать отсчёт градусов с оси X. Как это может помочь в ВЕ? Самый простой пример. Направление взгляда юнита (т.е. в какую сторону направлена его передняя часть =)). А направления вычисляй по осям. Т.е. в право получится 0 градусов, вверх – 90, влево – 180, вниз – 270. Ты можешь сказать, почему вправо 0, если 270 + 90 = 360? Но ведь 360 это и есть 0. Теперь давай попробуем найти точку по двум параметрам: расстоянию от центра и градусам. Из центра проведи прямую, которая будет пересекаться с кругом (радиус этого круга). Это будет выглядеть примерно так:

Давай посчитаем длину нашего радиуса. Для этого из точки пересечения радиуса с кругом (я отметил её жирной красной точкой =) проведи линию вниз. Эта прямая попадёт примерно на 5 штрих. Т.е. длина нашего радиуса 5. Теперь посмотрим угол, который образует наш радиус с осью Х. Он равен 45 градусам. Т.е. мы вычислили точку по двум параметрам. В ВЕ реализован этот метод вычисления координат и называется он – Полярные координаты. Чтобы вычислить точку нам нужен центр, расстояние и угол. Это действие называется Point With Polar Offset. На практике оно выглядит так:
Code
Set loc = ((Центр) offset by Расстояние towards Градусы degrees)
С помощью этого действия можно реализовать, например, движение по кругу и ещё много разных фишек, которые были не доступны без этого действия.


Сообщение отредактировал Vedun - Четверг, 19 Апреля 2007, 22:41:17
 

VedunДата: Четверг, 19 Апреля 2007, 22:46:14 | Сообщение # 3
2 уровень
Группа: Проверенные
Сообщений: 39
Награды: 0
Репутация: 47
Блокировки:

Глава 6. Массивы, циклы и полярные координаты. Соединим приятное с полезным.

Вспомним ситуацию, когда надо создать 360 точек. Читатель, теперь, когда ты знаешь, что такое цикл, как ты это сделаешь? Да, нужно создать цикл, который будет выполнять действие 360 раз. А что если каждую точку надо удалить? Как это реализовать? Давай вспомним строение цикла:

Code
  local integer int = 1   
   loop   
      exitwhen int > 5      
      set int = int + 1   
   endloop 

У нас есть переменная int, которая отвечает за выход их цикла.


В ВЕ есть специальные переменные, которые отвечают за выход из цикла. Это bj_forLoopAIndex и bj_forLoopAIndexEnd. 1 переменная, это аналог нашей переменной int. 2 переменная, как я считаю, не нужна совершенно. Это аналог нашей цифры 5 (строка exitwhen int > 5).

Code
local effect array e   
  local integer int = 1   
  loop   
     exitwhen int > 5 
     call AddSpecialEffectLocBJ( GetRectCenter(GetPlayableMapRect()), "Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl" ) 
     set int = int + 1   
  endloop 

Путь к файлам в JASS пишется не как обчно (например, Abilities\Spells), а с двумя слэшами (чёрточками) - Abilities\\Spells.

Добавлено (19-04-2007, 10:44 Pm)
---------------------------------------------
Этот цикл создаст 5 эффектов (восклицательных знаков) в центре карты. Согласен, это бессмысленно, но это лишь пример. Читатель, обрати внимание на локальный массив переменных типа эффект (effect). Поставим задачу – записать в этот массив все созданные спецэффекты. Как это сделать? Вот здесь и нужна нам переменная int. Эта переменная с самого начала равна 1. Т.е. с неё начинается цикл. При каждом выполнении цикла она увеличивается на единицу, пока не станет больше 5 и не сработает условие выхода. Эта переменная может помочь нам записать все точки в массив. Чем? Чтобы занести точки в массив, нам нужен индекс для каждой переменной массива. А если создаётся 5 точек, значит нам нужны индексы от 1 до 5 (или от 0 до 4). Теперь снова посмотрим на переменную int. Она идеально подходит в качестве индекса. Теперь можно закончить наш цикл:

Code
local effect array e   
  local integer int = 1   
  loop    
    exitwhen int > 5   
     call AddSpecialEffectLocBJ(GetRectCenter(GetPlayableMapRect()), "Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl" )   
     set e[int] = GetLastCreatedEffectBJ()   
     set int = int + 1   
  endloop 

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

Code
PolarProjectionBJ(GetRectCenter(GetPlayableMapRect()), 1000, 0)

Это действие создаст что нибудь на расстоянии 1000 справа от центра карты. Теперь совместим циклы и полярные координаты. Читатель, теперь посмотри на этот цикл:
Code
local effect array e 
  local integer int = 1   
  loop   
     exitwhen int > 5   
     call AddSpecialEffectLocBJ(PolarProjectionBJ(GetRectCenter(GetPlayableMapRect()), 1000, 72*int),  
               "Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl" )   
     set e[int] = GetLastCreatedEffectBJ() 
     set int = int + 1   
  endloop 

Попробуй разобрать этот цикл сам, если не сможешь, прочитай его описание чуть ниже.


Сообщение отредактировал BL-AF - Суббота, 08 Сентября 2007, 19:44:40
 

VedunДата: Четверг, 19 Апреля 2007, 23:05:26 | Сообщение # 4
2 уровень
Группа: Проверенные
Сообщений: 39
Награды: 0
Репутация: 47
Блокировки:
Цикл:
Мы знаем, что круг это 360 градусов. У нас 5 эффектов, которые надо расположить по кругу. Для того, чтобы узнать в какой точке будет эффект, мы 360 разделим на 5. Получится 72 градуса. Теперь мы просто эти 72 градуса умножаем на номер спецэффекта (1 эффект, 2 эффект и т.д.). В качестве этого номера у нас переменная int. Всё остальное тебе понятно.


Глава 7. Локальные переменные. Преимущества программирования на JASS.

Читатель, мы подошли к обсуждению преимуществ языка JASS. Локальные переменные. Какие у них могут быть преимущества? Представь ситуацию, когда нужно отнять здоровье у юнита, а через пять секунд вернуть прежнее значение. Да, несложно, можно сделать и без JASS’а. Но вдруг здоровье надо отнять у 5 юнитов? Или 10, 15 и т.д. Что делать в таком случае? Здесь никак не обойтись без локальных переменных. Мы просто занесём юнита в эту переменную и отнимем у него жизнь. А через 5 секунд восстановим её. Плюс в том, что если запустить эту функцию хоть ещё 10 раз, здоровье нашего юнита всё равно восстановится. Каждый раз при выполнении какой либо функции создаются новые локальные переменные. И запусти ты её хоть 1000 раз, всё будет работать.
JASS расширяет границы программирования в WarCraft, он позволяет сделать то, что недоступно обычному пользователю редактора триггеров. Но всё же не стоит забывать про триггеры. Они гораздо удобнее кода в чистом виде. Хотя иногда требуется именно JASS, ведь в редакторе триггеров реализовано далеко не всё!


Надеюсь моя статья с кратким описанием основ языка JASS поможет хоть кому нибудь.

=======================
Ещё выложу свои статьи по триггерным спеллам и анализу триггеров на JASS.

Добавлено (19-04-2007, 11:05 Pm)
---------------------------------------------
ZeToX-2007, если я статью переправлю полностью, выложишь её по нормальному? А то в 10 постах одна статья...

Сообщение отредактировал BL-AF - Суббота, 08 Сентября 2007, 19:45:18
 

Форум о Warcraft 3 » Раздел для картостроителей » GUI / Jass » [СТАТЬЯ] Ликбез для начинающих
  • Страница 1 из 1
  • 1
Поиск:

Copyright © 2006 - 2024 Warcraft3FT.info При копировании материалов c сайта ставьте, пожалуйста, активную обратную ссылку на нас • Design by gReeB04ki ©
Хостинг от uCoz