Comment répartir uniformément une main de cartes?

20

Étant donné un ensemble de cartes à jouer (images rectangulaires avec une largeur et une hauteur), comment puis-je faire pivoter et positionner chacune d'elles de manière à ce qu'elles apparaissent dans un motif en `` éventail '', tout comme vous tiendriez une main de cartes dans la vraie vie. Quelles mathématiques faut-il pour cela?

MISE À JOUR

Voici la finale, dans l'implémentation du navigateur en JavaScript: https://cosmicrealms.com/blog/2013/03/16/hand-of-cards/ et http://jsfiddle.net/tyyvk/108/

Sembiance
la source
9
Monsieur, vous semblez avoir trop d'as dans votre main. Veuillez vous éloigner de la table.
Tomas Andrle
Le violon doit être mis à jour pour utiliser une version ultérieure de MooTools.
tomdemuyt

Réponses:

30

Théorie

Puisque vous n'avez pas spécifié dans quelle plateforme vous implémentez cela, je vais donner une description de l'algorithme d'une manière indépendante du langage:

  1. Empilez d' abord toutes les cartes les unes sur les autres en leur donnant la même position initiale.
  2. Ensuite, pour chaque carte, appliquez une rotation (généralement centrée autour de l'un des coins inférieurs , mais le déplacement de cette origine vous permettra essentiellement de modifier l'apparence du ventilateur).
  3. Augmentez l'angle de rotation entre chaque appel , en fonction du nombre de cartes et de la quantité que vous souhaitez qu'elles soient réparties.

Que la rotation soit centrée autour de l'un des coins inférieurs de la carte (ou près du coin) devrait être évident en la regardant:

entrez la description de l'image ici


la mise en oeuvre

Quant à la façon de mettre en œuvre cela, cela dépend de votre plate-forme. Sur XNA, vous pouvez simplement utiliser le paramètre Origin de SpriteBatch.Drawpour changer le centre de votre rotation.

Voici ce que j'ai obtenu avec le code suivant (avec quelques ajustements à l'origine pour le rendre meilleur - fondamentalement, l'origine commence près du coin droit et se termine près du coin gauche):

int cards = 20;
float range = MathHelper.ToRadians(90);
float initialAngle = MathHelper.ToRadians(-45);
float increment = range / cards;
Vector2 leftCorner = new Vector2(0, texture.Height * 0.9f);
Vector2 rightCorner = new Vector2(texture.Width, texture.Height * 0.9f);
Vector2 fanPosition = new Vector2(400, 300);
spriteBatch.Begin();
for (float angle = 0; angle < range; angle+=increment)
{
    float cardAngle = initialAngle + angle;
    Vector2 cardOrigin = Vector2.Lerp(rightCorner, leftCorner, angle / range);
    spriteBatch.Draw(texture, fanPosition, null, Color.White, cardAngle, cardOrigin, 1f, SpriteEffects.None, 0f);
}
spriteBatch.End();

Et le résultat:

entrez la description de l'image ici

David Gouveia
la source
7
J'ajouterais que l'apparence peut être modifiée en utilisant un centre de rotation différent, si vous souhaitez couvrir un arc plus petit, vous devez utiliser un point de rotation qui se trouve sous la carte.
aaaaaaaaaaaa
@eBusiness Vous avez raison, je vais ajouter cela.
David Gouveia
Merci beaucoup David! J'ai implémenté le code que vous avez montré en JavaScript ici: jsfiddle.net/tyyvk/7
Sembiance