În acest tutorial, vă ajut să creați nivele pentru orice gen de joc și să faceți mult mai ușor nivelurile de proiectare. Veți învăța cum să vă creați primul motor de hartă a țiglelor pentru a fi utilizat în oricare dintre proiectele viitoare. O să folosesc Haxe cu OpenFL, dar ar trebui să puteți urmări în orice limbă.
Iată ce vom acoperi:
S-ar putea să începi bine și o idee de joc nouă!
Firește, Wikipedia are o definiție în profunzime a jocului pe bază de țiglă, dar pentru a obține un conținut de bază, există doar câteva lucruri pe care trebuie să le cunoașteți:
Pentru a obține chiar mai mult de bază, o voi spune așa:
Un joc bazat pe țiglă creează plăci pentru a crea fiecare nivel.
În ceea ce privește tipurile de plăci obișnuite - dreptunghiulare și izometrice - vom folosi plăci dreptunghiulare în acest articol pentru simplitatea lor. Dacă decideți să încercați niște niveluri izometrice într-o zi, există matematică suplimentară implicată pentru ca aceasta să funcționeze. (Odată ce ați terminat aici, verificați acest amorsor excelent pentru a crea lumi izometrice.)
Există câteva beneficii minunate pe care le obțineți de la utilizarea unui motor de țiglă. Cel mai aparent perk este că nu va trebui să creați imagini masive cu mâna pentru fiecare nivel individual. Acest lucru va reduce timpul de dezvoltare și va reduce dimensiunile fișierelor. Având 50 de imagini de 1280x768 px pentru un joc pe 50 de niveluri, având o singură imagine cu 100 de plăci, este o diferență enormă.
Un alt efect secundar este că localizarea lucrurilor pe hartă folosind codul devine puțin mai ușoară. În loc de a verifica lucruri cum ar fi coliziunea bazată pe un pixel exact, puteți utiliza o formulă rapidă și ușoară pentru a determina ce țiglă trebuie să accesați. (Voi trece peste asta un pic mai târziu.)
Primul lucru pe care îl veți avea nevoie atunci când vă construiți un motor de țiglă este un set de plăci. Aveți două opțiuni: utilizați dalele altcuiva sau creați-vă propriile.
Dacă decideți să utilizați plăci care au fost deja făcute, puteți găsi artă disponibilă gratuit pe tot cuprinsul webului. Dezavantajul este că arta nu a fost făcută special pentru jocul tău. Pe de altă parte, dacă sunteți doar prototipuri sau încercați să învățați un nou concept, plăcile libere vor face truc.
Există destul de puține resurse acolo pentru artă liberă și open source. Iată câteva locuri pentru a începe căutarea dvs.:
Aceste trei link-uri ar trebui să vă ofere mai mult decât suficiente locuri pentru a găsi niște dale decente pentru prototipurile dvs. Înainte de a merge nebun grabbing tot ce găsiți, asigurați-vă că ați înțeles ce licență totul este acoperit și ce restricții au venit cu. Multe licențe vă vor permite să utilizați arta în mod liber și pentru uz comercial, dar ar putea necesita atribuire.
Pentru acest tutorial, am folosit niște dale de la un joc de artă Open Game Art for platformers. Puteți descărca versiunile scalate sau originalele.
Dacă nu ați făcut încă plinul de a face arta pentru jocurile dvs., ar putea fi un pic intimidant. Din fericire, există niște bucăți de software uimitoare și simple care vă ajută să ajungeți în gros, astfel încât să puteți începe să practicați.
Mulți dezvoltatori încep cu arta pixelilor pentru jocurile lor și aici sunt câteva instrumente minunate pentru că:
Acestea sunt unele dintre cele mai populare programe pentru realizarea artei pixelilor. Dacă doriți ceva mai puternic, GIMP este o opțiune excelentă. Puteți face, de asemenea, unele artă vectorială cu Inkscape și urmați câteva tutoriale uimitoare de la 2D Game Art For Programmers.
Odată ce ați apucat de software-ul puteți începe experimentarea cu a face propriile dvs. plăci. Deoarece acest tutorial este menit să vă arate cum să vă creați harta țiglelor motor Nu voi intra prea mult în detaliu despre realizarea propriu-zise a plăcilor, dar trebuie să țineți minte un singur lucru:
Asigurați-vă că plăcile se potrivesc perfect și adăugați unele variante pentru a le menține interesante.
Dacă țiglele tale prezintă linii evidente între ele când se pun împreună, jocul nu va arăta foarte frumos. Asigurați-vă că ați pus ceva timp în crearea unui "puzzle" plăcut de plăci, făcându-le fără probleme și adăugând unele variații.
Acum, avem toate aceste lucruri de artă în afara de drum, putem scufunda în cod pentru a pune dvs. nou dobândite (sau creat) țigle pe ecran.
Să începem cu sarcina de bază de a afișa o singură țiglă pe ecran. Asigurați-vă că plăcile dvs. au aceeași dimensiune și sunt salvate în fișiere separate de imagini (vom vorbi mai târziu despre foile de sprite).
Odată ce ai gresie în dosarul cu active al proiectului tău, poți scrie foarte simplu Ţiglă
clasă. Iată un exemplu în Haxe:
import flash.display.Sprite; import flash.display.Bitmap; import openfl.Assets; clasa Tile se extinde Sprite private var imagine: Bitmap; funcția publică nouă () super (); image = Bitmap nou (Assets.getBitmapData ("assets / grassLeftBlock.png")); addChild (imagine);
Deoarece tot ceea ce facem acum este să punem o singură țiglă pe ecran, singurul lucru pe care îl face clasa este să importați imaginea țiglă din bunuri
folder și adăugați-l ca un copil la obiect. Această clasă va varia probabil foarte mult pe baza limbajului de programare pe care îl utilizați, dar ar trebui să puteți găsi cu ușurință un ghid despre cum să afișați o imagine pe ecran.
Acum că avem a Ţiglă
class, trebuie să creăm o instanță a Ţiglă
și adăugați-o la clasa noastră principală:
import flash.display.Sprite; importul flash.events.Event; import flash.Lib; class Main extinde Sprite funcția publică nouă () super (); var tile = Placi noi (); addChild (tigla); funcția statică publică principală () Lib.current.addChild (new Main ());
Principal
clasa creează un nou Ţiglă
când constructorul ( nou()
, numită atunci când începe jocul) este apelată și o adaugă în lista de afișare.
Când jocul este rulat, principal()
funcția va fi de asemenea numită și o nouă Principal
obiect va fi adăugat la etapă. Ar trebui să aveți acum țigla dvs. care apare în partea din stânga sus a ecranului. Până acum, bine.
Bacsis: Dacă nici unul dintre aceste lucruri nu are sens - nu vă faceți griji! Este vorba doar de codul standard Haxe. Lucrul esențial de înțeles este că acest lucru creează o Ţiglă
obiect și îl adaugă pe ecran.
Următorul pas este să găsiți o modalitate de a umple întregul ecran cu plăci. Una dintre cele mai ușoare căi de a face acest lucru este să umplem o matrice cu numere întregi care reprezintă fiecare a ID-ul țiglei. Apoi puteți itera prin matrice pentru a decide care dale de afișat și unde să-l afișeze.
Aveți opțiunea de a utiliza o matrice tipică sau de a utiliza o matrice bidimensională. În cazul în care nu sunteți familiarizați cu matrice 2D, este în principiu o singură matrice care este umplută cu mai multe matrice. Cele mai multe limbi vor denumi acest lucru ca fiind nameOfArray [x] [y]
Unde X
și y
sunt indicii pentru accesarea unui singur element.
De cand X
și y
sunt, de asemenea, utilizate pentru coordonatele ecranului, ar putea avea sens să folosească X
și y
ca coordonate pentru plăcile noastre. Trucul cu matrice 2D înțelege modul în care sunt organizate numerele întregi. S-ar putea să trebuiască să inversați y
și X
când iterăm prin matrice (exemplul de mai jos).
(0, 0, 0, 0), [0, 0, 0, 0, 0] 0], [0, 0, 0, 0, 0]];
Observați că în această implementare elementul "0" din matrice este el însuși o matrice, de cinci numere întregi. Acest lucru înseamnă că accesați fiecare element cu y
primul, atunci X
. Dacă încercați să accesați exampleArr [1] [0]
, ați accesa şaselea ţiglă.
Dacă nu înțelegeți bine modul în care funcționează matricele 2D chiar acum, nu vă faceți griji. Pentru acest tutorial voi folosi o matrice normală pentru a păstra lucrurile simple și pentru a face lucrurile mai ușor de vizualizat:
private var exampleArr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0];
Exemplul de mai sus arată modul în care o matrice normală poate fi puțin mai simplă. Putem vizualiza exact unde va fi tigla și tot ce trebuie să facem este să folosim o formulă simplă (nu vă îngrijorați, vine!) Pentru a obține tigla dorită.
Acum, să scriem un cod pentru a crea matricea noastră și ao completa cu una. Numărul unu va fi ID-ul care reprezintă prima noastră țiglă.
Mai întâi trebuie să creăm o variabilă în interiorul clasei noastre principale pentru a ține tabloul nostru:
privat harta var: Array;
Ar putea părea puțin ciudat, așa că o voi despică pentru tine.
Numele variabilei este harta și i-am dat un tip foarte specific: mulțime
.
porțiunea ne spune programului nostru că matricea va conține numai numere întregi. Arrays poate să dețină aproape orice tip pe care îl doriți, deci, dacă utilizați altceva pentru a vă identifica dalele, nu ezitați să modificați parametrul aici.
Apoi trebuie să adăugăm un cod la adresa noastră Principal
constructor de clasă (amintiți-vă, acesta este nou()
funcția) astfel încât să putem crea o instanță a hărții noastre:
map = array nou();
Această linie va crea o matrice goală pe care o putem umple în curând cu cele pentru a le testa. Mai întâi, să definim câteva valori care ne vor ajuta cu matematica noastră:
static public var TILE_WIDTH = 60; static public var TILE_HEIGHT = 60; statică publică var var SCREEN_WIDTH = 600; statică publică var SCREEN_HEIGHT = 360;
Am făcut aceste valori statică publică
pentru că acest lucru ne va permite accesul la acestea de oriunde din programul nostru (prin Main.Tile_WIDTH
si asa mai departe). De asemenea, s-ar putea să fi observat că împărțirea SCREEN_WIDTH
de TILE_WIDTH
ne ofera 10
și împărțirea SCREEN_HEIGHT
de TILE_HEIGHT
ne ofera 6
. Aceste două cifre vor fi folosite pentru a decide câte numere întregi să fie stocate în matricea noastră.
var = Std.int (SCREEN_WIDTH / TILE_WIDTH); var h = Std.int (SCREEN_HEIGHT / TILE_HEIGHT); pentru (i în 0 ... w * h) hartă [i] = 1
În acest bloc de cod, atribuim 10
și 6
la w
și h
, așa cum am menționat mai sus. Apoi trebuie să intrăm în a pentru
pentru a crea o matrice care se potrivește 10 * 6
numere întregi. Acest lucru va reprezenta suficientă plăci pentru a umple întregul ecran.
Acum ne-am construit harta de bază, dar cum vom spune plăcilor să intre în locul lor? Pentru asta trebuie să ne întoarcem la Ţiglă
clasa și să creeze o funcție care să ne permită să mutăm țigle după dorință:
funcția publică setLoc (x: Int, y: Int) image.x = x * Main.TILE_WIDTH; image.y = y * Main.TILE_HEIGHT;
Când sunăm setLoc ()
funcționează, trecem în X
și y
coordonează în funcție de clasa noastră de hartă (formula vine în curând, îți promit!). Funcția ia aceste valori și le traduce în coordonate pixel prin multiplicarea acestora TILE_WIDTH
și TILE_HEIGHT
, respectiv.
Singurul lucru pe care trebuie sa-l faci pentru a ne face pe ecran este sa ne spui Principal
clasa pentru a crea placi și a le pune în loc pe baza locațiilor lor în cadrul hărții. Să ne întoarcem Principal
și să pună în aplicare următoarele:
pentru (i în 0 ... map.length) var tile = țiglă nouă (); var x = i% w; var y = Math.floor (i / w); tile.setLoc (x, y); addChild (tigla);
Oh da! Așa-i, avem acum un ecran plin de țigle. Să descompunem ceea ce se întâmplă mai sus.
Formula pe care am menționat în continuare este în sfârșit aici.
Noi calculam X
prin luarea modulul (%
) de eu
și w
(care este de 10, amintiți-vă).
Modulul este doar restul după diviziunea întregului: \ (14 \ div 3 = 4 \ text remainder 2 \) so \ (14 \ text modulus 3 =.
Folosim acest lucru pentru că ne dorim valoarea noastră X
pentru a reveni la 0
la începutul fiecărui rând, așa că tragem țigla respectivă pe extrema stângă:
În ceea ce privește y
, noi luăm podea()
de i / w
(adică, noi rotunjim rezultatul în jos) pentru că vrem doar y
pentru a crește după ce am ajuns la sfârșitul fiecărui rând și am mutat un nivel:
Math.floor ()
atunci când împărțiți numere întregi; Haxe se ocupă doar de diviziunea întregului în mod diferit. Dacă utilizați o limbă care face diviziune întreg, puteți folosi doar i / w
(presupunând că ambele sunt întregi). În cele din urmă, am vrut să menționez un pic despre nivelurile de derulare. De obicei, nu veți crea nivele care se potrivesc perfect în portul de vizualizare. Hărțile dvs. vor fi probabil mult mai mari decât ecranul și nu doriți să continuați să desenați imagini pe care playerul nu le va putea vedea. Cu unele matematici rapide și ușoare, ar trebui să puteți calcula ce dale trebuie să fie pe ecran și ce dale pentru a evita desenul.
De exemplu: dimensiunea ecranului dvs. este de 500x500, plăcile dvs. sunt 100x100, iar dimensiunea dvs. la nivel mondial este de 1000x1000. Ar trebui pur și simplu să faceți o verificare rapidă înainte de desenarea plăcilor pentru a afla ce piese sunt pe ecran. Folosind locația portului de vizualizare - să zicem 400x500 - trebuie doar să desenați dale de la rândurile 4 la 9 și coloanele de la 5 la 10. Puteți obține aceste numere împărțind locația după dimensiunea dalelor, apoi compensând aceste valori cu ecranul dimensiunea împărțită la mărimea dalelor. Simplu.
S-ar putea să nu pară prea mult, deoarece toate plăcile sunt la fel, dar fundația este aproape acolo. Singurele lucruri rămase sunt de a crea diferite tipuri de dale și de a proiecta harta noastră astfel încât ele să se alinieze și să creeze ceva frumos.
Bine, acum avem o hartă plină de imagini care acoperă ecranul. Prin acest punct ar trebui să aveți mai mult de un tip de țiglă, ceea ce înseamnă că trebuie să ne schimbăm Ţiglă
constructor pentru a ține cont de faptul că:
funcția publică nouă (id: Int) super (); switch (id) caz 1: imagine = Bitmap nou (Assets.getBitmapData ("assets / grassLeftBlock.png")); cazul 2: image = Bitmap nou (Assets.getBitmapData ("assets / grassCenterBlock.png")); cazul 3: image = Bitmap nou (Assets.getBitmapData ("assets / grassRightBlock.png")); cazul 4: image = Bitmap nou (Assets.getBitmapData ("assets / goldBlock.png")); cazul 5: image = Bitmap nou (Assets.getBitmapData ("assets / globe.png")); cazul 6: image = Bitmap nou (Assets.getBitmapData ("assets / mushroom.png")); addChild (imagine);
De când am folosit șase plăci diferite pentru harta mea, aveam nevoie de o intrerupator
declarație care acoperă numerele unu până la șase. Veți observa că constructorul are acum un număr întreg ca parametru, astfel încât să știm ce fel de tiglă să creați.
Acum, trebuie să ne întoarcem la noi Principal
constructor și repara crearea de țiglă în nostru pentru
buclă:
pentru (i în 0 ... map.length) var tile = țiglă nouă (harta [i]); var x = i% w; var y = Math.floor (i / w); tile.setLoc (x, y); addChild (tigla);
Tot ce trebuia să facem era să trecem harta [i]
la Ţiglă
constructor pentru a-l face să funcționeze din nou. Dacă încercați să rulați fără a trece un număr întreg Ţiglă
, vă va da câteva erori.
Aproape totul este în vigoare, dar acum avem nevoie de o modalitate de a proiecta hărți în loc să le umplem doar cu plăci aleatoare. Mai întâi, eliminați pentru
buclă în Principal
constructor care pune fiecare element la unul. Apoi putem crea propria noastră hartă cu mâna:
hartă = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, , 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 1, 2, 2, 3];
Dacă formatați matricea ca cea de mai sus, puteți vedea cu ușurință modul în care vor fi organizate plăcile noastre. Puteți, de asemenea, să introduceți doar matricea ca o linie lungă de numere, dar prima este frumoasă deoarece puteți vedea 10 și 6 în jos.
Când încercați să executați programul acum, ar trebui să obțineți câteva excepții pentru pointer. Problema este că folosim zerouri în harta noastră și în cea a noastră Ţiglă
clasa nu știe ce să facă cu zero. În primul rând, vom repara constructorul adăugând o verificare înainte de a adăuga imaginea copil:
dacă (imagine! = null) addChild (imagine);
Această verificare rapidă vă asigură că nu adăugăm copiilor nula Ţiglă
obiecte create. Ultima modificare pentru această clasă este setLoc ()
funcţie. În acest moment încercăm să setăm X
și y
valori pentru o variabilă care nu a fost inițializată.
Să adăugăm o altă verificare rapidă:
funcția publică setLoc (x: Int, y: Int) dacă (imagine! = null) image.x = x * Main.TILE_WIDTH; image.y = y * Main.TILE_HEIGHT;
Cu aceste două fixări simple în loc și plăcile pe care le-am furnizat de mai sus, ar trebui să puteți conduce jocul și să vedeți un nivel simplu de platformă. Din moment ce am lăsat 0 ca "non-țiglă", îl putem lăsa transparent (gol). Dacă doriți să obțineți un nivel mai înalt, puteți pune un fundal înaintea așezării plăcilor; Tocmai am adăugat un gradient albastru deschis pentru a arăta ca un cer în fundal.
Acest lucru este destul de mult tot ce aveți nevoie pentru a configura o modalitate simplă de a edita nivelurile. Încercați să experimentați puțin cu matricea și să vedeți ce desene sau modele puteți crea pentru alte nivele.
Odată ce ați obținut elementele de bază, vă recomandăm să utilizați alte instrumente pentru a vă ajuta să proiectați rapid nivelurile și să vedeți cum arată acestea înainte de a le arunca în joc. O opțiune este crearea unui editor de nivel propriu. Alternativa este de a apuca unele software-ul care este disponibil gratuit pentru utilizare. Cele două instrumente populare sunt editorul de arhitecți și Editorul Ogmo. Amândouă fac editare la nivel mult mai ușor cu opțiuni de export multiple.
postări asemănatoareAcum știți ce este un joc pe bază de țiglă, cum să obțineți niște plăci pentru a vă folosi nivelurile dvs. și cum să vă murdăriți mâinile și să scrieți codul pentru motorul dvs. și puteți chiar să faceți niște editări de nivel de bază cu o simplă matrice . Amintiți-vă că acest lucru este doar începutul; există o mulțime de experiențe pe care le puteți face pentru a face un motor chiar mai bun.
De asemenea, am furnizat fișierele sursă pentru a fi verificate. Iată cum arată SWF-ul final:
Descărcați SWF aici.... și aici, din nou, este matricea pe care o generează:
hartă = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, , 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 1, 2, 2, 3];
Următoarea dvs. sarcină este să faceți niște cercetări și să încercați câteva lucruri noi pentru a îmbunătăți ceea ce ați făcut aici. Frunzele Sprite sunt o modalitate foarte bună de a îmbunătăți performanța și de a ușura viața. Trucul este de a obține un cod solid stabilit pentru citirea de pe o foaie de sprite, astfel încât jocul dvs. nu trebuie să citească fiecare imagine individual.
De asemenea, ar trebui să începeți să vă exersați abilitățile de artă făcând câteva seturi de tigla proprii. În acest fel puteți obține arta potrivită pentru jocurile viitoare.
Ca întotdeauna, lăsați câteva comentarii mai jos despre modul în care motorul dvs. funcționează pentru dvs. - și poate chiar și unele demo-uri pentru ca noi să putem încerca următorul joc de țiglă.