Иногда программисты изобретают свои «велосипеды», но действительно ли это плохо, особенно если творение не отличимо от оригинала, а автор получает бесценный опыт? Эта история началась чуть более года назад с появлением у моей супруги современного смартфона. Она попросила найти пасьянс «Косынку», такой же как был когда-то на настольной Windows. Просмотрев десяток программ, я был неприятно удивлен — почти везде было неудобное управление, спорные картинки карт, море дополнительных наворотов вроде 250 пасьянсов в одном, установки фотографии на рубашку и блекджека с блудницами. В результате, выбрали один из более-менее годных вариантов и на какое-то время об этом забыли.
Пролетел год и я начал писать программы для мобильных. При этом ребром стал вопрос кросс-платформенности, отладки in-app покупок, подготовки контента под разные платформы. Была мысль сделать для пробы пера «Тетрис» или очередной калькулятор, но все же в качестве «велосипеда» я выбрал «Косынку». Идейным стрежнем проекта стало максимально точное повторение старого, доброго пасьянса из набора игр Windows.
Контент
Первая проблема возникла с графикой: в интернете полно рисунков карт, многие из них бесплатны, но почти все довольно вычурны, странно смотрятся на мобильных экранах, да и просто не похожи на старые карты из cards.dll. Карты для Windows попиксельно рисовала талантливый дизайнер Сюзан Кэр в 1989м году, в 16-ти цветном режим. При желании их легко найти в сети, но использовать наврядли можно без нарушений IP. Гораздо интереснее оказались карты, используемые в некоторых играх мира Linux — они распостранялись под GPL лицензией, хоть и выглядели немного странно, с черно-белыми старшими картами (фигурами). Автором этих карт оказался тов. Oxymoron, на сайте которого лежат сами картинки и скрипт их сборки. Он нарисовал собственные цифры и иконки мастей, а фигуры взял из неизвестного источника, но довольно похожие на оригинал. Я немного доработал скрипт, чтобы он сохранял карты в PNG, добавил прозрачность, а заодно раскрасил вручную старшие карты. Для иконки туза пик была нарисована собственная стилизованная картинка, по аналогии с оригиналом напоминающая кельтский узор. Она же и стала иконкой программы.Для рубашки была выбрана самая приятная (на мой взгляд) картинка с пляжем и пальмой с ручной прорисовкой. Получилось очень узнаваемо — взгляд на картинке не задерживается, хотя если всмотреться, то разница очевидна.

