¿Cómo puedo desplegar uniformemente una mano de cartas?

20

Dado un conjunto de cartas de juego (imágenes rectangulares con un ancho y una altura), ¿cómo puedo rotar y colocar cada una de ellas para que aparezcan en un patrón de 'abanico', al igual que si tuviera una mano de cartas en la vida real? ¿Qué matemática se necesita para hacer esto?

ACTUALIZAR

Aquí está el final, en la implementación del navegador en JavaScript: https://cosmicrealms.com/blog/2013/03/16/hand-of-cards/ y http://jsfiddle.net/tyyvk/108/

Sembranza
fuente
99
Señor, parece que tiene demasiados ases en la mano. Por favor, aléjate de la mesa.
Tomas Andrle
El violín debe actualizarse para usar una versión posterior de MooTools.
tomdemuyt

Respuestas:

30

Teoría

Como no especificó en qué plataforma está implementando esto, le daré una descripción del algoritmo de forma independiente del lenguaje:

  1. Primero apila cada carta una encima de la otra dándoles la misma posición inicial.
  2. Luego, para cada tarjeta, aplique una rotación (generalmente centrada alrededor de una de las esquinas inferiores , pero mover este origen esencialmente le permitirá modificar el aspecto del ventilador).
  3. Incremente el ángulo de rotación entre cada llamada , dependiendo de la cantidad de tarjetas y de cuánto desea que se distribuyan.

Es evidente que la rotación se centra alrededor de una de las esquinas inferiores de la tarjeta (o cerca de la esquina) al mirarla:

ingrese la descripción de la imagen aquí


Implementación

En cuanto a cómo implementar esto, depende de su plataforma. En XNA, simplemente puede usar el parámetro Origen de SpriteBatch.Drawpara cambiar el centro de su rotación.

Esto es lo que obtuve con el siguiente código (con algunos ajustes en el origen para que se vea mejor, básicamente el origen comienza cerca de la esquina derecha y termina cerca de la esquina izquierda):

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

Y el resultado:

ingrese la descripción de la imagen aquí

David Gouveia
fuente
77
Agregaría que la apariencia se puede ajustar usando un centro de rotación diferente, si desea abarcar un arco más pequeño, debe usar un punto de rotación que se encuentre debajo de la tarjeta.
aaaaaaaaaaaa
@eBusiness Tienes razón, lo agregaré.
David Gouveia
Muchas gracias David! He implementado el código que has mostrado en JavaScript aquí: jsfiddle.net/tyyvk/7
Sembiance