Приветствую всех, дорогие читатели
Сегодняшний день давайте посвятим МТА, а именно анимации GUI (перемещение, размеры, и прочее). Я думаю перемещение GUI мышью для далёких от Lua будет трудновато, так что напишу для него отдельный урок.
В этом уроке почти весь код будет написан на ООП в МТА.
Для этого нам понадобятся:
1) Прямые ручки (ну куда-ж без них то)
2) Базовое знание MTA Lua (а именно - построение функций, строение ресурса, события, переменные, частично - ООП)
Начнём:
Для начала создадим просто изображение на экране. Я буду использовать файл pane.png размером 1х1px, так как я его использую везде
PHP код:
local MoveImage = {}
MoveImage.Image = GuiStaticImage.create(50, 50, 100, 100, "pane.png", false)
Мы создали переменную MoveImage (тип table), и в этой таблице создали переменную Image (тип userdata - gui-staticimage), которая является изображением на экране, располагающаяся на позициях 50,50 с размером 100х100. Вызывать это изображение мы будем именно через MoveImage.Image
Далее нам понадобится переменная, отвечающая за активацию какой-либо анимации. Я, например, сделаю 2 анимации для данного изображения, следовательно мне понадобится тип integer для переменной. Если мне бы нужна была одна анимация, то я бы воспользовался типом boolean.
PHP код:
MoveImage.Animation = 0
Мы создали переменную Animation в уже существующей таблице MoveImage. Сразу определим её значения:
0 - Анимация отключена
1 - Первая анимация
2 - Вторая анимация
После создания переменной, нам нужно будет её где-то использовать. Анимацию делать будем в событии onClientRender. Замечу, что скорость выполнения анимации будет зависеть от FPS (так как onClientRender выполняется покадрово)
PHP код:
addEventHandler("onClientRender", root, function()
//Здесь будет проверка на переменную Animation
if MoveImage.Animation == 1 then //Если переменная Animation равна 1 (если используем первую анимацию)
//Получаем позиции и размеры исходного изображения на каждый кадр, пока анимация равна 1
local x, y = MoveImage.Image:getPosition(false)
local w, h = MoveImage.Image:getSize(false)
x, y = x+1, y-1 //Обновляем значения переменных позиции таким образом, чтобы изображение перемещалось вверх
w, h = w-2, h-2 //Обновляем значения переменных размера таким образом, чтобы изображение при перемещении уменьшалось
//Обновляем позиции и размеры
MoveImage.Image:setPosition(x, y, false)
MoveImage.Image:setSize(w, h, false)
//Это будет длиться бесконечно, пока переменная Animation не поменяет своё значение
//Для этого мы будем отталкиваться относительно размеров
//Так как размеры уменьшаются на 2 пикселя за кадр, мы не сможем определить, когда нужно точно остановиться, так что проверка будет с учётом желаемого результата
//Ну точнее можем, но дополнительные расчёты нам не нужны
if h <= 0 then //Так как уменьшаем размеры, значит <, желаемый результат учитываем
//Когда размеры нулевые, изображение на экране уже найти будет практически невозможно
//Следовательно сия цикл должен быть закончен, поэтому меняем значение переменной
MoveImage.Animation = 2
//Чтобы совсем закончить анимацию, можно поставить 0, но я решил сразу выполнить вторую анимацию, которая будет выполнять обратное действие
end
elseif MoveImage.Animation == 2 then //Сразу тут-же делаю проверку на использование второй анимации
//Точно так-же получаем позиции и размеры исходного изображения
local x, y = MoveImage.Image:getPosition(false)
local w, h = MoveImage.Image:getSize(false)
//Точно так-же меняем размеры, но уже в обратном направлении
x, y = x-1, y+1
w, h = w+2, h+2
//Только сделаем проверки на размеры, ибо всё таки это изображение будет видимо, и если оно превысит желаемые позиции и размеры, это будет растянуто (Некрасиво :D)
if x <= 50 then x = 50 end
if y >= 50 then y = 50 end
if w >= 100 then w = 100 end
if h >= 100 then h = 100 end
//Обновляем позиции и размеры
MoveImage.Image:setPosition(x, y, false)
MoveImage.Image:setSize(w, h, false)
//И закрываем цикл
if h == 100 then
//Полностью прекратим выполнение анимации. Для бесконечного цикла можно использовать в первой анимации значение второй анимации, а здесь - значение первой анимации
MoveImage.Animation = 0
end
end
end)
Так-же можно сделать с изменением прозрачности. Я не буду здесь расписывать комментарии, думаю всё будет понятно (алгоритм тот-же, что и выше).
Здесь будет бесконечный цикл - постоянная анимация увеличения и снижения уровня прозрачности
PHP код:
addEventHandler("onClientRender", root, function()
if MoveImage.Animation == 1 then
MoveImage.Image:setAlpha(
MoveImage.Image:getAlpha()-0.05
)
if MoveImage.Image:getAlpha() <= 0 then
MoveImage.Animation = 2
end
elseif MoveImage.Animation == 2 then
MoveImage.Image:setAlpha(
MoveImage.Image:getAlpha()+0.05
)
if MoveImage.Image:getAlpha() >= 1 then
MoveImage.Animation = 1
end
end
end)
Здесь мы уяснили, что за анимацию отвечает переменная Animation в таблице MoveImage (Аля MoveImage.Animation)
Теперь давайте разберёмся, как можно вызывать анимацию. Для начала я предлагаю создать функцию для того, чтобы вызывать анимацию
PHP код:
function runAnimation(num)
if num < 0 or num > 2 then return false end //Если номер вызова анимации не принадлежит участку от 0 до 2, то просто закончить выполнение функции
//Иначе просто начать или закончить выполнение анимации
MoveImage.Animation = num
end
Теперь как вызывать функцию для того, чтобы вызвать анимацию
PHP код:
runAnimation(0) //Остановить выполнение анимации
runAnimation(1) //Выполнить первую анимацию
runAnimation(2) //Выполнить вторую анимацию
Ну и как теперь это можно использовать
PHP код:
//Например по нажатию какой-либо кнопки
bindKey("m", "up", function() runAnimation(math.random(0, 2)) end)
PHP код:
//Ну или по нажатию на само изображение
addEventHandler("onClientGUIClick", MoveImage.Image, function() runAnimation(1) end, false)
Конечный вид:
PHP код:
local MoveImage = {}
MoveImage.Image = GuiStaticImage.create(50, 50, 100, 100, "pane.png", false)
MoveImage.Animation = 0
addEventHandler("onClientRender", root, function()
if MoveImage.Animation == 1 then
local x, y = MoveImage.Image:getPosition(false)
local w, h = MoveImage.Image:getSize(false)
x, y = x+1, y-1
w, h = w-2, h-2
MoveImage.Image:setPosition(x, y, false)
MoveImage.Image:setSize(w, h, false)
if h <= 0 then
MoveImage.Animation = 2
end
elseif MoveImage.Animation == 2 then
local x, y = MoveImage.Image:getPosition(false)
local w, h = MoveImage.Image:getSize(false)
x, y = x-1, y+1
w, h = w+2, h+2
if x <= 50 then x = 50 end
if y >= 50 then y = 50 end
if w >= 100 then w = 100 end
if h >= 100 then h = 100 end
MoveImage.Image:setPosition(x, y, false)
MoveImage.Image:setSize(w, h, false)
if h == 100 then
MoveImage.Animation = 0
end
elseif MoveImage.Animation == 3 then
MoveImage.Image:setAlpha(
MoveImage.Image:getAlpha()-0.05
)
if MoveImage.Image:getAlpha() <= 0 then
MoveImage.Animation = 4
end
elseif MoveImage.Animation == 4 then
MoveImage.Image:setAlpha(
MoveImage.Image:getAlpha()+0.05
)
if MoveImage.Image:getAlpha() >= 1 then
MoveImage.Animation = 0
end
end
end)
function runAnimation(num)
if num < 0 or num > 4 then return false end
MoveImage.Animation = num
end
bindKey("m", "up", function() runAnimation(math.random(1, 2) == 1 and 1 or 3) end)
addEventHandler("onClientGUIClick", MoveImage.Image, function(but)
if but == "left" then runAnimation(1) else runAnimation(3) end
end, false)
Спасибо за прочтение, и, если будут вопросы, задавайте