Come posso distribuire uniformemente una mano di carte?


20

Dato un set di carte da gioco (immagini rettangolari con larghezza e altezza) come posso ruotare e posizionare ognuna in modo che appaiano in uno schema 'a ventaglio', proprio come faresti con una mano di carte nella vita reale. Quale matematica è necessaria per fare questo?

AGGIORNARE

Ecco il finale, nell'implementazione del browser in JavaScript: https://cosmicrealms.com/blog/2013/03/16/hand-of-cards/ e http://jsfiddle.net/tyyvk/108/


9
Signore, sembra che tu abbia troppi assi in mano. Per favore, allontanati dal tavolo.
Tomas Andrle,

Il violino deve essere aggiornato per utilizzare una versione successiva di MooTools.
tomdemuyt,

Risposte:


30

Teoria

Dato che non hai specificato in quale piattaforma lo stai implementando, ti darò una descrizione dell'algoritmo in modo indipendente dal linguaggio:

  1. Prima impila tutte le carte una sopra l'altra dando loro la stessa posizione iniziale.
  2. Quindi per ogni carta applica una rotazione (di solito centrata attorno a uno degli angoli inferiori , ma spostare questa origine ti permetterà essenzialmente di modificare l'aspetto della ventola).
  3. Incrementa l'angolo di rotazione tra ogni chiamata , a seconda del numero di carte e di quanto vuoi che vengano distribuite.

Che la rotazione sia centrata attorno a uno degli angoli inferiori della carta (o vicino all'angolo) dovrebbe essere evidente osservandola:

inserisci qui la descrizione dell'immagine


Implementazione

Per quanto riguarda come implementarlo, dipende dalla tua piattaforma. Su XNA puoi semplicemente usare il parametro Origin di SpriteBatch.Drawper cambiare il centro della tua rotazione.

Ecco cosa ho ottenuto con il seguente codice (con alcune modifiche all'origine per renderlo migliore - in pratica l'origine inizia vicino all'angolo destro e finisce vicino all'angolo sinistro):

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();

E il risultato:

inserisci qui la descrizione dell'immagine


7
Aggiungerei che l'aspetto può essere modificato usando un centro di rotazione diverso, se vuoi estendere un arco più piccolo dovresti usare un punto di rotazione che si trova sotto la carta.
aaaaaaaaaaaa

@eBusiness Hai ragione, lo aggiungerò.
David Gouveia,

Grazie mille David! Ho implementato il codice che hai mostrato in JavaScript qui: jsfiddle.net/tyyvk/7
Sembiance
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.