Animarea cu folii de active o alternativă la blitz

Așa că ai un joc minunat în fapte, are tot felul de fizică complexă, AI inamic epic sau ce-ai-tu. Dar se simte lipsită de viață. Vrei un OOMPH, vrei o animație!

Dacă mergeți și căutați cum să animați, primul răspuns pe care îl întâlniți va fi, cel mai probabil, o metodă care folosește foi de sprite și batere. De fapt, aproape toate tutorialele de pe web vorbesc despre nimic dar blitz, ca și cum nu ar exista altă cale de a anima. Dar, din experiența mea, există o modalitate mai bună de a-ți anima orcii și goblini!

Această metodă ar putea fi apelată animând cu foi de material - sau mai mult din punct de vedere tehnic, tweening cu foi de lucru - spre deosebire de utilizare spiriduș-foi. Înainte de a intra în exact ce înseamnă acest lucru, să luăm în considerare o întrebare importantă:


Ce este greșit cu Blitting?

Mai jos sunt câteva motive De ce nu ați vrea să folosiți blitzul în anumite cazuri.

1. Are mult spațiu

Fie că vorbim de spațiu RAM sau de spațiu pe disc, foile de sprite pot bloca cu ușurință lucrurile. Mai ales dacă încercați să faceți grafică HD. Foile mari de sprite pot fi împărțite în mai multe PNG-uri, preluând RAM prețios și răsfoind dimensiunea jocului dacă nu sunteți atent.

2. Nu este dinamică

Ce se întâmplă atunci când doriți să accelerați o animație? Ai putea sări peste niște cadre, dar cum rămâne cu încetinirea? Animația ar arăta amețită și urâtă. Chiar dacă doriți să suportați doar 60 de cadre pe secundă, ce se întâmplă dacă un computer poate rula jocul mai repede? Ați putea să aveți animații în culori cu jaw-dropping la rate de cadre mai ridicate fără a lucra în plus și ar fi bine să alegeți oricând modificarea ratei de înregistrare a jocului.

Și dacă vrei să se întâmple ceva când brațele jucătorului ajung într-un loc? Sau să-l facă să ridice ceva? Va trebui să marcați manual brațul pe toată durata animației, ceea ce poate dura mult timp, deoarece nu puteți obține date despre unde vreunul dintre membrele sale este dintr-o foaie de sprite.

3. Nu vă permite să faceți tranziții

Ce se întâmplă când jucătorul rulează și sare dintr-o dată? Se taie imediat animația de salt. Acest lucru pare a fi încurcat și acest lucru s-ar întâmpla de fiecare dată când animația trece într-o stare nouă. Va trebui să faceți o tranziție pentru fiecare pereche de animații pe care o aveți, ceea ce nu este doar consumator de timp insuficient, ci are și efectul negativ al creșterii utilizării RAM, după cum sa discutat mai devreme.


Alternativa

Utilizarea foilor de material nu numai că permite animațiilor să fie dinamice și să crească cu orice FPS, precum și să treacă ușor între oricare dintre cele două stări, dar de asemenea ia o cantitate mică de spațiu pe disc și de memorie RAM, comparativ cu bâzâitul!

Acest lucru nu este chiar foarte nou. Unele jocuri populare îl folosesc, cum ar fi Closure-ul recent popular. Singura sa limitare este că nu poate face animație cadru-cu-cadru (FBF), deoarece se bazează pe tweening - deci, dacă aveți explozii complexe, va trebui să utilizați foi de sprite.

Dar pentru o mulțime de cazuri, veți găsi că nu va trebui să faceți asta și este mai mult decât merită efortul de a avea un sistem de genul acesta pentru jocul dvs., deoarece unele jocuri s-ar putea baza pe acest lucru, aruncându-se de o tonă . De asemenea, este foarte cool pentru că este similar cu modul în care puteți anima un joc 3D!

Deci, pentru a rezuma:


Să ne dăm dreptate

Acesta este un caracter și foaia de inventar.

După cum sugerează și numele, o fișă de activ este un PNG cu toate membrele / activele caracterului sau obiectului separate.
Și aici sunt datele de animație în JSON (desigur, puteți utiliza oricare format doriți să lucrați cu):

 // acest fragment prezintă primele trei cadre ale animației "Body" "-name": "Body", "Frame": "" -x ":" - ":" - ":" - ":" - ":" 0.000 ", y ":" - 64,05 "," rotație ":" 0,707 "

Acum combinând aceste două împreună într-un motor minunat, veți obține:

Și, spre deosebire de o animație blițată, acest lucru ar putea accelera sau crește, sau tranziția foarte liniștită. Deci, asta vom face.


Pasul 1: Exportul fișei dvs. de active

