Animacja poklatkowa (ang. flip-book animation) składa się z serii obrazów (klatek animacji), które są pokazywane jeden za drugim, więc patrząc na nie sprawiają wrażenie ruchu. Technika ta jest bardzo podobna do tradycyjnej animacji używanej w kinematografii https://pl.wikipedia.org/wiki/Animacja i oferuje nieograniczoną kontrolę, ponieważ każda klatka może być modyfikowana indywidualnie. Jednakże pamięć zajmowana przez wszystkie obrazy składające się na taką animację może być duża w zależności od ilości klatek i ich wielkości. Płynność animacji zależy od liczby klatek pokazywanych w każdej sekundzie (FPS z ang. frames per second), co wymaga oczywiście większej ilości pracy. Animacje typu flip-book w Defoldzie są przechowywane albo jako indywidualne obrazy umieszczone w galerii zwanej Atlas, albo jako obrazy umieszczone w bezpośrednim sąsiedztwie, w poziomej sekwencji jak kafelki w tzw. Źródle Kafelków - Tile Source.
Sprite’y i węzły GUI mogą odtwarzać animacje poklatkowe i masz nad tym całkowitą kontrolę w trakcie działania programu.
sprite.play_flipbook()
. Poniżej przykład.gui.play_flipbook()
. Poniżej przykład.Tryb odtwarzania (playback mode) “once ping-pong” odtworzy animację klatka po klatce do samego końca, a następnie odtworzy ją jeszcze raz w odwrotnej kolejności, od tyłu, ale do drugiej klatki animacji, a nie do pierwszej. Jest to zabieg służący łatwemu wiązaniu animacji w serie.
Załóżmy, że Twoja gra posiada możliwość “uniku”, która pozwala graczom nacisnąć klawisz, aby wykonać unik. Masz przygotowane 4 animacje, żeby w pełni pokazać unik:
Skrypt poniżej przedstawia potrzebną logikę:
local function play_idle_animation(self)
if self.dodge then
sprite.play_flipbook("#sprite", hash("dodge_idle"))
else
sprite.play_flipbook("#sprite", hash("idle"))
end
end
function on_input(self, action_id, action)
-- "dodge" to nasza akcja zbindowana z inputem
if action_id == hash("dodge") then
if action.pressed then
sprite.play_flipbook("#sprite", hash("start_dodge"), play_idle_animation)
-- zapamiętaj, że wykonujemy unik
self.dodge = true
elseif action.released then
sprite.play_flipbook("#sprite", hash("stop_dodge"), play_idle_animation)
-- zapamiętaj, że skończyliśmy unik
self.dodge = false
end
end
end
Przy wyborze obrazu i animacji dla węzła graficznego interfejsu użytkownika (ang. GUI), np. “box” albo “pie” tak naprawdę właśnie przypisujesz źródło obrazów (atlas lub tile source) i domyślną animację, tak samo jak w przypadku sprite’ów. Takie źródło grafiki jest statycznie przypisane do węzła, ale animacja może być zmieniona w trakcie trwania programu. Nieruchome obrazki są traktowane jako jednoklatkowa animacja, więc zamiana obrazu jest jednoznaczna z odtworzeniem innej animacji poklatkowej na węźle:
function init(self)
local character_node = gui.get_node("character")
-- To wymaga, żeby węzły miały domyślne animacje w tym samym atlasie lub źródłe kafelków
-- co nowa animacja, którą odtwarzamy
gui.play_flipbook(character_node, "jump_left")
end
Funckje sprite.play_flipbook()
i gui.play_flipbook()
przyjmują jako ostatni argument opcjonalną funkcję, która jest wywoływana w momencie zakończenia animacji, tzw. callback. Będzie ona wywołana po skończeniu animacji, więc tylko dla takich, które nie są zapętlone, czyli w trybach odtwarzania: PLAYBACK_ONCE_*
i nie będzie wywołana w przypadku ręcznego anulowania animacji za pomocą go.cancel_animations()
. Można użyć takiej funkcjonalności w celu wywołania specjalnych wydarzeń po skończonej animacji (np. procesu zadania obrażeń po skończonej animacji ataku) lub do połączenia różnych animacji w serie, jedna za drugą. Przykłady:
local function flipbook_done(self)
msg.post("#", "jump_completed")
end
function init(self)
sprite.play_flipbook("#character", "jump_left", flipbook_done)
end
local function flipbook_done(self)
msg.post("#", "jump_completed")
end
function init(self)
gui.play_flipbook(gui.get_node("character"), "jump_left", flipbook_done)
end
Animacje można odtwarzać raz lub w pętli. Sposób odtwarzania animacji jest określany przez tryb odtwarzania (ang. Playback mode):
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB