Ce trebuie să știți când convertiți un joc flash în HTML5?

Publicat: 2022-03-10
Rezumat rapid ↬ Sfaturile prezentate în acest articol urmăresc să ajute dezvoltatorii de jocuri HTML5 să evite greșelile obișnuite atunci când își convertesc jocurile Flash în JavaScript, precum și să facă ca întregul proces de dezvoltare să se desfășoare cât mai ușor posibil. Sunt necesare cunoștințe de bază despre JavaScript, WebGL și cadrul Phaser.

Odată cu creșterea utilizării HTML5, multe companii încep să-și refacă cele mai populare titluri pentru a scăpa de Flash învechit și pentru a-și potrivi produsele la cele mai recente standarde din industrie. Această schimbare este vizibilă în special în industria jocurilor de noroc/cazinourilor și divertismentului și are loc de câțiva ani, așa că o selecție decentă de titluri a fost deja convertită.

Din păcate, atunci când navighezi pe internet, te poți împiedica destul de des de exemple de muncă aparent grăbită, ceea ce are ca rezultat calitatea de iubitor a produsului final. De aceea, este o idee bună ca dezvoltatorii de jocuri să-și dedice o parte din timpul lor pentru a se familiariza cu subiectul conversiei Flash în HTML5 și pentru a învăța ce greșeli trebuie evitate înainte de a se apuca de treabă.

Printre motivele pentru care alegeți JavaScript în loc de Flash, în afară de problemele tehnice evidente, se numără și faptul că schimbarea designului jocului dvs. de la SWF la JavaScript poate oferi o experiență mai bună pentru utilizator, care, la rândul său, îi conferă un aspect modern. Dar cum se face? Aveți nevoie de un convertor de jocuri JavaScript dedicat pentru a scăpa de această tehnologie învechită? Ei bine, conversia Flash în HTML5 poate fi o simplă simplă - iată cum să aveți grijă de ea.

Lectură recomandată : Principiile designului jocului HTML5

Cum să îmbunătățiți experiența de joc HTML5

Convertirea unui joc pe o altă platformă este o oportunitate excelentă de a-l îmbunătăți, de a-i rezolva problemele și de a crește audiența. Mai jos sunt câteva lucruri care pot fi făcute cu ușurință și care merită luate în considerare:

  • Suport dispozitive mobile
    Conversia din Flash în JavaScript permite atingerea unui public mai larg (utilizatori de dispozitive mobile); De obicei, suportul pentru controalele ecranului tactil trebuie implementat și în joc. Din fericire, atât dispozitivele Android, cât și iOS acceptă acum și WebGL, astfel încât randarea la 30 sau 60 FPS poate fi de obicei realizată cu ușurință. În multe cazuri, 60 FPS nu va provoca probleme, ceea ce doar se va îmbunătăți cu timpul, pe măsură ce dispozitivele mobile devin din ce în ce mai performante.

  • Îmbunătățirea performanței
    Când vine vorba de compararea ActionScript și JavaScript, acesta din urmă este mai rapid decât primul. În afară de asta, convertirea unui joc este o ocazie bună pentru a revizui algoritmii utilizați în codul jocului. Cu dezvoltarea jocurilor JavaScript le puteți optimiza sau elimina complet codul neutilizat care a rămas de dezvoltatorii originali.
  • Remedierea erorilor și îmbunătățirea jocului
    Dacă dezvoltatorii noi caută codul sursă al jocului, poate ajuta la remedierea erorilor cunoscute sau la descoperirea unora noi și foarte rare. Acest lucru ar face ca jocul să fie mai puțin iritant pentru jucători, ceea ce i-ar face să petreacă mai mult timp pe site-ul tău și i-ar încuraja să încerce celelalte jocuri ale tale.
  • Adăugarea de analize web
    Pe lângă urmărirea traficului, analiza web poate fi folosită și pentru a aduna cunoștințe despre cum se comportă jucătorii într-un joc și unde se blochează în timpul jocului.
  • Adăugarea localizării
    Acest lucru ar crește audiența și este important pentru copiii din alte țări care îți joacă jocul. Sau poate că jocul tău nu este în engleză și vrei să susții acea limbă?