Геймплей
Как оказалось, геймплей в «Косынке» не так уж и прост за счет подсчета очков, таймера, выдачи по одной/три карты, а заодно и режима Vegas. К примеру, игра на деньги с выдачей по одной карте (т.е. без возможности переворачивать колоду), заметно отличается от стандартной: ее цель перенести как можно больше карт к тузам и набрать более $42, чтобы выйти из минуса и начать следующую партию, если пасьянс не сложился. В игре же на счет перенос карты из колоды «вниз», а потом к тузам дает 15 очков, в то время как сразу к тузам — только 10. Естественно, задокументировано это очень условно, потому пришлось загнать оригинальную игру в wine и провести полноценный ресерч.Код
Бизнес логику программы я написал на чистой Java 1.6, без использования сторонних библиотек, Android, Swing и пр. Для Android эта часть собирается в виде отдельной библиотеки и подключается к GUI проекту без особых проблем, а вот для других ОС я решил идти нестандартным путем и не заниматься портированием «в лоб» на другие языки. После некоторой обработки напильником проект Sharpen смог преобразовать этот код в чистый C#, что открыло путь к реализации под iOS c помощью MonoTouch, а в будующем и для Windows Phone 7/8. Простейшие юнит-тесты показали, что логика работы не изменилась, трансляция прошла успешно. В среде MonoTouch я без особых нюансов реализовал отображение GUI, отладил игру на эмуляторе и iPod Touch и отправил на одобрение в iTunes Store. Настройки программы я реализовал с помощью внешнего биндинга к KGN.InAppSettings, споткнувшись о некоторые мелочи вроде отсутствия поддержки thumb для внешних библиотек.
Проблемы
После недели аппрува в Apple, моя «Классическая Косынка» появилась в iTunes Store. Я ожидал критики графики или возможных лицензионных споров, но в первый же день все отзывы были однозначны: игра вылетает сразу при запуске. Игру из магазина я убрал и начал изучать проблемы. У моих знакомых игра запускалась отлично, эмулятор и iPod Touch 4g тоже не показывали никаких сбоев. Понадобилось несколько дней и помощь форумчан, чтобы найти первый серьезный баг: в региональных стандартах iOS для Европы и Украины указан десятичный разделитель «точка», а в России это уже «запятая». Соответственно, преобразование float в строку работало на одних устройствах и крашилось на других. В течение недели после отправки на аппрув, оказалось, что игра еще и крашилась при запуске в альбомном режиме. На iPod и iPhone все программы стартуют в портретной ориентации, потому обнаруживается это только на iPad, которого у меня не было. На ре-аппрув ушла еще неделя, за которорую игра окончательно пропала из категории «Новое» и успешно утонула за пределами Top 1000. К тому же, иконка с прозрачным фоном, отлично принятая в Android Market, была похабно обработана скриптами Apple и стала откровенно не симпатичной.High-definition
К тому моменту, как проект заработал нормально, были заменены иконки и пр., у меня появился новый iPad, где я обнаружил, что разрешения карт откровенно не хватает для 9.7" экрана, да и на Retina Display «прыгающие карты» откровенно тормозят. Борьба с лагами заняла пару дней, за которые я успел основательно породниться с Core Animation, а вот для улучшения разрешения пришлось нанять дизайнера. Результатом его работы стали цифры, буквы и масти высокого разрешения, максимально похожие по стилю на оригинал. Фигуры я увеличил с помощью Photo Zoom Pro, чтобы не потерять аутентичность пиксельной графики. Вышло не идеально, но все же довольно уда��но.На эту работу было потрачено немало усилий, потому было логично выпустить отдельно HD версию, а заодно добавить внутреигровую покупку в обычную версию. С реализацией In-App Purchases под MonoTouch оказалось не все просто, а чтобы смотрелось это органично, я решил избавиться от KGN.InAppSettings и сделать единый интерфейс для настроек и покупок. Технические детали я тут описывать не буду, но набралось их немало, включая мартышкин труд по созданию собственных Settings, идентичных системным, борьба с отсутствием документации к StoreKit для Mono, разные баги с отладкой покупок и пр.
Профит
Игра не стала шедевром, не попала в топы, да и наврядли окупит стоимость разработки и работу дизайнера, но все же теперь у меня на всех устройствах (включая и смартфон, с которого все началось) есть «Косынка», максимально похожая на оригинал, ставший родным еще со времен Windows 3.1. Опыт написания портируемого кода на Java и переноса его на C# оказался просто бесценным — подобным методом моей командой портировано уже несколько крупных Android проектов на iOS, а за счет отладки на небольшой игре получилось неплохо изучить подводные грабли MonoTouch и вообще разработки под iOS, а заодно написать некое количество полезных библиотек. Может кто-то и посмеется над этой историей, но как по мне, «велосипед» вышел весьма годным, а время было потрачено совсем не зря.
Post Scriptum
Я специально избегал углубления в подробности портирования и работы с MonoTouch, потому что каждая из них достойна отдельного топика. Рано или поздно соберусь с силами и выложу на суд общественности свой класс для In-Game Settings, менеджер покупок и пр.
Ссылки на проект я не выкладываю, чтобы не посчитали рекламой.
Если кому нужен обновленный скрипт генерации карт, пишите на scanwords@runserver.net, он является derivative work от GPL проекта, потому выложу без проблем.