Самый ранний вариант можно изучить - спрайты и модели. Именно в них можно задавать анимации.
Спрайт
пример создания спрайта
При создании спрайта MinimapWaypoint анимация проигрывает сама. При создании спрайт проигрывает анимацию stand
Frame "SPRITE" "MinimapWaypoint" {
BackgroundArt "UI\Minimap\Minimap-Waypoint.mdx",
}
код создания спрайта
local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
local sprite = BlzCreateFrameByType("SPRITE", "MinimapWaypoint", gameUI, "MinimapWaypoint", 0)
BlzFrameSetAbsPoint(sprite, FRAMEPOINT_CENTER, 0.4, 0.3)
Как проиграть анимацию триггером?
Разбираем функцию BlzFrameSetSpriteAnimate анимировать спрайт можно действием BlzFrameSetSpriteAnimate.
---@param frame framehandle
---@param primaryProp integer
---@param flags integer
---@return nothing
function BlzFrameSetSpriteAnimate(frame, primaryProp, flags) end -- (native)
Где frame - фрейм;
primaryProp это не индекс анимации, но воспроизводит определённый спектр.
флаг | анимация |
---|---|
0 | birth |
1 | death |
2 | stand |
3 | morph |
4 | alternate |
flags - последняя цифра в функции скорее всего зациклить ли анимацию, однако не тестировалось. Не знаю как воспроизвести. Другой источник сообщает, что модель должна быть зациклена, чтобы это включать. А это ещё в редакторе моделей работать над моделью.
Код анимирования спрайта
local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
local sprite = BlzCreateFrameByType("SPRITE", "MinimapWaypoint", gameUI, "MinimapWaypoint", 0)
BlzFrameSetAbsPoint(sprite, FRAMEPOINT_CENTER, 0.4, 0.3)
local sss = 0 --счетчик
TimerStart(CreateTimer(), 1.00, true, function()
print("SSS: "..sss)
BlzFrameSetSpriteAnimate(sprite, sss, 0)
sss = sss+1
if sss>2 then
sss = 1
end
end)
function Test2()
-- create a Sprite copy the button's positions
local model = BlzCreateFrameByType("SPRITE", "SpriteName", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)
BlzFrameSetAbsPoint(model, FRAMEPOINT_CENTER, 0.4, 0.3)
BlzFrameSetSize(model, 0.01, 0.01)
-- apply the model
BlzFrameSetModel(model, "Abilities\\Weapons\\RockBoltMissile\\RockBoltMissile.mdl", 0)
-- Models don't care about Frame Size, But world Object Models are huge . To use them in the UI one has to scale them down alot.
BlzFrameSetScale(model, 0.00006)
-- play death animation
-- birth = 0
-- death = 1
-- stand = 2
-- morph = 3
-- alternate = 4
BlzFrameSetSpriteAnimate(model, 1, 0)
end
Настройка размеров спрайта
Функцией BlzFrameSetSize трудно изменить размеры модели. По факту, нативка совсем не изменяет размер модели спрайта. Замечано, что задание размеров size фрейма изменяют только положение модели спрайта от текущего положения спрайта. Т.е. модель спрайта почему-то не всегда там, где спрайт. Советую не трогать BlzFrameSetSize.
Хотя я вам должен сказать, что дело не только в нативке BlzFrameSetSize. Сам спрайт багованный, и он не перемещается туда, куда указываешь (хотя не со всеми спрайтами такое происходит. но и может произойти и такое. Не знаю с чем связано, мб модель, или какая связь модели с изменением координат). А если и размеры указать BlzFrameSetSize, то отклонется модель спрайта еще дальше. Получается модель спрайта отклоняется два раза от зафикс точки спрайта: при указании новой позиции на экране x,y (не факт), и при изменении размеров size.
Поэтому проще спрайт привязать к точкам другого фрейма, чтобы не съезжал.
По идее у вас не будет съезжать, если указан дефолтный размер модели. Т.е. возьмем модель кулдауна, по факту размер кнопки равен w=0.039,h=0.039. Создается в нужном месте. а вот при изменении размера от дефолтного, модель съезжает.
BlzFrameSetSize(sprite, 0.35,0.35) --модель съезжает в правый верхний угол
настраивать размер спрайта можно через
BlzFrameSetScale(sprite, 0.15)
Задание модели фрейму
Прописывать нужно модель как обычно, двойными слешами и с путем как обычно в импорте
BlzFrameSetModel(new_Frame, "war3mapImported\\myModel.mdx", 0)
Специальная функция создания фрейма от Hate
Можно создать спрайт с помощью функции ниже. Дело в том, что многие спрайты недоработанные, багованные и могут съезжать от первоначальных координат. Поэтому проще спрайт привязать к точкам другого фрейма, чтобы не съезжал
Предложено новый фрейм крепить точками relative_point_from, relative_point_to к заданному relative_to_frame с оффсетами.
Hate советует привязывать левый низ FRAMEPOINT_BOTTOMLEFT, к левому низу FRAMEPOINT_BOTTOMLEFT
---@param model string
---@param scale real
---@param relative_to_frame framehandle
---@param relative_point_from framepointtype
---@param relative_point_to framepointtype
---@param offset_x real
---@param offset_y real
---@param parent framehandle
---@return framehandle
function CreateSprite(model, scale, relative_to_frame, relative_point_from, relative_point_to, offset_x, offset_y, parent)
local new_Frame = BlzCreateFrameByType("SPRITE", "justAName", parent, "WarCraftIIILogo", 0)
BlzFrameSetPoint(new_Frame, relative_point_from, relative_to_frame, relative_point_to, offset_x, offset_y)
BlzFrameSetSize(new_Frame, 1., 1.)
BlzFrameSetScale(new_Frame, scale)
BlzFrameSetModel(new_Frame, model, 0)
return new_Frame
end
Создание через fdf-file
Этот раздел для понимания работы:
Здесь я пробую создать MODEL (см. ниже про model), идентично это работает и со спрайтами. Просто когда спрайт создаешь, он запускает анимацию и исчезает. Если не подобрать нужную. Поэтому возня это вся. чтобы вы понимали: некоторые спрайты типа кулдауна имеют анимацию в 1 сек, при запуске спрайт очень быстро проигрывает анимацию, и все. Вы не успеваете ничего понять, и проверить зафиксирован ли спрайт. Пример в моем случае, нужно было посмотреть как сидит кулдаун на кнопке, и нужно было выровнять положение модели. Я решил использовать MODEL вместо SPRITE (внизу показаны спрайты, но я пробовал через MODEL для проверки), чтобы смотреть как расположены будут фреймы. Тип Model не может проигрывать анимации, это модель с статичным изображением. Некоторые модели по типу кулдауна помогают чекать тек положение, размеры. Но возможно этот способ может и не подойти вам, я еще не знаю всех нюансов моделей и frame-model/sprite. Зависит, что за модель используется. Некоторые модели могут не отображаться в Model (мб нет статичной анимации или чего еще, как с примером waypoint. некоторые говорят, что нужно в таких модели камеру настраивать, как у портретов)
Когда вы поймете, что Model создается правильно, и никуда не съезжает. Проверите размеры. Теперь уже можно переделать обратно на тип фрейм Sprite.
первый способ
Frame "FRAME" "parentCoold" {
Height 0.039,
Width 0.039,
Frame "SPRITE" "Coold" {
BackgroundArt "UI\Feedback\Cooldown\UI-Cooldown-Indicator.mdx",
LayerStyle "NOSHADING",
SetAllPoints,
}
}
второй способ (от Hate)
Frame "FRAME" "parentCoold" {
Height 0.039,
Width 0.039,
Frame "SPRITE" "Coold" {
BackgroundArt "UI\Feedback\Cooldown\UI-Cooldown-Indicator.mdx",
LayerStyle "NOSHADING",
SetPoint BOTTOMLEFT, "parentCoold", BOTTOMLEFT, 0, 0,
}
--перед тем как инициировать код, необходимо задержка для спрайтов. Когда в начале игры только-только прорисовывается экран, спрайт уже проиграл половину анимации, из-за чего мб не понятно. тк спрайт в 1 сек оч быстро проигрывает. На гифку не успеваю записать
TimerStart(CreateTimer(), 2.00, false, function()
local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
local parent = BlzCreateFrameByType("FRAME", "parentCoold", gameUI, "parentCoold", 0)
BlzFrameSetSize(parent, 0.035, 0.035) --если указать размеры родителю (что указан в fdf), то модель спрайта-потомка меняет размеры следом. Обращаю внимвние на то, что дефолтный размер модели кулдауна 0.039×0.039. Но тут указываю родителю спрайта 0.035х0.035, и модель принимает точно такой размер.
BlzFrameSetAbsPoint(parent, FRAMEPOINT_CENTER, 0.4, 0.3)
local child = BlzGetFrameByName("Coold",0) --BlzFrameGetChild(parent, 0)
--BlzFrameSetScale(child, 0.15)
--далее пытаюсь создать иконку блейда, чтобы сравнить не съехала. Если не съехла, можно выключить, и запустить второй раз посмотреть лежит ли она внутри.
local blademaster = BlzCreateFrameByType("BACKDROP", "Blademaster", gameUI, "", 0)
BlzFrameSetSize(blademaster, 0.035, 0.035)
BlzFrameSetAbsPoint(blademaster, FRAMEPOINT_CENTER, 0.4, 0.3)
BlzFrameSetTexture(blademaster, "ReplaceableTextures\\CommandButtons\\BTNHeroBlademaster",0, true)
если нужно, чтобы спрайт был выше иконки блэйда
--BlzFrameSetLevel(parent, 2)
--BlzFrameSetLevel(blademaster, 1)
end)
Они дают два идентичных результата. Нужно тогда вторым способом (способ Hate) в fdf-file подвинуть оффсетами в нижний левый угол, чтобы модель ровнее сиделось (незначительно действие, можно сказать незаметно для глаза. Особенно, когда анимация проигрывает).
Как видим теперь изображение стоит на месте. Поскольку модель кулдауна имеет размеры приблизительно 0.039 x 0.039 (на сам деле, чуть больше чем 0.039), но вы не можете изменить размер модели спрайта через BlzFrameSetSize. BlzFrameSetSize можно задавать только наводящему фрейму, точнее родителю parent. Изменяешь parent, изменяется и child.
Как мы видим выше, создана вторая картинка блэйда, чтобы сравнить расположение и размеры. Картинка блэйда имеет меньший размер 0.035 x 0.035 - специально задал такой же размер. Фрейм parent тоже задал 0.035 x 0.035 через BlzFrameSetSize. И фрейм child изменяет размеры также следом.
Вот спрайт анимированный
А вот чтобы изменить размеры модели необходимо задать скэйл BlzFrameSetScale(child, 2.00) - ВНИМАНИЕ: Scale можно задать только спрайту, MODEL никак не хочет изменять размеры
На gif файле показано как спрайт увеличен в 2 раза.
Так понимаю, смотря на рис выше:
Если размеры слишком большие > 1.00, то в правый верхний угол растягивается. И наоборот, если < 1.00. Размеры легко считать, если знать дефолтные размеры модель = 0.039 x 0.039. Этот множитель умножает на эти размеры, достаточно просто получается
Если размеры слишком большие > 1.00, то в правый верхний угол растягивается. И наоборот, если < 1.00. Размеры легко считать, если знать дефолтные размеры модель = 0.039 x 0.039. Этот множитель умножает на эти размеры, достаточно просто получается
Фрейм MODEL
Тип модель ни чем не отличается от спрайта. Правда, не знаю, может ли данный тип проигрывать анимацию. Может ли дело в анимации? Также в отличии от спрайта, я не смог изменять размеры, если привязать MODEL к какому-нибудь фрейму. Этот тип абсолютно бесполезен, либо я не знаю чего-то такого.
fdf-file model
В отличии от спрайта в model всегда почему-то прописывается
LayerStyle "NOSHADING",
LayerStyle "NOSHADING",
Зато, как model получилось, но не получается никак анимацию запустить. На одном кадре модель заступорена, получилась статичная картинка кулдауна.
Frame "MODEL" "Coold" {
BackgroundArt "UI\Feedback\Cooldown\UI-Cooldown-Indicator.mdx",
LayerStyle "NOSHADING",
}
код создания фрейма
local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
local fh = BlzCreateFrameByType("MODEL", "Coold", gameUI, "Coold", 0)
BlzFrameSetAbsPoint(fh, FRAMEPOINT_CENTER, 0.0, 0.3)
Вывод
MODEL - это тип фрейма, где модель задана статичным изображением. Размер модели никак не изменить, также не получается проиграть анимацию.
Frame "FRAME" "parentModel2" {
Height 0.039,
Width 0.039,
Frame "MODEL" "Model2" {
BackgroundArt "UI\Glues\ScoreScreen\ScoreScreen-Background\ScoreScreen-Background.mdl",
//SetAllPoints,
SetPoint BOTTOMLEFT, "parentModel2", BOTTOMLEFT, 0, 0,
LayerStyle "NOSHADING",
}
}
Анимированные рамки
Может кому пригодится, когда то тоже искал как анимировать рамку, образцы и примеры итд.
Альтернативный способ
Предлагается анимировать фреймы с помощью таймера:
STATUSBAR
Третий вариант предлагается через StatusBar:
Ранее уже были образцы с SimpleStatusBar. Однако, симплстатусбар никак не анимирует модель, а всего лишь растягивает/урезает текстуру. Такое не сложно сделать и обычными средствами, зная пропорцию и растянуть изображение. Однако, этот инструмент не растягивает изображение, а урезает, что находит свое мини-преимущество.
Снизу это фон backdrop (иконка рыцаря смерти), сверху это текстура бара (иконка паладина). Она не размазывается при растяжении/сжатии полоски, как видим урезается часть изображения.
Вернемся к нашему обычному статус-бару. Дело в том, что анимации в спрайтах и моделях никак не регулируются, вы запустили, и анимация пошла, нельзя влиять на скорость воспроизведения, плохо работают, и прочее. И поэтому дело берет в свои руки StatusBar
STATUSBAR — это неинтерактивный (не игровой) фрейм, отображающий модель Warcraft 3. В отличие от Sprite, он не зацикливает анимацию, но текущее время animationTime можно установить с помощью BlzFrameSetValue в виде % от Min/Max до AnimationTime.
- Говорят, что «STATUSBAR» поддерживает только анимацию интервалом 1 сек, последовательности после 1 сек отбрасываются.
- Этот тип довольно хорошо можно создать с помощью кода только ModelBar без FDF.
От авторов: Hate и TriggerHappy:
do
local real = MarkGameStarted
function MarkGameStarted()
real()
local bar = BlzCreateFrameByType("STATUSBAR", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)
BlzFrameSetAbsPoint(bar, FRAMEPOINT_TOPLEFT, 0.4, 0.3)
-- Screen Size does not matter but has to be there
BlzFrameSetSize(bar, 0.00001, 0.00001)
-- Models don't care about Frame Size, But world Object Models are huge . To use them in the UI one has to scale them down alot.
BlzFrameSetScale(bar, 1)
--BlzFrameSetModel(bar, "ui/feedback/cooldown/ui-cooldown-indicator.mdx", 0)
--BlzFrameSetModel(bar, "ui/feedback/XpBar/XpBarConsole.mdx", 0)
BlzFrameSetModel(bar, "ui/feedback/progressbar/timerbar.mdx", 0)
--BlzFrameSetModel(bar, "ui/feedback/buildprogressbar/buildprogressbar.mdx", 0)
--BlzFrameSetMinMaxValue(bar, 0, 100)
local i = 0
TimerStart(CreateTimer(), 0.1, true, function()
BlzFrameSetValue(bar, i)
i = i + 1
--i = GetRandomInt(0, 100)
print(BlzFrameGetValue(bar))
end)
print("done")
end
end
Подобным статус баром можно анимировать все что угодно. Если ранее мы анимировали полосы, то можно анимировать бутылки, или анимации как хп/мана бар в диабло, где не типичные полосы, а шары по бокам. Кулдаун можно свой анимировать. На этом - всё.
Как шкалу запустить от 0 до 100% таймером?
- period - 0.05, период обновления,
- cd - длительность, сколько должен заполнятся хп бар;
Мой фрейм перезарядки слева направо, адаптируйте под себя:
function StartFrameCD(cd, fh,period)
local amount = period*100 / cd
local full = 0
TimerStart(CreateTimer(), period, true, function()
full = full + amount
BlzFrameSetValue(fh, full)
if full >= 100 then
DestroyTimer(GetExpiredTimer())
full = 0
end
end)
end
Это работает железно, я так делаю каст бары из фреймов или эффектов, вот ещё пример
Напоследок, карта от Берги, где прикручена модель со вспышкой CD.
Ред. ScorpioT1000
Ред. Makeba
Updt. А почему с публикации снято?