Silnik gier 2D: scenariusze animacji jednym wywołaniem — sekwencje tweenów
Silnik gier 2D w Moonlight Animate miał już bogate tweeny — płynne animowanie właściwości węzła w czasie (pozycja, obrót, skala, krycie, barwa, wartości liczbowe). Można było też łączyć je w łańcuchy, ale tylko ręcznie, przez zagnieżdżanie callbacków — a to szybko robi się nieczytelne i podatne na błędy:
-- STARY sposób: łańcuch przez zagnieżdżone callbacki (im dłuższy, tym gorzej)
mp.tween(wróg, "x", 300, 2, function()
mp.after(1, function()
mp.tween(wróg, "x", 0, 2, function()
-- ...i tak w kółko, ręcznie
end)
end)
end)
Nowa funkcja mp.tween_sequence zamienia to w czytelny scenariusz kroków.
Jedna lista, wykonywana po kolei
-- Patrol wroga w nieskończonej pętli: idź w prawo, poczekaj, wróć, poczekaj
mp.tween_sequence(wróg, {
{prop='x', to=300, dur=2, easing='ease-in-out'},
{wait=1},
{prop='x', to=0, dur=2, easing='ease-in-out'},
{wait=1},
}, {loops=-1})
Kroki są trzech rodzajów i mieszają się dowolnie:
- animacja —
{prop='x', to=100, dur=1}(właściwość wbudowana) albo{key='mana', to=50, dur=0.5}(wartość z tablicy węzła); - oczekiwanie —
{wait=0.5}(pauza w sekundach czasu gry); - wywołanie —
{call=function() ... end}(odpal dowolny kod i idź dalej).
W opcjach: loops (-1 = w nieskończoność, N = N powtórzeń) oraz on_complete — funkcja odpalana raz
po normalnym zakończeniu scenariusza.
Co to naprawdę daje ponad ręczny łańcuch
To nie jest tylko ładniejszy zapis. Ręczne łączenie callbacków ma trzy realne braki, które scenariusz rozwiązuje:
- Pętle, w tym nieskończone. Zapętlenie łańcucha przez ręczne wołanie się z ostatniego callbacku jest
upierdliwe i łatwo w nim o przeciek. Tu wystarczy
loops=-1. - Jeden uchwyt do zatrzymania.
mp.stop_sequence(uchwyt)zatrzymuje cały scenariusz — łącznie z jego bieżącą animacją — jednym wywołaniem. W ręcznym łańcuchu musiałbyś śledzić każdy pośredni uchwyt sam. - Zero przecieków przy zniknięciu obiektu. Gdy węzeł zostanie usunięty w połowie scenariusza (np. wróg
zginął w trakcie patrolu), scenariusz jest po cichu porzucany — bez zawieszenia, bez
on_complete, bez wiszących w pamięci callbacków.
Przewidywalny w każdej sytuacji
- Reużywa istniejące tweeny — kroki-animacje to te same krzywe wygładzania, te same typy właściwości,
ta sama determinacja co zwykły
mp.tween. Zero osobnego silnika interpolacji. - Pauza gry zamraża cały scenariusz (animacje i oczekiwania stają), a wznowienie kontynuuje dokładnie tam, gdzie stanął.
- Jeśli w trakcie kroku-animacji ktoś uruchomi osobny tween na tej samej właściwości, scenariusz przerywa się w kontrolowany sposób zamiast utknąć.
mp.is_sequencing(węzeł)mówi, czy węzeł ma żywy scenariusz — przydatne do bramkowania wejścia gracza podczas cutscenki.
Typowe zastosowania
Cutscenki (kamera najeżdża → dialog → kamera wraca), animacje interfejsu (przycisk: powiększ → poczekaj → zmniejsz), sekwencje ruchu przeciwników (patrol, wahadło, obchód), skryptowane wejścia/wyjścia paneli HUD. Wszystko, co jest sekwencją zdarzeń w czasie, zapisuje się teraz jako jedna czytelna lista — kolejny klocek dokładany do silnika gier 2D w Moonlight Animate.