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

Впровадження
Щодо того, як це здійснити, це залежить від вашої платформи. У 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();
І результат:
