Содержание:
1. Введение 2. Основные функции 3. Первая графика - круг 4. Создание линий 5. Колёса и спирали 6. Несколько советов
1. Введение
Уже давно известно, что основной составляющей любой нестандартной способности является графика, даже подумав, что многие из вас не знают, как сделать свои эффекты, не имеют программы для того, чтобы их создать или просто не хотят увеличивать размер своей карты. Однако это далеко не значит то, что вы не сможете сделать собственный эффект, обладая небольшими знаниями в триггерах и безграничной фантазией. Эта статья расскажет вам основы реализации статических - недвижимых - графических эффектов.
Внимание! Эта статья не убирает утечки памяти в результате выполнения функций!
2. Основные функции
Первое, что нужно знать о графике - две основные функции, которые в своей основе строят триггер. Все алгоритмы в основном вертятся вокруг этих функций, поэтому важно их освоить.
а) Дистанция между точками Эту функцию легко понять. Две точки - параметры, расстояние между ними - результат. Особо объяснять не надо. Для того, чтобы вы немного поняли, что такое дистанция, я скажу, что экран в WarCraft III имеет размер 1900 х 1250.
Пример: на изображении ниже есть 3 точки - a, b и c. Вот, какие получатся значения расстояния:
dist(a,b) = 25
dist(b,c)=√149 = 12,2065
dist(c,a) = √52 = 7,211
Примечание: функция коммутативная, т.е. dist(a,b) = dist(b,a).
б) Угол между точками. Более сложная функция, но знакомая, особенно для тех, кто имеет базовые знания в геометрии. Угол между точками вернёт угол, на котором находится вторая точка от первой. Чтобы легче её запомнить, поставьте две боевые единицы и заставьте их повернуться лицом друг к другу.
Примечание: Функция не коммутативная. angle(a,b) и angle(b,a) - разные вещи. angle(a,b) = angle(b,a)-180.00.
Пример: На изображении ниже вы видите 3 точки: m,n и p. Вот, какие значения функция вернёт для каждой из них:
angle(m,n) = 0
angle(n,m) = 180
angle(m,p) = 270
angle(p,m) = 90
angle(n,p) = 225
angle(p,n) = 45
с) Полярная проекция на точку. Специальная функция, которую мы будем использовать больше всего. написав в параметрах точку р, дистанцию d и угол а, получим точку p' по след. условиям:
dist( p,p’ )=d
angle( p,p’ )=a
Эта функция немного утечная, но вы скоро поймёте, почему она настолько важна при создании геометрической графики в способностях.
Пример: Допустим, у нас есть некая точка а(3;3). Требуется создать точки b = PolarOffset(a,100,60), c=PolarOffset(a,200,225),
d=PolarOffset(c,150,90), e=PolarOffset(b,170, 270). Ниже можно найти решение.
Примечание: Дистанции выделены синим, углы - красным.
3. Первая графика - круг
После того, как мы обсудили важные функции, можно приступить к созданию простой графической фигуры - круга. Я предупрежу вас, что здесь мы не будем работать со сложными координатами и подобными вещами. Мы используем изученные функции.
Первый вопрос возникнет у многих из вас: "Как же создать эту фигуру? Спецэффектами?". Ответ - нет, я полностью против спецэффектов, т.к. ими трудно управлять и можно получить неожиданный результат. Я использую боевых единиц, в частности потому, что их можно объединять в группы, да и у них есть тени, а также потому, что они являются интерактивными объектами со множеством возможных событий.
Итак, как же создать такую боевую единицу? На самом деле, очень просто. Если вы уже работали с нестандартными способностями, то наверняка слышали о боевых единицах-дамми. Наша боевая единица очень на них похожа. Она будет стоить 0 золота и 0 дерева, требовать 0 пищи, невыделяемой и неуязвимой. Называется такая боевая единица ракетой. Единственной отличие ракеты от дамми заключается в том, что у них (ракет) всегда есть прикреплённая модель, соответственно ракеты видны и имеют тип "Летающий" с некоторой высотой над поверхностью.
Для нашего круга я использовал ракету с классическим огненным эффектом. Перед тем, как начать создавать круг, мы должны подумать, как мы его создадим. Естественно, что он будет состоять из ракет. Обычно при работе с графикой важно знать, сколько ракет мы будем использовать. Для радиуса 400, думаю, 36 будет вполне достаточно. Соответственно, больше радиус - больше ракет.
Какое у круга определение? Это геометрическая фигура, состоящая из множества точек, равноудалённых от центра. Мы не можем использовать множеств в программировании, но зато можем использовать факт - равноудалённые от центра. Другой важный факт - расстояние между ракетами должно быть равно. Получим такую окружность:
Теперь давайте изучим этот график, чтобы его понять. Жёлтые линии - это расстояния от центра до точек, является константой. Чилса на лучах представляют собой номер элемента круга. Угол между точками центра и элемента зависит от его номера.
Угол между поледним элементом и центром равен 360 градусов. Поэтому a*n=360 => a = 360/n, n!=0. Ещё одна важная часть - точка "k", так как из неё можно вывести формулу любого угла.
Это выглядит похожим на несколько полярных проекций на точку. Исходя из этого, можно реализовать такой круг.
For each (Integer A) from 1 to 36, do (Actions)
Loop - Actions
Unit - Create 1 Missile for Player 1 (Red) at (Circle_Center offset by 400.00 towards ((Real((Integer A))) x (360.00 / 36.00)) degrees) facing Circle_Center)
4. Создание линий
Теперь научимся рисовать ещё одну важную фигуру - линию между двумя точками. Звучит так, что это очень сложно, но на самом деле всё просто. Как всегда, сначала я покажу формулу, потом будем действовать по ней.
Угол здесь является константой. Он равен g. "Движущимся" элементом здесь является дистанция. Можно заметить, что она равна k*d, где k - индекс. Получим формулу dist(k) = k*(total_dist/n).
Теперь давайте применим это. StartPoint и EndPoint - переменные-точки. Вот, как это будет выглядеть:
For each (Integer A) from 1 to 36, do (Actions)
Loop - Actions
Unit - Create 1 Missile for Player 1 (Red) at (StartPoint offset by ((Real((Integer A))) x ((Distance between StartPoint and EndPoint) / 36.00)) towards (Angle from StartPoint to EndPoint) degrees facing EndPoint)
Прежде, чем идти дальше, убедитесь, что освоили всё, что говорилось в этом и в предыдущих пунктах.
5. Колёса и спирали
Давайте пойдём дальше и сделаем что-то в комплексе. Одна из таких комбинаций в итоге даст нам круг с несколькими радиусами. Это будет несложно создать.
Вам на заметку - Никогда не пытайтесь выводить общую формулу для всей фигуры. Лучше рисовать её по элементам.
И снова я покажу изображение, на этот раз для колеса.
Для начала создадим круг с радиусом r из центральной точки, используя метод в части 3. Затем нужно прибавить все радиусы.
Полярные координаты, на которых построены диаметры:
Center = center of the circle.
Distance = radius of the circle.
Angle = k*a and 180+k*a.
a=360/2n.; k=1,(n-1); n=total number of diameters.
Очень просто создать данную фигуру в wacraft. Смотрите:
//first create the circle
For each (Integer A) from 1 to 36, do (Actions)
Loop - Actions
Unit - Create 1 Missile for Player 1 (Red) at (Circle_Center offset by 400.00 towards ((Real((Integer A))) x (360.00 / 36.00)) degrees) facing Circle_Center)
//and now the diameters
For each (Integer A) from 1 to 8, do (Actions)
Loop - Actions
Set StartPoint = (StartPoint offset by 400.00 towards ((Real((Integer A))) x (360.00 / 20.00)) degrees)
Set StartPoint = (StartPoint offset by 400.00 towards ((Real((Integer A))) x (180.00 + (360.00 / 20.00))) degrees)
//ofcourse we need to create multiple lines
For each (Integer
from 1 to 36, do (Actions)
Loop - Actions
Unit - Create 1 Missile for Player 1 (Red) at (StartPoint offset by ((Real((Integer B))) x ((Distance between StartPoint and EndPoint) / 36.00)) towards (Angle from StartPoint to EndPoint) degrees facing EndPoint)
Спираль будет состоять из нескольких окружностей, примерно так, как на рисунке:
Начинает выглядеть логично. Существуют две важные вещи: количество ракет, создающих круг, должно быть маленьким. Угол возрастает вместе с добавлением новой окружности.
Вот, как будет выглядеть нужная нам формула:
Angle = e*n+(a*k). a=360/number_of_spires. e = constant real value (deviation angle). k=1,number_of_spires. n = index of current element of the spire.
Distance = r+(c*n). r = radius of circle at the center of the spiral. c = constant real value. n = same as above.
Теперь просто применим формулу.
For each (Integer A) from 1 to 20, do (Actions)
Loop - Actions
For each (Integer
from 1 to 7, do (Actions)
Loop - Actions
Unit - Create 1 Missile for Player 1 (Red) at (CENTER offset by (100.00 + (8.00 x (Real((Integer A))))) towards (((360.00 / 7.00) x (Real((Integer B)))) + (6.00 x (Real((Integer A))))) degrees) facing CENTER
6. Несколько советов
1) Запишите ракеты в группу. Это лучше, чем перебирать их в массиве, да и удалять их проще.
2) Удалите утечки. Обязательно записывайте их в переменную! Если вы сделаете что-то наподобие “RemoveLocation(PolarProjection([…]))”, это будет абсолютно неправильно. Получается, что вы создаёте точку и тут же её удаляете.
3) Работайте с координатами. Это можно сделать и без Custom Script-кода путём использования функции “Преобразование – Convert Coordinates to point”. Тогда вы, хоть и получая точку, сможете управлять отдельной координатой.
4) Если потребуется использование более двух циклов, не пугайтесь. Просто создайте свои переменные типа "Целочисленная" и используйте их в циклах.