Mai multe după săritură! Continuați să citiți mai jos ↓

De ce omiterea HTML și CSS pentru interfața de utilizare în joc va îmbunătăți performanța jocului

Când vine vorba de dezvoltarea jocurilor JavaScript, poate fi tentant să folosiți HTML și CSS pentru butoanele, widget-urile și alte elemente GUI din joc. Sfatul meu este să fii atent aici. Este contraintuitiv, dar folosirea elementelor DOM este mai puțin performantă pe jocurile complexe, iar acest lucru capătă mai multă importanță pe mobil. Dacă doriți să obțineți 60 FPS constant pe toate platformele, atunci poate fi necesară demisia de la HTML și CSS.

Elementele GUI non-interactive, cum ar fi barele de sănătate, barele de muniție sau contoarele de scoruri pot fi implementate cu ușurință în Phaser folosind imagini obișnuite (clasa Phaser.Image ), utilizând proprietatea .crop pentru tăiere și clasa Phaser.Text pentru simplă. etichete de text.

Elemente interactive precum butoanele și casetele de selectare pot fi implementate folosind clasa Phaser.Button . Alte elemente, mai complexe, pot fi compuse din diferite tipuri simple, cum ar fi grupuri, imagini, butoane și etichete de text.

Notă: De fiecare dată când instanțiați un obiect Phaser.Text sau PIXI.Text, este creată o nouă textură pentru a reda textul. Această textură suplimentară rupe loturile de vârfuri, așa că aveți grijă să nu aveți prea multe dintre ele .

Cum să vă asigurați că s-au încărcat fonturile personalizate

Dacă doriți să randați textul cu un font vectorial personalizat (de exemplu, TTF sau OTF), atunci trebuie să vă asigurați că fontul a fost deja încărcat de browser înainte de a randa orice text. Phaser v2 nu oferă o soluție în acest scop, dar poate fi folosită o altă bibliotecă: Web Font Loader.

Presupunând că aveți un fișier cu font și că includeți aplicația Web Font Loader în pagina dvs., mai jos este un exemplu simplu despre cum să încărcați un font:

