Crearea în mod dinamic a cardurilor de joc folosind codul pentru blocajele jocurilor

Ce veți crea

Acest tutorial este diferit de tutorialele mele anterioare, deoarece acesta este orientat spre blocaje de joc și prototipuri de jocuri, în special jocuri de cărți. Vom crea o platformă de joc 2D în Unity fără a folosi orice fel de artă - pur și simplu cu cod.

1. Componentele unui pachet de cărți de joc

Un pachet de cărți de joc are un număr total de 52 de cărți, câte 13 cărți fiecare având 4 simboluri diferite. Pentru a crea un cod folosind, trebuie să creați aceste 4 simboluri, baza dreptunghiulară rotunjită a cardului și designul de pe spatele cardului.

Designul de pe spatele cardului poate fi orice model abstract și există numeroase moduri de a crea unul. Vom crea un model simplu tileabil, care va fi apoi tiglat pentru a crea designul. Nu vom avea un design special pentru cardurile A, K, Q și J.

2. Soluții alternative

Înainte de a începe, trebuie să menționez că există soluții mai ușoare pe care le putem folosi pentru a crea un pachet de cărți. Unele dintre acestea sunt enumerate mai jos.

  1. Cel evident este de a folosi arta pre-redată pentru toate desenele.
  2. Mai puțin evident este utilizarea unui font care conține toate simbolurile necesare. De asemenea, putem transforma fontul menționat într-un font bitmap pentru a reduce apelurile și a crește performanța.

Soluția bazată pe fonturi este cea mai rapidă și mai ușoară dacă doriți să faceți prototipuri rapide.

3. Crearea texturilor în timpul runtime-ului

Primul pas este să înveți cum să creezi un Texture2D folosind codul care poate fi apoi folosit pentru a crea un spiriduș în Unitate. Următorul cod arată crearea unei texturi goale de 256x256.

Textura Texture2D = Texture2D nou (256, 256, TextureFormat.ARGB4444, fals); texture.filterMode = FilterMode.Trilinear; texture.wrapMode = TextureWrapMode.Clamp; texture.Apply ();

Ideea este de a atrage toate desenele pe textura înainte de a le folosi aplica metodă. Putem desena desenele pe pixelul texturii cu ajutorul pixelului SetPixel , după cum se arată mai jos.

textură.SetPixel (x, y, culoare.white);

De exemplu, dacă vrem să umplem întreaga textura cu o culoare, am putea folosi o metodă ca aceasta.