Primul pas este să vă pregătiți fișa de inventar. Puteți face acest lucru în mai multe moduri. Ideea este să se încheie cu o foaie care conține activele și un fișier de date care conține pozițiile activelor în foaie. Aceasta este exact aceeași metodă ca și pentru crearea unei foi de sprite, cu excepția faptului că în locul spritelor adăugați active separate.

Exportați membrele și piesele player-ului ca PNG-uri individuale, apoi utilizați un program precum Texture Packer pentru a le grupa într-o foaie. Există și alte programe, dar eu personal prefer Texture Packer din cauza cât de versatil și bogat în caracteristici este.

Bacsis: Indiferent de software-ul pe care îl utilizați pentru a vă face foile, asigurați-vă că există cel puțin 2 pixeli de umplutură între fiecare material și extrudare 1px. Acest lucru va preveni unele probleme urâte în viitor.

Pasul 2: Exportați datele de animație

Acesta este, fără îndoială, cel mai important pas, deoarece acestea vor fi datele pe care le folosiți pentru a crea toate animațiile în timpul run-time. De asemenea, este important pentru că este independent de platformă. Puteți folosi aceleași date de animație pe un PS3 ca pe un iPhone.

Datele de care aveți nevoie sunt poziția x, poziția y, valoarea rotației și alte proprietăți ale fiecărui element pentru fiecare cadru al animației dvs..

Dacă utilizați Adobe Flash pentru a anima, puteți să exportați cu ușurință datele de animație. În teorie, tot ce trebuie să faceți este să vă răsuciți prin copiii lui MovieClip și să treceți prin cadre în timp ce obțineți datele.

Cu toate acestea, aceasta poate fi o provocare. Din fericire, există instrumente care fac deja acest lucru. De exemplu, Grapefrukt este un instrument minunat care are o varietate de caracteristici, inclusiv exportul de sprite, precum și de date de animație în XML.

Notă: Trebuie să vă asigurați că numele activelor dvs. din date corespund cu numele din fișa de materiale, astfel încât acestea să poată fi ușor asociate.

Dacă încercați să-l modificați sau dacă doriți doar caracteristica simplă a exportării de animație, puteți opta să folosiți propria mea clasă de exportatoare de animație, care exportă automat date de animație într-un fișier JSON din același director. Puteți descărca aici, împreună cu o fișă cu exemple de materiale și o animație de exemplu.

Dacă utilizați alt software de animație (sau propriul dvs.) nu ar trebui să fie prea greu să găsiți sau să scrieți un plugin care să exporte coordonatele și datele materialelor la fiecare cadru.

Iată o listă cu toate atributele pe care exportatorii Flash le produc pentru fiecare produs:

  • X și y
  • rotație (în grade sau radiani)
  • scaleX și scaleY (cât de mult este scalarea activului pe fiecare axă)
  • alfa (transparenţă)
  • COLORMATRIX (vă permite să exportați date cum ar fi luminozitatea, nuanța și contrastul)

Nu există nicio limită pentru cantitatea de date pe care o puteți transmite. De exemplu, am adăugat un extra adâncime câmp în exportatorul meu care îmi spune profunzimea fiecărui bun. Deci, dacă animatorul aranjează activele într-o anumită ordine sau modifică straturile, acestea se actualizează automat în motor.

Așa cum puteți vedea, puteți face o mulțime de diferite tipuri de animație și caracteristici cu datele potrivite.


Pasul 3: Parsarea datelor

Așa că acum ți-ai pregătit foaia de inventar, fișierul de date și animația JSON. În continuare vine partea cea mai dificilă: scrierea sistemului de animație care înțelege datele noastre și transformă activele separate și datele brute într-o animație frumoasă.

Primul pas este să încărcați datele de animație. Acest lucru ar trebui să fie ușor deoarece majoritatea limbilor au un parser JSON sau XML.

Apoi, împărțiți fiecare material din foaie (sau, mai degrabă, faceți dreptunghiul numai cu activul dvs.) și păstrați-i într-o matrice.

Deci acum obiectele noastre de joc au două matrice: an assetArray care are activele reale, și o animationArray care are datele de animație.

Notă: Poate doriți să indexați animationArray și dați numele activelor. Acest lucru este astfel încât să puteți accesa cu ușurință datele corecte din matricea de animație - deci dacă tipăresc valoarea object.assetArray [5] .name, Mi-ar lua "picior", de exemplu. Atunci, dacă mă duc și voi avea acces object.animationArray [ "picior"], Ar trebui să obțin datele de animație pentru piciorul personajului.

Acum, să vedem un cod!

 /// În interiorul funcției de actualizare a obiectului var animationArray: Array = object.animationArray; var activArray: Array = object.assetArray; / / ne forțăm prin toate activele pentru (var i: int = 0; i < assetArray.length; i++) assetArray[i].x = object.x; assetArray[i].y = object.y; assetArray[i].angle = object.angle; 

