Como posso distribuir uniformemente uma mão de cartas?


20

Dado um conjunto de cartas de baralho (imagens retangulares com largura e altura), como posso girar e posicionar cada uma para que elas apareçam em um padrão de 'leque', como se você segurasse uma mão de cartas na vida real. Que matemática é necessária para fazer isso?

ATUALIZAR

Aqui está a implementação final do navegador em JavaScript: https://cosmicrealms.com/blog/2013/03/16/hand-of-cards/ e http://jsfiddle.net/tyyvk/108/


9
Senhor, você parece ter muitos ases na mão. Por favor, afaste-se da mesa.
Tomas Andrle

O violino precisa ser atualizado para usar uma versão posterior do MooTools.
tomdemuyt 16/02

Respostas:


30

Teoria

Como você não especificou em qual plataforma está implementando isso, darei uma descrição do algoritmo de maneira independente da linguagem:

  1. Primeiro empilhe todas as cartas umas sobre as outras, dando-lhes a mesma posição inicial.
  2. Em seguida, para cada cartão, aplique uma rotação (geralmente centralizada em torno de um dos cantos inferiores , mas mover essa origem permitirá essencialmente que você ajuste a aparência do ventilador).
  3. Aumente o ângulo de rotação entre cada chamada , dependendo do número de cartões e quanto você deseja que eles sejam distribuídos.

Que a rotação esteja centrada em torno de um dos cantos inferiores do cartão (ou próximo ao canto), deve ser evidente olhando para ele:

insira a descrição da imagem aqui


Implementação

Quanto à forma de implementar isso, isso depende da sua plataforma. No XNA, você pode simplesmente usar o parâmetro Origin SpriteBatch.Drawpara alterar o centro de sua rotação.

Aqui está o que obtive com o código a seguir (com alguns ajustes na origem para torná-la melhor - basicamente a origem começa no canto direito e termina no canto esquerdo):

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 o resultado:

insira a descrição da imagem aqui


7
Eu acrescentaria que a aparência pode ser alterada usando um centro de rotação diferente; se você quiser abranger um arco menor, use um ponto de rotação abaixo do cartão.
Aaaaaaaaaaaa

@eBusiness você está certo, eu vou acrescentar que no.
David Gouveia

Muito obrigado David! Eu implementei o código que você mostrou em JavaScript aqui: jsfiddle.net/tyyvk/7
Sembiance
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.