privat void PaintRectangle (textură Texture2D, Rect rectBounds, Culoare culoare) pentru (int i = (int) rectBounds.x; i

Odată ce avem Texture2D create, îl putem folosi pentru a crea un spiriduș pentru a fi afișate pe ecran.

Sprite sprite = Sprite.Create (textură, noul Rect (0.0f, 0.0f, texture.width, texture.height), Vector2 nou (0.5f, 0.5f), 1);

Partea complicată în toate acestea este crearea de desene sau modele necesare pe textură.

4. Crearea formei inimii

Când vine vorba de crearea formei inimii, există multe abordări diferite pe care le putem folosi, printre care unele ecuații complicate, precum și o simplă amestecare a formelor. Vom folosi metoda de amestecare a formelor așa cum este arătat mai jos, în special cel cu triunghi.

După cum ați observat, putem folosi două cercuri și un pătrat sau un triunghi pentru a crea forma de bază a inimii. Asta inseamna ca ar fi dor de acele curbe foarte frumoase, dar s-ar potrivi perfect scopului nostru.

Pictura unui cerc

Să aruncăm o privire asupra unor ecuații pentru a picta un cerc. Pentru un cerc cu centru la origine și rază r, ecuația pentru punct (X y) pe cerc este X2 + y2 = r2. Acum, dacă centrul cercului este la (H, k) atunci ecuația devine  (X-h)2 + (Y-k)2 = r2. Deci, dacă avem o dreptunghi dreptunghiulară, atunci putem trece prin toate punctele din acel dreptunghi și putem determina care puncte intră în interiorul cercului și care nu. Putem crea cu ușurință PaintCircle bazată pe această înțelegere, după cum se arată mai jos.

particulă void PaintCircle (textura Texture2D, raza flotorului, vector2 midpoint, culoarea culorii) Rect circleBounds = new Rect (); circleBounds.x = Mathf.Clamp (midPoint.x- (raza), 0, rezoluție); circleBounds.y = Mathf.Clamp (midPoint.y- (raza), 0, rezoluție); circleBounds.width = Mathf.Clamp (2 * raza, 0, rezoluție); circleBounds.height = Mathf.Clamp (2 * raza, 0, rezoluție); pluti iValue; pentru (int i = (int) circleBounds.x; imidPoint.x-iValue && i

Odată ce avem PaintCircle , putem continua să ne creăm forma inimii după cum se arată mai jos.

void PaintHearts (textura Texture2D) // 2 cercuri în partea de sus float radius = rezoluție * 0.26f; Vector2 mid = new Vector2 (rază, rezoluție-rază); PaintCircle (textură, rază, la mijlocul, Color.red); mid = new Vector2 (rezoluție-rază, rezoluție-rază); PaintCircle (textură, rază, la mijlocul, Color.red); // triunghi la lățimea flotorului inferior = rezoluție * 0.58f; int endJ = (int) (rezoluție * 0.65f); int startJ = (int) (rezoluție * 0.1f); float delta = (lățime / capăt); float midI = rezoluție * 0.5f; pentru (int i = 0; i(Midi (delta * (j-startJ))) && i<(midI+(delta*(j-startJ)))) texture.SetPixel(i, j, Color.red);    

Variabila rezoluţie este lățimea și înălțimea texturii.

5. Crearea formei de diamante

Vom discuta două moduri de a desena forma de diamant.

Pictura unui simplu diamant

Cea mai ușoară este extinderea codului folosit pentru triunghi și adăugarea unui triunghi inversat în partea superioară pentru a crea forma necesară, după cum se arată mai jos.

 void PaintDiamond (textura Texture2D) float width = resolution * 0.35f; pentru (int i = 0; imidJ) j = rezoluția-j; if (i> (Midi (delta * j)) && i<(midI+(delta*j))) isValid=true;  else if(i>(Midi (delta * j)) && i<(midI+(delta*j))) isValid=true;   return isValid;  PaintDiamond(texture);

Pictura unui curvy diamant

Al doilea este de a folosi o altă ecuație pentru a crea o versiune mai bună, curbată a formei noastre de diamant. Vom folosi aceasta pentru a crea designul placilor pentru partea din spate a cardului nostru. Ecuația pentru un cerc derivă din ecuația inițială a unei elipse, care este (X / a)2 + (Y / b)2 = r2.

Această ecuație este aceeași cu cea a cercului atunci când variabilele A și b sunt ambele 1. Ecuația de elipsă poate fi apoi extinsă într-o ecuație de tip super-alunecare pentru forme similare doar prin schimbarea puterii, (X / a)n + (Y / b)n = rn. Deci când n este 2 avem elipsa, și pentru alte valori ale lui n vom avea forme diferite, dintre care unul este diamantul nostru. Putem folosi abordarea folosită pentru a ajunge la PaintCircle pentru a ajunge la noi PaintDiamond metodă.

private void PaintDiamond (textura Texture2D, RectBounds, Vector2 midPoint, Culoare culoare, float n = 0.8f) float iValue; int a = (int) (rectBounds.width / 2); int b = (int) (rectBounds.height / 2); float nRoot = 1 / n; float delta; float partialOne; rectBounds.width = Mathf.Clamp (rectBounds.x + rectBounds.width, 0, rezoluție); rectBounds.height = Mathf.Clamp (rectBounds.y + rectBounds.height, 0, rezoluție); rectBounds.x = Mathf.Clamp (rectBounds.x, 0, rezoluție); rectBounds.y = Mathf.Clamp (rectBounds.y, 0, rezoluție); pentru (int i = (int) rectBounds.x; imidPoint.x-iValue && i

Pictura unui dreptunghi rotunjit

Aceeași ecuație poate fi utilizată pentru a crea forma bazei dreptunghiului cardului rotunjit prin modificarea valorii n.

privat void PaintRoundedRectangle (textura Texture2D) pentru (int i = 0; imid.x-iValue && i

Pictura unui design tigla

Folosind asta PaintDiamond , putem desena cinci diamante pentru a crea textura placilor pentru designul de pe spatele cardului nostru.

Codul pentru desenarea designului placajului este cel descris mai jos.

 privat void PaintTilingDesign (textura Texture2D, int tileResolution) Vector2 mijloc = nou Vector2 (tileResolution / 2, tileResolution / 2); float dimensiune = 0.6f * tileResolution; PaintDiamond (textură, noul Rect (mid.x-size / 2, mid.y-size / 2, dimensiune, dimensiune), mediu, Color.red); mid = nou Vector2 (0,0); PaintDiamond (textură, noul Rect (mid.x-size / 2, mid.y-size / 2, dimensiune, dimensiune), mediu, Color.red); vector = vector2 noi (tileResolution, 0); PaintDiamond (textură, noul Rect (mid.x-size / 2, mid.y-size / 2, dimensiune, dimensiune), mediu, Color.red); mid = nou Vector2 (tileResolution, tileResolution); PaintDiamond (textură, noul Rect (mid.x-size / 2, mid.y-size / 2, dimensiune, dimensiune), mediu, Color.red); mijloc = nou Vector2 (0, tileResolution); PaintDiamond (textură, noul Rect (mid.x-size / 2, mid.y-size / 2, dimensiune, dimensiune), mediu, Color.red); 

6. Crearea formei de spade

Forma picelor este doar flip-ul vertical al formei inimii noastre, împreună cu o formă de bază. Această formă de bază va fi aceeași pentru forma cluburilor. Figura de mai jos ilustrează modul în care putem folosi două cercuri pentru a crea această formă de bază.

PaintSpades metoda va fi așa cum se arată mai jos.

void PaintSpades (textura Texture2D) // 2 cercuri pe raza mijlocie a flotorului = rezoluție * 0.26f; Vector2 mid = nou Vector2 (rază, rezoluție-2.2f * rază); PaintCircle (textură, rază, la mijlocul, Color.black); mid = nou Vector2 (rezoluție-rază, rezoluție-2.2f * rază); PaintCircle (textură, rază, la mijlocul, Color.black); // triunghi la lățimea maximă a flotorului = rezoluție * 0,49f; int startJ = (int) (rezoluție * 0.52f); float delta = (lățime / (rezoluție-startJ)); float midI = rezoluție * 0.5f; int alteredJ; raza = rezoluție * 0.5f; float midJ = rezoluție * 0,42f; pluti iValue; pentru (int i = 0; i(Midi (delta * alteredJ)) && i<(midI+(delta*alteredJ))) texture.SetPixel(i, j, Color.black);   //bottom stalk for (int k=0;kmid.x + iValue) mediu = nou Vector2 (rezoluție, midJ); iValue = (Mathf.Sqrt (raza * raza - ((k-mid.y) * (k-mid.y)))); // + mid.x; dacă eu

7. Crearea formei cluburilor

În acest moment, sunt sigur că vă puteți da seama cât de ușor a devenit pentru a crea forma cluburilor. Tot ce avem nevoie sunt două cercuri și forma de bază pe care am creat-o pentru forma picelor.

PaintClubs metoda va fi așa cum se arată mai jos.

 void PaintClubs (textura Texture2D) int radius = (int) (rezoluție * 0.24f); // 3 cercuri Vector2 mid = new Vector2 (rezoluție * 0.5f, rezoluție-rază); PaintCircle (textură, rază, la mijlocul, Color.black); mid = nou Vector2 (rezoluție * 0.25f, rezoluție- (raza 2.5f *)); PaintCircle (textură, rază, la mijlocul, Color.black); mid = nou Vector2 (rezoluție * 0.75f, rezoluție- (raza 2.5f *)); PaintCircle (textură, rază, la mijlocul, Color.black); // raza stâlpului de bază = (int) (rezoluția * 0.5f); float midY = rezoluție * 0,42f; int stalkHeightJ = (int) (rezoluție * 0.65f); pluti iValue; pentru (int i = 0; imid.x + iValue) mid = new Vector2 (rezoluție * 1.035f, midY); iValue = (Mathf.Sqrt (raza * raza - ((j-mid.y) * (j-mid.y)))); // + mid.x; dacă eu

8. Texturi de ambalare

Dacă explorați fișierele sursă Unity pentru acest proiect, veți găsi a TextureManager clasa care face toate grele de ridicare. Odată ce am creat toate texturile necesare, TextureManager clasa utilizează PackTextures metodă de combinare a acestora într-o singură textură, reducând astfel numărul de apeluri solicitate atunci când folosim aceste forme.

Rect [] packedAssets = packedTexture.PackTexturi (toateGrafica, 1);

Utilizarea packedAssets array, putem extrage cutiile de margini ale texturilor individuale din textura principală numită packedTexture.

public Rect GetTextureRectByName (șir texturăName) textureName = textureName.ToLower (); int textureIndex; Rect textureRect = Rect nou (0,0,0,0); dacă (textureDict.TryGetValue (textureName, textureIndex)) textureRect = ConvertUVToTextureCoordinates (packedAssets [textureIndex]);  altceva Debug.Log ("nici o textură" + textureName);  retur texturaRect;  privat Rect ConvertUVToTextureCoordinates (Rect rect) retur nou Rect (rect.x * packedTexture.width, rect.y * packedTexture.height, rect.width * packedTexture.width, rect.height * packedTexture.height); 

Concluzie

Cu toate componentele necesare create, putem continua să creăm pachetul de cărți, deoarece este doar o problemă de a stabili în mod corespunzător formele. Putem folosi fie UI Unity pentru carduri compozite, fie noi putem crea cărțile ca texturi individuale. Puteți explora exemplul de cod pentru a înțelege modul în care am folosit prima metodă de a crea machete de carduri.

Putem urma aceeasi metoda pentru a crea orice fel de arta dinamica la runtime in Unity. Crearea de artă în timpul execuției este o operație însoțită de performanță, dar trebuie făcută o singură dată dacă salvăm și reutilizăm aceste texturi în mod eficient. Prin ambalarea activelor create dinamic într-o singură textură, câștigăm și avantajele utilizării unui atlas de textură.

Acum, când avem pachetul nostru de cărți de joc, spuneți-mi ce jocuri pe care intenționați să le creați.