Як я можу рівномірно розкрити руку карт?


20

З огляду на набір ігрових карт (прямокутні зображення із шириною та висотою), як я можу обертати та розміщувати кожну з них так, щоб вони відображалися у шаблоні «віяла», як би ви тримали руку карт у реальному житті. Яка математика потрібна для цього?

ОНОВЛЕННЯ

Ось фінал, в реалізацію браузера в JavaScript: https://cosmicrealms.com/blog/2013/03/16/hand-of-cards/ та http://jsfiddle.net/tyyvk/108/


9
Сер, здається, у вас в руці занадто багато тузів. Будь ласка, відійдіть від столу.
Томаш Андрле

Для використання пізнішої версії MooTools загадку потрібно оновити.
tomdemuyt

Відповіді:


30

Теорія

Оскільки ви не вказали, на якій платформі ви це реалізуєте, я опишу алгоритм мовно-агностичним способом:

  1. Спочатку укладайте кожну карту один на одного, надаючи їм однакове початкове положення.
  2. Потім для кожної картки застосуйте поворот (як правило, орієнтований навколо одного з нижніх кутів , але переміщення цього походження дозволить вам налаштувати вигляд вентилятора).
  3. Збільшуйте кут повороту між кожним викликом , залежно від кількості карток та кількості ви бажаєте їх розповсюдження.

Щоб обертання було зосереджено навколо одного з нижніх кутів картки (або біля кута), повинно бути очевидним з його погляду:

введіть тут опис зображення


Впровадження

Щодо того, як це здійснити, це залежить від вашої платформи. У XNA ви можете просто скористатися параметром Origin SpriteBatch.Drawдля зміни центру обертання.

Ось що я отримав із наступного коду (з декількома налаштуваннями на початок, щоб він виглядав краще - в основному походження починається біля правого кута і закінчується біля лівого кута):

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

І результат:

введіть тут опис зображення


7
Додам, що вигляд можна змінити, використовуючи інший центр обертання, якщо ви хочете провести меншу дугу, ви повинні використовувати точку обертання, яка лежить нижче картки.
aaaaaaaaaaaa

@eBusiness Ви маєте рацію, додам це.
Девід Гувейя

Велике спасибі Давид! Я реалізував тут код, який ви показали у JavaScript: jsfiddle.net/tyyvk/7
Sembiance
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.