Opprette spillkort dynamisk ved hjelp av kode for spillestopp

Hva du skal skape

Denne opplæringen er forskjellig fra mine tidligere opplæringsprogrammer, da denne er orientert mot spillstopp og spillprototyping, spesielt kortspill. Vi skal lage en 2D-kortkortdekk i Unity uten å bruke noen art-rent med kode.

1. Komponenter på et Playing Card Deck

Et spillekort dekk har totalt 52 kort med 13 kort hver av 4 forskjellige symboler. For å opprette en som bruker kode, må vi lage disse 4 symbolene, den avrundede rektangulære basen for kortet og designet på baksiden av kortet.

Designet på baksiden av kortet kan være et abstrakt mønster, og det er mange måter å lage en på. Vi skal skape et enkelt fliseremønster som da vil bli flislagt for å skape designet. Vi har ingen spesiell design for A-, K-, Q- og J-kortene.

2. Alternative løsninger

Før vi begynner, må jeg nevne at det er enklere løsninger der ute som vi kan bruke til å lage et kortkort. Noen av disse er listet opp nedenfor.

  1. Den åpenbare er å bruke pre-gjengitt kunst for alle designene.
  2. Den mindre åpenbare er å bruke en skrift som inneholder alle nødvendige symboler. Vi kan også slå nevnte skrifttype inn i en bitmap skrift for å redusere trekke samtaler og øke ytelsen.

Font-basert løsning er den raskeste og enkleste en hvis du vil gjøre raske prototyper.

3. Opprette teksturer under Runtime

Det første trinnet er å lære å lage en Texture2D bruker kode som deretter kan brukes til å lage en Sprite i enhet. Følgende kode viser opprettelsen av en 256x256 blank tekstur.

Texture2D texture = ny Texture2D (256, 256, TextureFormat.ARGB4444, false); texture.filterMode = FilterMode.Trilinear; texture.wrapMode = TextureWrapMode.Clamp; texture.Apply ();

Tanken er å tegne alle designene på tekstur før vi bruker Søke om metode. Vi kan tegne design på teksturpiksel ved piksel ved hjelp av SetPixel metode, som vist nedenfor.

texture.SetPixel (x, y, Color.white);

For eksempel, hvis vi ønsket å fylle ut hele tekstur med en farge, kunne vi bruke en metode som dette.

