Création dynamique de cartes à jouer à l'aide de code pour les bourrages de jeu

Ce que vous allez créer

Ce didacticiel est différent de mes didacticiels précédents, car celui-ci est axé sur les jeux vidéo et le prototypage, en particulier les jeux de cartes. Nous allons créer un jeu de cartes à jouer 2D dans Unity sans utiliser d’art purement avec du code..

1. Composants d'un jeu de cartes à jouer

Un jeu de cartes à jouer contient un total de 52 cartes avec 13 cartes de 4 symboles différents. Pour en créer un en utilisant un code, nous devrons créer ces 4 symboles, la base rectangulaire arrondie de la carte et le dessin au verso de la carte..

Le motif au verso de la carte peut être n’importe quel motif abstrait et il existe de nombreuses façons de le créer. Nous allons créer un simple motif mosaïque qui sera ensuite mosaïqué pour créer le motif. Nous n'aurons pas de design spécial pour les cartes A, K, Q et J.

2. Solutions alternatives

Avant de commencer, je dois mentionner qu’il existe des solutions plus simples que nous pouvons utiliser pour créer un jeu de cartes. Certains d'entre eux sont énumérés ci-dessous.

  1. La solution évidente consiste à utiliser des œuvres d'art pré-rendues pour toutes les conceptions..
  2. La moins évidente consiste à utiliser une police contenant tous les symboles nécessaires. Nous pouvons également transformer cette police en une police bitmap pour réduire les appels de dessin et améliorer les performances..

La solution basée sur les polices est la plus rapide et la plus simple si vous souhaitez réaliser des prototypes rapides..

3. Création de textures pendant l'exécution

La première étape consiste à apprendre à créer un Texture2D en utilisant du code qui peut ensuite être utilisé pour créer un Lutin dans l'unité. Le code suivant montre la création d'une texture vierge de 256 x 256.

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

L'idée est de dessiner tous les motifs sur la texture avant d'utiliser le Appliquer méthode. Nous pouvons dessiner des dessins sur la texture pixel par pixel en utilisant le SetPixel méthode, comme indiqué ci-dessous.

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

Par exemple, si nous voulions remplir toute la texture avec une couleur, nous pourrions utiliser une méthode comme celle-ci..