Creați un fișier CSS simplu care va fi încărcat de Web Font Loader (nu trebuie să îl includeți în HTML):

 @font-face { // This name you will use in JS font-family: 'Gunplay'; // URL to the font file, can be relative or absolute src: url('../fonts/gunplay.ttf') format('truetype'); font-weight: 400; }

Acum definiți o variabilă globală numită WebFontConfig . Ceva atât de simplu ca acesta va fi de obicei suficient:

 var WebFontConfig = { 'classes': false, 'timeout': 0, 'active': function() { // The font has successfully loaded... }, 'custom': { 'families': ['Gunplay'], // URL to the previously mentioned CSS 'urls': ['styles/fonts.css'] } };

La sfârșit, nu uitați să vă puneți codul în apelul „activ” afișat mai sus. Si asta e!

Cum să fie mai ușor pentru utilizatori să salveze jocul

Pentru a stoca constant date locale în ActionScript, ați folosi clasa SharedObject. În JavaScript, înlocuirea simplă este localStorage API, care permite stocarea șirurilor de caractere pentru recuperarea ulterioară, supraviețuind reîncărcărilor paginilor.

Salvarea datelor este foarte simplă:

 var progress = 15; localStorage.setItem('myGame.progress', progress);

Rețineți că, în exemplul de mai sus, variabila de progress , care este un număr, va fi convertită într-un șir.

Încărcarea este de asemenea simplă, dar rețineți că valorile preluate vor fi șiruri de caractere sau null dacă nu există.

 var progress = parseInt(localStorage.getItem('myGame.progress')) || 0;

Aici ne asigurăm că valoarea returnată este un număr. Dacă nu există, atunci 0 va fi atribuit variabilei de progress .

De asemenea, puteți stoca și prelua structuri mai complexe, de exemplu, JSON:

 var stats = {'goals': 13, 'wins': 7, 'losses': 3, 'draws': 1}; localStorage.setItem('myGame.stats', JSON.stringify(stats)); … var stats = JSON.parse(localStorage.getItem('myGame.stats')) || {};

Există unele cazuri când obiectul localStorage nu va fi disponibil. De exemplu, când utilizați protocolul file:// sau când o pagină este încărcată într-o fereastră privată. Puteți folosi instrucțiunea try and catch pentru a vă asigura că codul va continua să funcționeze și va folosi valorile implicite, ceea ce este arătat în exemplul de mai jos:

 try { var progress = localStorage.getItem('myGame.progress'); } catch (exception) { // localStorage not available, use default values }

Un alt lucru de reținut este că datele stocate sunt salvate pe domeniu, nu pe adresă URL. Deci, dacă există riscul ca multe jocuri să fie găzduite pe un singur domeniu, atunci este mai bine să utilizați un prefix (spațiu de nume) la salvare. În exemplul de mai sus 'myGame.' este un astfel de prefix și de obicei doriți să-l înlocuiți cu numele jocului.

Notă : dacă jocul dvs. este încorporat într-un iframe, atunci localStorage nu va persista pe iOS. În acest caz, ar trebui să stocați datele în iframe-ul părinte .

Cum să folosiți înlocuirea implicită a Fragment Shader

Când Phaser și PixiJS redă sprite-urile dvs., ele folosesc un simplu shader intern de fragmente. Nu are multe caracteristici pentru că este croit pentru o viteză. Cu toate acestea, puteți înlocui acel shader pentru scopurile dvs. De exemplu, îl puteți folosi pentru a inspecta overdraw sau pentru a accepta mai multe caracteristici pentru randare.

Mai jos este un exemplu despre cum să vă furnizați propriul shader de fragmente implicit la Phaser v2:

 function preload() { this.load.shader('filename.frag', 'shaders/filename.frag'); } function create() { var renderer = this.renderer; var batch = renderer.spriteBatch; batch.defaultShader = new PIXI.AbstractFilter(this.cache.getShader('filename.frag')); batch.setContext(renderer.gl); }

Notă: Este important să rețineți că shaderul implicit este utilizat pentru TOATE sprite-urile, precum și atunci când se redă o textură. De asemenea, rețineți că utilizarea shaderelor complexe pentru toate sprite-urile din joc va reduce foarte mult performanța de randare .

Cum să schimbați metoda de nuanță cu un shader implicit

Shaderul implicit personalizat poate fi folosit pentru a înlocui metoda de nuanță implicită în Phaser și PixiJS.

Nuanțarea în Phaser și PixiJS funcționează prin înmulțirea pixelilor de textură cu o anumită culoare. Înmulțirea întunecă întotdeauna culorile, ceea ce, evident, nu este o problemă; pur și simplu este diferit de nuanțarea Flash. Pentru unul dintre jocurile noastre, trebuia să implementăm o nuanță similară cu Flash și am decis că ar putea fi folosit un shader implicit personalizat. Mai jos este un exemplu de astfel de shader de fragmente:

 // Specific tint variant, similar to the Flash tinting that adds // to the color and does not multiply. A negative of a color // must be supplied for this shader to work properly, ie set // sprite.tint to 0 to turn whole sprite to white. precision lowp float; varying vec2 vTextureCoord; varying vec4 vColor; uniform sampler2D uSampler; void main(void) { vec4 f = texture2D(uSampler, vTextureCoord); float a = clamp(vColor.a, 0.00001, 1.0); gl_FragColor.rgb = f.rgb * vColor.a + clamp(1.0 - vColor.rgb/a, 0.0, 1.0) * vColor.a * fa; gl_FragColor.a = fa * vColor.a; }

Acest shader luminează pixelii adăugând o culoare de bază celei de nuanță. Pentru ca acest lucru să funcționeze, trebuie să furnizați negativ de culoarea dorită. Prin urmare, pentru a obține alb, trebuie să setați:

 sprite.tint = 0x000000; // This colors the sprite to white Sprite.tint = 0x00ffff; // This gives red

Rezultatul în jocul nostru arată astfel (observați cum tancurile clipesc alb când sunt lovite):

Exemplu de shader implicit personalizat în dezvoltarea jocului
Shader implicit personalizat (rezervoarele clipind în alb).

Cum să inspectați overdraw pentru a detecta problemele cu rata de umplere

Înlocuirea shaderului implicit poate fi, de asemenea, folosită pentru a ajuta la depanare. Mai jos am explicat cum poate fi detectat overdraw cu un astfel de shader.

Suprasenarea are loc atunci când mulți sau toți pixelii de pe ecran sunt randați de mai multe ori. De exemplu, multe obiecte ocupă același loc și sunt redate unele peste altele. Câți pixeli poate reda un GPU pe secundă este descris ca rata de umplere. GPU-urile desktop moderne au o rată de umplere excesivă pentru scopuri 2D obișnuite, dar cele mobile sunt mult mai lente.

Există o metodă simplă de a afla de câte ori este scris fiecare pixel de pe ecran, înlocuind shaderul global implicit de fragment în PixiJS și Phaser cu acesta:

 void main(void) { gl_FragColor.rgb += 1.0 / 7.0; }

Acest shader luminează pixelii care sunt procesați. Numărul 7.0 indică câte scrieri sunt necesare pentru a albi pixelii; puteți acorda acest număr după bunul plac. Cu alte cuvinte, pixelii mai ușori de pe ecran au fost scrisi de mai multe ori, iar pixelii albi au fost scrisi de cel puțin 7 ori.

Acest shader ajută, de asemenea, la găsirea atât a obiectelor „invizibile” care, din anumite motive, sunt încă redate, cât și a sprite-urilor care au zone transparente excesive în jurul cărora trebuie să fie îndepărtate (GPU-ul trebuie încă să proceseze pixeli transparenți în texturile tale).

Exemplu de shader Overdraw în acțiune în dezvoltarea jocului
Overdraw shader în acțiune. (Previzualizare mare)

Imaginea din stânga arată modul în care un jucător vede jocul, în timp ce cea din dreapta afișează efectul aplicării umbririi overdraw la aceeași scenă.

De ce motoarele fizice sunt prietenii tăi

Un motor de fizică este un middleware care este responsabil pentru simularea corpurilor fizice (de obicei dinamica corpului rigid) și a coliziunilor lor. Motoarele fizice simulează spații 2D sau 3D, dar nu ambele. Un motor fizic tipic va oferi:

  • mișcarea obiectului prin setarea vitezelor, accelerațiilor, articulațiilor și motoarelor;
  • detectarea coliziunilor între diferite tipuri de forme;
  • calcularea răspunsurilor la ciocnire, adică modul în care două obiecte ar trebui să reacționeze atunci când se ciocnesc.

La Merixstudio, suntem mari fani ai motorului de fizică Box2D și l-am folosit de câteva ori. Există un plugin Phaser care funcționează bine în acest scop. Box2D este folosit și în motorul de joc Unity și GameMaker Studio 2.

În timp ce un motor de fizică vă va accelera dezvoltarea, există un preț pe care va trebui să-l plătiți: performanță redusă la timp de rulare. Detectarea coliziunilor și calcularea răspunsurilor este o sarcină intensivă de CPU. Este posibil să fiți limitat la câteva zeci de obiecte dinamice într-o scenă pe telefoanele mobile sau să vă confruntați cu performanțe degradate, precum și cu o rată de cadre redusă sub 60 FPS.

Exemplu de diferență în scena unui joc cu și fără suprapunerea noastră de depanare a fizicii Phaser afișată în partea de sus
Suprapunerea de depanare a fizicii lui Phaser. (Previzualizare mare)

Partea din stânga a imaginii este o scenă dintr-un joc, în timp ce partea dreaptă arată aceeași scenă cu suprapunerea de depanare a fizicii Phaser afișată în partea de sus.

Cum se exportă sunete dintr-un fișier .fla

Dacă aveți efecte de sunet pentru un joc Flash în interiorul unui fișier .fla , atunci exportul lor din GUI nu este posibil (cel puțin nu în Adobe Animate CC 2017) din cauza lipsei opțiunii de meniu care să servească acest scop. Dar există o altă soluție - un script dedicat care face exact asta:

 function normalizeFilename(name) { // Converts a camelCase name to snake_case name return name.replace(/([AZ])/g, '_$1').replace(/^_/, '').toLowerCase(); } function displayPath(path) { // Makes the file path more readable return unescape(path).replace('file:///', '').replace('|', ':'); } fl.outputPanel.clear(); if (fl.getDocumentDOM().library.getSelectedItems().length > 0) // Get only selected items var library = fl.getDocumentDOM().library.getSelectedItems(); else // Get all items var library = fl.getDocumentDOM().library.items; // Ask user for the export destination directory var root = fl.browseForFolderURL('Select a folder.'); var errors = 0; for (var i = 0; i < library.length; i++) { var item = library[i]; if (item.itemType !== 'sound') continue; var path = root + '/'; if (item.originalCompressionType === 'RAW') path += normalizeFilename(item.name.split('.')[0]) + '.wav'; else path += normalizeFilename(item.name); var success = item.exportToFile(path); if (!success) errors += 1; fl.trace(displayPath(path) + ': ' + (success ? 'OK' : 'Error')); } fl.trace(errors + ' error(s)');

Cum să utilizați scriptul pentru a exporta fișiere de sunet:

  1. Salvați codul de mai sus ca fișier .jsfl pe computer;
  2. Deschideți un fișier .fla cu Adobe Animate;
  3. Selectați „Comenzi” → „Run Command” din meniul de sus și selectați scriptul în dialogul care se deschide;
  4. Acum apare un alt fișier de dialog pentru selectarea directorului de destinație de export.

Și gata! Acum ar trebui să aveți fișiere WAV în directorul specificat. Ceea ce rămâne de făcut este să le convertești, de exemplu, în MP3, OGG sau AAC.

Cum să utilizați fișierele MP3 în conversiile Flash în HTML5

Vechiul format MP3 a revenit, deoarece unele brevete au expirat și acum fiecare browser poate decoda și reda MP3-uri. Acest lucru face dezvoltarea puțin mai ușoară, deoarece în sfârșit nu este nevoie să pregătiți două formate audio separate. Anterior aveai nevoie, de exemplu, de fișiere OGG și AAC, în timp ce acum MP3 va fi suficient.

Cu toate acestea, există două lucruri importante pe care trebuie să le rețineți despre MP3:

  • Necesitatea MP3-urilor de a decoda după încărcare, ceea ce poate consuma mult timp, mai ales pe dispozitivele mobile. Dacă vedeți o pauză după ce s-au încărcat toate activele, atunci probabil înseamnă că MP3-urile sunt decodate;
  • Redarea fără întrerupere a MP3-urilor în buclă este puțin problematică. Soluția este să folosești mp3loop, despre care poți citi în articolul postat de Compu Phase.

Deci, de ce ar trebui să convertiți Flash în JavaScript?

După cum puteți vedea, conversia Flash în JavaScript nu este imposibilă dacă știți ce să faceți. Cu cunoștințe și pricepere, puteți înceta să vă mai luptați cu Flash și să vă bucurați de jocurile fluide și distractive create în JavaScript. Nu încercați să reparați Flash - scăpați de el înainte ca toată lumea să fie forțată să facă asta!

Doriți să aflați mai multe?

În acest articol, m-am concentrat în principal pe Phaser v2. Cu toate acestea, o versiune mai nouă a Phaser este acum disponibilă și vă încurajez cu tărie să o verificați, deoarece a introdus o multitudine de caracteristici proaspete, interesante, cum ar fi mai multe camere, scene, hărți în tile sau motorul fizic Matter.js.

Dacă sunteți suficient de curajos și doriți să creați lucruri cu adevărat remarcabile în browsere, atunci WebGL este lucrul potrivit pentru a învăța de la zero. Este un nivel mai scăzut de abstractizare decât diferitele cadre sau instrumente de construire a jocurilor, dar vă permite să obțineți o performanță și o calitate mai mari chiar dacă lucrați la jocuri 2D sau demonstrații. Printre multe site-uri web pe care le puteți găsi utile atunci când învățați elementele de bază ale WebGL ar fi WebGL Fundamentals (folosește demonstrații interactive). În plus, pentru a afla mai multe despre ratele de adoptare a caracteristicilor WebGL, verificați WebGL Stats.

Amintiți-vă întotdeauna că nu există prea multe cunoștințe – mai ales când vine vorba de dezvoltarea jocurilor!