Până în prezent, ne străduim prin toate bunurile să le punem X, y și rotație la cea a obiectului mamei. Acest lucru este important pentru ca obiectele dvs. să se poată deplasa fără a distruge animația, astfel încât coordonatele de animație să fie relative la acel punct.

 /// În interiorul funcției de actualizare a obiectului var animationArray: Array = object.animationArray; var activArray: Array = object.assetArray; / / ne forțăm prin toate activele pentru (var i: int = 0; i 

Aici am adăugat linia + animationArray [assetArray [i] .name] [currentFrame] .x, Unde currentFrame este un număr întreg reprezentând cadrul curent în care vă aflați.

Acum, toate activele ar fi la primele lor poziții de cadru, așa că odată ce creșteți currentFrame, ei ar fi în pozițiile Cadrului 2 și așa mai departe.

Felicitări, ați creat animație! Se pare identic cu modul în care ați fi făcut-o cu o foaie de sprite, cu excepția faptului că vă costă doar câteva kilobyte în loc de megaocteți.

Acesta este doar un exemplu foarte simplu. În mod normal, doriți să aveți animații separate, cum ar fi o animație "care rulează" cu 30 de cadre și o animație "salt" cu 12 cadre. Pentru a face acest lucru, ați adăuga un alt strat la ierarhia de animație, astfel încât să pară ceva similar:


Pasul 4: Interpolare

Nu trebuie să ne oprim acolo. Vrem să încercăm să facem animațiile noastre la fel de netede și dinamice așa cum am promis.

În mod normal, acest lucru ar fi ceva destul de dificil - ar trebui să stocăm starea completă a cadrului precedent pentru a interpola curentul. Dar, din fericire, sistemul nostru stochează deja aceste informații!

Tu mereu știți unde a fost cadrul anterior și unde va fi următorul cadru, astfel încât interpolarea între cadre este la fel de simplă:

 var data: Array = animațieArray [assetArray [i] .name] var X: număr = date [currentFrame] .x + (date [currentFrame + 1]. assetArray [i] .x = obiect.x + X

Aici avem diferența dintre următorul cadru și cadrul curent, înmulțit cu a timeFactor care este timp între cele două cadre.

Acest lucru înseamnă că, în loc de animația dvs., arătați astfel în mișcare lentă:


... ar arata astfel:


Lua acea, blitting!


Pasul bonus: Matricea culorilor

Dacă utilizați Flash pentru a anima, matricea dvs. de culoare poate arăta astfel:

1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0

Nu este foarte lizibil acum?

Flash stochează toate datele de luminozitate, contrast și saturație acolo. Din fericire, ei și-au postat formularul, așa că nu trebuie să încercăm să inversăm acest lucru.

Formula de mai jos vă arată cum să calculați valorile finale RGBA ale pixelului date culorii sursă și matricei de culoare (A este matricea de matrice de culoare):

 [a] [a] [a] [a] [a] [a] [a] [a] (a [8] * srcB) + (a [6] * srcR) + (a [7] * srcB) * srcG) + (a [12] * srcB) + (a [13] * srcA) + a [14] alphaResult = ] * srcB) + (a [18] * srcA) + a [19]

Mai multe informații despre Flash ColorMatrix clasa poate fi găsită aici.


Concluzie și studiu de caz

Deși ar putea părea un pic înfricoșător la început, această metodă este într-adevăr ușor de utilizat atunci când totul este configurat, și stabilirea unei baze adecvate merită puțin timp și efort.

Aceasta nu înseamnă că această metodă este ideală pentru fiecare situație. Așa cum am menționat anterior, dacă jocul dvs. se bazează pe animație cadru-cu-cadru sau pe lucruri care nu pot fi făcute cu adăugarea, atunci acest lucru nu ar funcționa. (Deși ați putut întotdeauna să amestecați și să potriviți metodele.)

Cu aceasta a spus, să aruncăm o privire la un exemplu final din lumea reală a utilizării acestei metode.

Aceasta este o ușă:

Se deschide și se închide și vrei ca jucătorul să nu poată trece prin el.

E simplu, nu? Ați avea o cutie de coliziune să se deplaseze vertical, în funcție de numărul de cadre prin animație. Problema este însă că această animație nu este liniară: există o ușoară ușurare. Potrivirea poziției verticale a casetei de coliziune cu cadrul actual al animației ar face ca caseta de coliziune să nu se sincronizeze cu animația, făcând lucrurile să pară ca ele să treacă fie prin ușă, fie să stea în aer subțire.

Din fericire, tu ai X, y, înălţime și lăţime din activul ușii animate, permițându-vă să vă sincronizați perfect coliziunea!


Blitz vs tabele de materiale