privat tomrom PaintRectangle (Texture2D tekstur, Rect rectBounds, Color farge) for (int i = (int) rectBounds.x; jeg

Når vi har en Texture2D opprettet, kan vi bruke den til å lage en Sprite å bli vist på skjermen.

Sprite sprite = Sprite.Create (tekstur, ny Rect (0.0f, 0.0f, texture.width, texture.height), ny Vector2 (0.5f, 0.5f), 1);

Den kompliserte delen i alt dette er etableringen av de nødvendige designene på tekstur.

4. Opprette hjerteformen

Når det gjelder opprettelsen av hjerteformen, er det mange forskjellige tilnærminger som vi kan bruke, blant annet noen kompliserte likninger, samt enkel blanding av former. Vi vil bruke blandingen av former som vist nedenfor, spesielt den med trekanten.

Som du har observert, kan vi bruke to sirkler og et kvadrat eller en trekant for å lage den grunnleggende hjerteformen. Dette betyr at det ville savne de ekstra vakre kurvene, men passer perfekt til vår hensikt.

Maling en sirkel

La oss pusse opp på noen likninger for å male en sirkel. For en sirkel med senter ved opprinnelse og radius r, ligningen for punktet (X, y) på sirkelen er x2 + y2 = r2. Nå hvis senterets senter er på (H, k) da blir ligningen  (X-h)2 + (Y-k)2 = r2. Så hvis vi har et firkantet begrensende boks rektangel så kan vi løpe gjennom alle punktene i rektangelet og bestemme hvilke punkter som kommer inn i sirkelen, og hvilke som ikke gjør det. Vi kan enkelt lage vår PaintCircle metode basert på denne forståelsen, som vist nedenfor.

privat tomrom PaintCircle (Texture2D tekstur, floatradius, Vector2 midPoint, Fargefarge) Rect circleBounds = new Rect (); circleBounds.x = Mathf.Clamp (midPoint.x- (radius), 0, oppløsning); circleBounds.y = Mathf.Clamp (midPoint.y- (radius), 0, oppløsning); circleBounds.width = Mathf.Clamp (2 * radius, 0, oppløsning); circleBounds.height = Mathf.Clamp (2 * radius, 0, oppløsning); flyte iValue; for (int i = (int) circleBounds.x; jegmidPoint.x-iValue && i

Når vi har PaintCircle metode, kan vi fortsette å skape vår hjerteform som vist nedenfor.

void PaintHearts (Texture2D tekstur) // 2 sirkler på topp floatradius = oppløsning * 0.26f; Vector2 mid = ny Vector2 (radius, oppløsning-radius); PaintCircle (tekstur, radius, mid, Color.red); midt = ny Vector2 (oppløsning-radius, oppløsning-radius); PaintCircle (tekstur, radius, mid, Color.red); // trekant nederst flytebredde = oppløsning * 0,58f; int endJ = (int) (oppløsning * 0,65f); int startJ = (int) (oppløsning * 0.1f); float delta = (bredde / endJ); float midI = oppløsning * 0.5f; for (int i = 0; i(MIDI (delta * (j-startJ))) && i<(midI+(delta*(j-startJ)))) texture.SetPixel(i, j, Color.red);    

Variabelen Vedtak er bredden og høyden på tekstur.

5. Opprette diamantformen

Vi drøfter to måter å tegne diamantformen på.

Maling en enkel diamant

Den enkleste er å utvide koden som brukes til trekanten og legge til en omvendt trekant på toppen for å skape den nødvendige formen, som vist nedenfor.

 void PaintDiamond (Texture2D tekstur) float width = resolution * 0.35f; for (int i = 0; imidJ) j = oppløsning-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);

Maling en buet diamant

Den andre er å bruke en annen ligning for å skape en bedre, svingete versjon av vår diamantform. Vi skal bruke denne til å lage fliseleggesignen på baksiden av kortet vårt. Ligningen for en sirkel kommer fra den opprinnelige ligningen av en ellipse, som er (X / a)2 + (Y / b)2 = r2.

Denne ligningen er den samme som for sirkelen når variablene en og b er begge 1. Ellipse likningen kan da utvides til en superellipse likning for lignende former bare ved å endre kraften, (X / a)n + (Y / b)n = rn. Så når n er 2 vi har ellipse, og for andre verdier av n Vi vil ha forskjellige former, hvorav den ene er vår diamant. Vi kan bruke tilnærmingen som brukes til å komme fram til PaintCircle metode for å komme fram til vårt nye PaintDiamond metode.

privat tomrom PaintDiamond (Texture2D tekstur, Rect rectBounds, Vector2 midPoint, Color farge, float n = 0.8f) float iValue; int a = (int) (rectBounds.width / 2); int b = (int) (rectBounds.height / 2); flyte nRoot = 1 / n; float delta; float partialOne; rectBounds.width = Mathf.Clamp (rectBounds.x + rectBounds.width, 0, oppløsning); rectBounds.height = Mathf.Clamp (rectBounds.y + rectBounds.height, 0, oppløsning); rectBounds.x = Mathf.Clamp (rectBounds.x, 0, oppløsning); rectBounds.y = Mathf.Clamp (rectBounds.y, 0, oppløsning); for (int i = (int) rectBounds.x; jegmidPoint.x-iValue && i

Maling en avrundet rektangel

Den samme ligningen kan brukes til å lage vår avrundede rektangulære kortbaseform ved å variere verdien av n.

privat tomrom PaintRoundedRectangle (Texture2D tekstur) for (int i = 0; imid.x-iValue && i

Maling av flislegging

Bruk dette PaintDiamond Metode, vi kan tegne fem diamanter for å lage teglestrukturen for designet på baksiden av kortet vårt.

Koden for tegning av flisekonstruksjonen er som nedenfor.

 privat tomrom PaintTilingDesign (Texture2D tekstur, int tileResolution) Vector2 mid = new Vector2 (tileResolution / 2, tileResolution / 2); float size = 0.6f * tileResolution; PaintDiamond (tekstur, ny Rect (mid.x-size / 2, mid.y-size / 2, størrelse, størrelse), midt, Color.red); midt = nytt Vector2 (0,0); PaintDiamond (tekstur, ny Rect (mid.x-size / 2, mid.y-size / 2, størrelse, størrelse), midt, Color.red); midt = ny Vector2 (fliseravløsning, 0); PaintDiamond (tekstur, ny Rect (mid.x-size / 2, mid.y-size / 2, størrelse, størrelse), midt, Color.red); midt = ny Vector2 (fliser, resolusjon, flisløsning); PaintDiamond (tekstur, ny Rect (mid.x-size / 2, mid.y-size / 2, størrelse, størrelse), midt, Color.red); midt = ny Vector2 (0, fliser resolusjon); PaintDiamond (tekstur, ny Rect (mid.x-size / 2, mid.y-size / 2, størrelse, størrelse), midt, Color.red); 

6. Opprette Spadesformen

Spadesformen er bare den vertikale flippen av vår hjerteform sammen med en grunnform. Denne grunnformen vil være den samme for klubbenes form også. Den nedenstående figuren illustrerer hvordan vi kan bruke to sirkler for å lage denne grunnformen.

De PaintSpades Metoden vil være som vist nedenfor.

void PaintSpades (Texture2D tekstur) // 2 sirkler på midtflatradius = oppløsning * 0.26f; Vector2 mid = ny Vector2 (radius, oppløsning-2,2f * radius); PaintCircle (tekstur, radius, mid, Color.black); midt = ny Vector2 (oppløsning-radius, oppløsning-2,2f * radius); PaintCircle (tekstur, radius, mid, Color.black); // trekant ved topp floatbredde = oppløsning * 0,49f; int startJ = (int) (oppløsning * 0,52f); float delta = (bredde / (oppløsning-startJ)); float midI = oppløsning * 0.5f; int alteredJ; radius = oppløsning * 0.5f; flyte midJ = oppløsning * 0,42f; flyte iValue; for (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) mid = ny Vector2 (oppløsning, midJ); iValue = (Mathf.Sqrt (radius * radius - ((k-mid.y) * (k-mid.y)))); // + mid.x; hvis jeg

7. Opprette Clubs Shape

På dette punktet er jeg sikker på at du kan finne ut hvor lett det har blitt å lage klubbens form. Alt vi trenger er to sirkler og grunnformen vi opprettet for spaderformen.

De PaintClubs Metoden vil være som vist nedenfor.

 void PaintClubs (Texture2D tekstur) int radius = (int) (oppløsning * 0.24f); // 3 sirkler Vector2 mid = ny Vector2 (oppløsning * 0.5f, oppløsning-radius); PaintCircle (tekstur, radius, mid, Color.black); midt = ny Vector2 (oppløsning * 0.25f, oppløsning- (2,5f * radius)); PaintCircle (tekstur, radius, mid, Color.black); midt = ny Vector2 (oppløsning * 0.75f, oppløsning- (2,5f * radius)); PaintCircle (tekstur, radius, mid, Color.black); // base stalkradius = (int) (oppløsning * 0,5f); flyte midY = oppløsning * 0.42f; int stalkHeightJ = (int) (oppløsning * 0,65f); flyte iValue; for (int i = 0; imid.x + iValue) mid = ny Vector2 (oppløsning * 1.035f, midY); iValue = (Mathf.Sqrt (radius * radius - ((j-mid.y) * (j-mid.y)))); // + mid.x; hvis jeg

8. Pakking av teksturer

Hvis du undersøker enhetens kildefiler for dette prosjektet, finner du en TextureManager klasse som gjør alt tungt løft. Når vi har skapt alle nødvendige teksturer, TextureManager klassen bruker PackTextures metode for å kombinere dem til en enkelt tekstur, og dermed redusere antall trekksamtaler som kreves når vi bruker disse figurene.

Rect [] packedAssets = packedTexture.PackTextures (allGraphics, 1);

Bruker packedAssets array, kan vi hente grensebokser av individuelle teksturer fra hovedtekststrukturen som heter packedTexture.

offentlig Rect GetTextureRectByName (streng teksturnavn) textureName = textureName.ToLower (); int textureIndex; Rect textureRect = ny Rect (0,0,0,0); hvis (textureDict.TryGetValue (textureName, out textureIndex)) textureRect = ConvertUVToTextureCoordinates (packedAssets [textureIndex]);  else Debug.Log ("ingen slik tekstur" + teksturnavn);  returnere textureRect;  Private Rect ConvertUVToTextureCoordinates (Rect rect) returner ny Rect (rect.x * packedTexture.width, rect.y * packedTexture.height, rect.width * packedTexture.width, rect.height * packedTexture.height); 

Konklusjon

Med alle nødvendige komponenter opprettet, kan vi fortsette å lage kortkortet vårt, da det bare handler om å legge ut formene riktig. Vi kan enten bruke Unity UI til komposittkort eller vi kan lage kortene som individuelle teksturer. Du kan utforske prøvekoden for å forstå hvordan jeg har brukt den første metoden for å lage kortoppsett.

Vi kan følge den samme metoden for å skape noen form for dynamisk kunst på kjøretid i Unity. Å lage kunst ved kjøretid er en ytelse-sulten operasjon, men det må bare gjøres en gang hvis vi lagrer og gjenbruk disse teksturer effektivt. Ved å pakke de dynamisk opprettede eiendommene til en enkelt tekstur, får vi også fordelene ved å bruke et teksturatlas.

Nå som vi har vår kortkort dekk, gi meg beskjed om hvilke spill du planlegger å lage med den.