PaintRectangle void privé (texture Texture2D, Rect rectifiée, couleur couleur) pour (int i = (int) rectBounds.x; i

Une fois que nous avons un Texture2D créé, nous pouvons l'utiliser pour créer un Lutin être affiché à l'écran.

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

La partie compliquée de tout cela est la création des dessins nécessaires sur la texture.

4. Créer la forme de coeur

Pour ce qui est de la création de la forme du cœur, nous pouvons utiliser de nombreuses approches différentes, parmi lesquelles des équations compliquées ainsi qu'un simple mélange de formes. Nous allons utiliser la méthode de mélange de formes comme indiqué ci-dessous, en particulier celle avec le triangle.

Comme vous l'avez observé, nous pouvons utiliser deux cercles et un carré ou un triangle pour créer la forme de base du cœur. Cela signifie qu'il manquerait ces très belles courbes mais conviendrait parfaitement à notre objectif.

Peindre un cercle

Revoyons quelques équations pour dessiner un cercle. Pour un cercle avec centre d'origine et rayon r, l'équation pour le point (x, y) sur le cercle est X2 + y2 = r2. Maintenant, si le centre du cercle est à (h, k) alors l'équation devient  (x-h)2 + (y-k)2 = r2. Donc, si nous avons un rectangle de cadre englobant un carré, nous pouvons alors parcourir en boucle tous les points de ce rectangle et déterminer quels points tombent à l'intérieur du cercle et lesquels ne le font pas. Nous pouvons facilement créer notre PaintCircle méthode basée sur cette compréhension, comme indiqué ci-dessous.

PaintCircle vide privé (texture Texture2D, rayon de flottement, point central Vector2, couleur couleur) Rect circleBounds = new Rect (); circleBounds.x = Mathf.Clamp (midPoint.x- (rayon), 0, résolution); circleBounds.y = Mathf.Clamp (midPoint.y- (rayon), 0, résolution); circleBounds.width = Mathf.Clamp (2 * rayon, 0, résolution); circleBounds.height = Mathf.Clamp (2 * rayon, 0, résolution); float iValue; pour (int i = (int) circleBounds.x; imidPoint.x-iValue && i

Une fois que nous avons le PaintCircle méthode, nous pouvons procéder pour créer notre forme de coeur comme indiqué ci-dessous.

void PaintHearts (Texture2D Texture) // 2 cercles sur le rayon du flottant supérieur = résolution * 0.26f; Vecteur 2 milieu = nouveau vecteur 2 (rayon, résolution-rayon); PaintCircle (texture, rayon, milieu, Color.red); milieu = nouveau vecteur 2 (résolution-rayon, résolution-rayon); PaintCircle (texture, rayon, milieu, Color.red); // triangle en bas float width = résolution * 0.58f; int endJ = (int) (résolution * 0.65f); int startJ = (int) (résolution * 0.1f); float delta = (width / endJ); float midI = résolution * 0.5f; pour (int i = 0; i(midI- (delta * (j-startJ))) && i<(midI+(delta*(j-startJ)))) texture.SetPixel(i, j, Color.red);    

La variable résolution est la largeur et la hauteur de la texture.

5. Créer la forme de diamant

Nous allons discuter de deux façons de dessiner la forme de diamant.

Peindre un simple diamant

La plus simple consiste à étendre le code utilisé pour le triangle et à ajouter un triangle inversé en haut pour créer la forme nécessaire, comme indiqué ci-dessous..

 void PaintDiamond (texture Texture2D) float width = resolution * 0.35f; pour (int i = 0; imidJ) j = résolution-j; si (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);

Peindre un diamant courbé

La seconde consiste à utiliser une autre équation pour créer une meilleure version courbée de notre forme en diamant. Nous allons utiliser celui-ci pour créer la conception de la mosaïque pour le verso de notre carte. L'équation d'un cercle provient de l'équation originale d'une ellipse, qui est (x / a)2 + (y / b)2 = r2.

Cette équation est la même que celle du cercle lorsque les variables une et b sont les deux 1. L'équation d'ellipse peut ensuite être étendue en une équation de superellipse pour des formes similaires en modifiant simplement la puissance, (x / a)n + (y / b)n = rn. Donc quand n est 2 nous avons l'ellipse, et pour d'autres valeurs de n nous aurons différentes formes, dont notre diamant. Nous pouvons utiliser l'approche utilisée pour arriver à la PaintCircle méthode pour arriver à notre nouvelle PaintDiamond méthode.

PaintDiamond vide privé (Texture2D texture, Rect RectBounds, Vector2 midPoint, Couleur couleur, 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, résolution); rectBounds.height = Mathf.Clamp (rectBounds.y + rectBounds.height, 0, résolution); rectBounds.x = Mathf.Clamp (rectBounds.x, 0, résolution); rectBounds.y = Mathf.Clamp (rectBounds.y, 0, résolution); pour (int i = (int) rectBounds.x; imidPoint.x-iValue && i

Peindre un rectangle arrondi

La même équation peut être utilisée pour créer notre forme de base de carte rectangle arrondie en faisant varier la valeur de n.

void privé PaintRoundedRectangle (texture Texture2D) pour (int i = 0; imid.x-iValue && i

Peindre une conception de carrelage

En utilisant cette PaintDiamond méthode, nous pouvons dessiner cinq diamants pour créer la texture de pavage pour la conception sur le dos de notre carte.

Le code pour dessiner la conception de carrelage est comme ci-dessous.

 PaintTilingDesign (structure Texture2D, int tileResolution) Vector2 mid = new Vector2 (tileResolution / 2, tileResolution / 2); taille de float = 0.6f * tileResolution; PaintDiamond (texture, nouveau rect (mid.x-size / 2, mid.y-size / 2, size, size), mid, Color.red); milieu = nouveau vecteur 2 (0,0); PaintDiamond (texture, nouveau rect (mid.x-size / 2, mid.y-size / 2, size, size), mid, Color.red); mid = nouveau Vector2 (tileResolution, 0); PaintDiamond (texture, nouveau rect (mid.x-size / 2, mid.y-size / 2, size, size), mid, Color.red); mid = nouveau Vector2 (tileResolution, tileResolution); PaintDiamond (texture, nouveau rect (mid.x-size / 2, mid.y-size / 2, size, size), mid, Color.red); mid = nouveau Vector2 (0, résolution de la tuile); PaintDiamond (texture, nouveau rect (mid.x-size / 2, mid.y-size / 2, size, size), mid, Color.red); 

6. Créer la forme de pique

La forme de pique est juste le retournement vertical de notre forme de coeur avec une forme de base. Cette forme de base sera la même pour la forme des clubs. La figure ci-dessous montre comment utiliser deux cercles pour créer cette forme de base..

le PaintSpades méthode sera comme indiqué ci-dessous.

vide PaintSpades (Texture2D texture) // 2 cercles sur le rayon moyen du flottant = résolution * 0.26f; Vector2 milieu = nouveau Vector2 (rayon, résolution-2.2f * rayon); PaintCircle (texture, rayon, milieu, Color.black); milieu = nouveau vecteur 2 (résolution-rayon, résolution-2.2f * rayon); PaintCircle (texture, rayon, milieu, Color.black); // triangle en haut float width = résolution * 0.49f; int startJ = (int) (résolution * 0.52f); float delta = (width / (resolution-startJ)); float midI = résolution * 0.5f; int altteredJ; rayon = résolution * 0.5f; float midJ = résolution * 0.42f; float iValue; pour (int i = 0; i(midI- (delta * altteredJ)) && i<(midI+(delta*alteredJ))) texture.SetPixel(i, j, Color.black);   //bottom stalk for (int k=0;kmid.x + iValue) mid = nouveau Vector2 (résolution, midJ); iValue = (Mathf.Sqrt (rayon * rayon - ((k-mid.y) * (k-milieu.y)))); // + mid.x; si je

7. Créer la forme de clubs

À ce stade, je suis sûr que vous pouvez comprendre à quel point il est devenu facile de créer la forme de clubs. Nous avons seulement besoin de deux cercles et de la forme de base que nous avons créée pour la forme de pique.

le PaintClubs méthode sera comme indiqué ci-dessous.

 vide PaintClubs (texture Texture2D) int radius = (int) (résolution * 0.24f); // 3 cercles Vector2 mid = nouveau Vector2 (résolution * 0.5f, résolution-rayon); PaintCircle (texture, rayon, milieu, Color.black); milieu = nouveau vecteur 2 (résolution * 0,25f, résolution- (2,5f * rayon)); PaintCircle (texture, rayon, milieu, Color.black); milieu = nouveau vecteur 2 (résolution * 0,75f, résolution- (2,5f * rayon)); PaintCircle (texture, rayon, milieu, Color.black); // rayon de la tige de base = (int) (résolution * 0.5f); float midY = résolution * 0.42f; int stalkHeightJ = (int) (résolution * 0,65f); float iValue; pour (int i = 0; imid.x + iValue) mid = nouveau Vector2 (résolution * 1.035f, midY); iValue = (Mathf.Sqrt (rayon * rayon - ((j-mid.y) * (j-mid.y)))); // + mid.x; si je

8. Textures d'emballage

Si vous explorez les fichiers source Unity pour ce projet, vous trouverez une TextureManager classe qui fait tout le gros du travail. Une fois que nous avons créé toutes les textures nécessaires, le TextureManager la classe utilise le PackTextures méthode pour les combiner en une seule texture, réduisant ainsi le nombre d'appels à dessiner requis lorsque nous utilisons ces formes.

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

En utilisant le Objets emballés tableau, nous pouvons récupérer les cadres de sélection des textures individuelles à partir de la texture principale nommée PackTexture.

public Rect GetTextureRectByName (string textureName) textureName = textureName.ToLower (); int textureIndex; Rect textureRect = new Rect (0,0,0,0); if (textureDict.TryGetValue (textureName, out textureIndex)) textureRect = ConvertUVToTextureCoordinates (coloredAssets [textureIndex]);  else Debug.Log ("pas de texture" + textureName);  return textureRect;  private Rect ConvertUVToTextureCoordinates (Rect rect) retour new Rect (rect.x * colisTexture.width, rect.y * colisTexture.height, rect.width * colisTexture.width, rect.height * colisTexture.height); 

Conclusion

Avec tous les composants nécessaires créés, nous pouvons procéder à la création de notre jeu de cartes, car il s’agit simplement d’organiser correctement les formes. Nous pouvons utiliser l'interface utilisateur Unity pour créer des cartes composites ou les créer sous forme de textures individuelles. Vous pouvez explorer l'exemple de code pour comprendre comment j'ai utilisé la première méthode pour créer des présentations de cartes..

Nous pouvons suivre la même méthode pour créer tout type d’art dynamique au moment de l’exécution dans Unity. La création artistique au moment de l'exécution est une opération gourmande en performances, mais elle ne doit être effectuée qu'une fois si nous sauvegardons et réutilisons efficacement ces textures. En regroupant les éléments créés de manière dynamique dans une seule texture, nous bénéficions également des avantages liés à l'utilisation d'un atlas de texture..

Maintenant que nous avons notre jeu de cartes à jouer, dites-moi quels jeux vous envisagez de créer avec.