spiiin: (2D)
Если Unity использовать для игр под мобильные платформы - писать плагины нужно. Потому что есть много полезных 3rd-party библиотек (для кросс-промо, виртуальной экономики, ачивментов/лидербордов, систем покупок, показа рекламы и т.д. и т.п., без чего современных мобильных игр уже почти не бывает), и фич самих платформ, которые не реализованы в движке. А официальная документация какая-то слишком скудная.

на примере плагинов под iphone:
http://docs.unity3d.com/Documentation/Manual/PluginsForIOS.html
Всё что есть - можно положить исходные файлы и статические библиотеки в папку Plugins/iOS, и они скопируются в проект. И всё! :(
- Не поддерживается копирование папок, так что нужно сваливать всё возможное в корневую папку. Если внутри фреймворка есть подпапки - работать он уже не будет.
- Невозможно встроиться в генерируемые стандартные файлы-обертки для ios приложения, если требуется реакция на какие-нибудь стандартные системные сообщения (это пофиксилось - если в Plugins/iOS положить файл с тем же именем, что и генерируемый автоматически в Classes, то он заменит стандартный).
- Невозможно изменить настройки проекта, чтобы добавить флаги компилятору или линкеру. А часто бывает нужно что-то подправить, добавить -all_load, например, чтобы обойти баг при загрузке .a файла, внутри которого есть смешанный сишно-объектносишный код.

Так что этот способ практически бесполезен - надо или хранить отдельно доправленный после генерации проект или запускать отдельно после генерации свою систему обработки напильником. Но запускать её каждый раз руками не труъ, можно врубиться в пайплайн построения игры. Если в папке Assets/Editor лежит файл PostprocessBuildPlayer, то он будет выполнен. В примере пустой перловский скрипт. В него надо вписать свой код модификации проекта.
Получить путь к проекту из скрипта можно так (на python'е):
projectPath = sys.argv[1]
projectFile = projectPath + '/Unity-iPhone.xcodeproj/project.pbxproj'



Небольшой хинт -  если есть купленные плагины от плагинописателей из prime31, можно найти их скомпиленный скрипт (тоже на python'е), и с помощью декомпилятора uncompile немного подсмотреть реализацию полезного для работы с проектом класса XcodeProject.
Tags:
spiiin: (Default)
1. Смешивание языков.
Objective-C код совместим с сишным кодом, но не всегда совместим с С++. Также существует язык Objective-C++, который позволяет более-менее свободно смешивать C++/Objective-C код. Компилятор gcc по умолчанию считает файлы с расширением .m содержащими код на Objective-C, а файлы с расширением .mm - код на языка Objictive-C++, но ему можно явно указать язык с помощью ключа -x

В универсальных заголовочных файлах определить, в какой язык включается файл, можно, проверяя наличие макросимволов __OBJC__ или __cplusplus.

Чтобы вызывать Objective-C код из языка С++, удобнее всего сделать обычный С++-класс-обертку, содержащий членом указатель на класс Objective-C, так как наследование от него невозможно. Если возможности создать класс нет (Objective-C, в отличие от Objective-C++, не дает возможности создавать C++-классы), то проще всего заворачивать вызовы в глобальные функции, и звать их из С++. При этом такие функции, как и обычные сишные, в С++ коде надо объявлять в блоке extern "C", так как компилятор манглит их имена по правилам языка си.

Проще это всё показать примером:
 //h-файл (общий заголовок)
 class ObjClassWrapper
 {
   ObjClass * objClass1;
   ObjClassWrapper(); { [[objClass1 alloc] init]; }
   ~ObjClassWrapper(); { [objClass1 dealloc]; }
   void method1(); { [objClass1 method1]; }
 };
 
 //mm-файл (язык Objective-C++)
 @interface ObjClass
 @end
 
 @implementation ObjClass
 -(void) method1
 {
   NSLog("Method1");
 }
 @end
 
 ObjClassWrapper::ObjClassWrapper() { [[objClass1 alloc] init]; }
 ObjClassWrapper::~ObjClassWrapper() { [objClass1 dealloc]; }
 void ObjClassWrapper::method1(); { [objClass1 method1]; }
 
 //m-файл (язык Objective-C)
 @implementation StaticObjClass
 +(void) method2
 {
   NSLog("Method2");
 }
 @end
 
 void method2() { [StaticObjClassObjClass method2]; }
 
 //c++-файл
 #include <universalHeader.h>   //объявляем класс-обертку
 extern "C" { void method2(); } //объявляем метод-обертку
 
 ObjClassWrapper w; w.method1();  //зовем код на Objective-C
 method2();
 

Про смешивание языков и вызов кода на С++ из языка Objective-C есть статья http://touchdev.ru/documents/963

2. True/Yes
Всегда интересно (раз два три), нафига разные ключевые слова? Главное, чтобы помещалось


3. Динамический Objective-C

3.1 Так как Objective-C является динамической веткой развития языка С++, то проверка наличия методов у экземляров выполняется только во время запуска приложения. Методы среды выполнения, позволяющие динамически оперировать классами и методами классов, находятся в библиотеке libobjc.A.dylib, которая подключается к любой программе. С помощью них можно, например, сделать подмену одного класса другим во всех местах, в которых будет обращения к оригинальному классу:
[[MyBundle class] poseAsClass:[NSBundle class]];  //заменяем класс бандла своим, переопределяя его стандартное поведение.
 
3.2 Однако такой метод уже признан apple устаревшим и вместо него можно подменять отдельные методы класса при помощи class_getInstanceMethod и свойства method_imp у селекторов класса. Описание интересного трика с подменой метода :
http://www.cocoadev.com/index.pl?MethodSwizzling

3.3 Помимо этого в самих классах также можно перегрузить служебные методы, используемые средой выполнения, например, присвоив новый класс свойству isa, проверяющему, какому классу принадлежит объект. Члены класса таким способом поменять нельзя, зато можно полностью сменить интерфейс.
obj->isa = [MyClass class]; 
3.4 Или можно перегрузить методы forwardInvocation: и methodSignatureForSelector: проверяющие само наличие метода у объекта
http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/forwardInvocation:

3.5 Ну и в самом языке есть возможность расширения существующих классов, вплоть до базового NSObject'а, используя категории http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html#//apple_ref/doc/uid/TP30001163-CH20-SW1
Tags:
spiiin: (Default)
Как-то нашел Smurfs' Village, представителя популярных сейчас на iphone/ipad жанра "ферм". Я даже по чуть-чуть в нее поигрывал, вызывая насмешки коллег и предложения купить за смс бутылочки от игровой зависимости. Насмешки вполне справедливые, так как играть без вложения реальных денег сложно и игровые ходы без ускорения могут занимать до 120 часов (или можно купить за реальные деньги ягоды, каждая из которых мгновенно проматывает 6 часов).
А сегодня с подсказки заметил, что игровое время считается не на сервере, а на клиенте. После небольшой проверки выяснилось, что защита состоит из двух уровней.
Первый - если есть доступ в интернет, то при логине сервер сверяет время на устройстве с тем, что должно было пройти с момента первого запуска игры и, в случае несоответствия, просит выставить правильное.
Второй - когда интернета нет, игра обнаруживает перевод времени назад. В этом случае следует сначала внутриигровое предупреждение от Штрумфа-папы, в котором он говорит, что игрок заставляет работать подопечных сверхурочно и им это не нравится. Если повторить мошенничество пару раз, то жители начнут уходить из деревни.
Но вот при переходе в бекграунд игра не измеряет реально прошедшее время, хотя это и можно организовать. А зря не проверяет.
Теперь у меня на айпаде уже могло быть 31 августа, прокачанная до двадцать второго уровня деревня с пятьюдесятью гномами и многими сотнями золота (при том, что за месяц реальной игры докачался только до 10 уровня, получил 10 гномов и денег не было вообще), которая могла бы отметиться в онлайне :)
Информация исключительно в образовательных целях - техника работает и в других "фермах", специальных защит нигде не обнаружилось.
Tags:
spiiin: (Default)
Взлом :
Как самому взломать программу из App Store(прошивка 2.0)
для iOS 4.x процесс отличается лишь немного.
- Берем jailbreak-нутый девайс, ставим cydia, через нее скачиваем openssh, gnu gdb, darwin cc tools и adv-cmds.
- Подключаемся через терминал к устройству с помощью пароля "alpine" (хм, на всех взломанных устройствах он одинаков).
- Смотрим смещение и размер зашифрованной секции через otool
- Запускаем программу, дампим расшифрованную секцию кода, в hex-редакторе подменяем зашифрованную секцию на сдампленную, правим флаг секции на "незашифрованная"
- Выбрасываем лишние файлы из бандла, остальные копируем в свой.

Антивзлом :
Как защитить свою iOS-программу от взлома
- Проверки наличия и состояния файлов. Плохи тем, что можно подложить в бандл левые файлы. Можно "вшивать" в программу хеши файлов, предварительно убедившись, что они не меняются при загрузке в appstore.
- Проверки на jailbreak-нутость устройства. Но некорректно считать пиратами всех, ломающих телефоны.
- Системные проверки. Проверка на то, что сегмент кода зашифрован.
Кажется, самый надежный метод защиты, так как зашифровать его обратно возможности нет. Т.е. взломщик вынужден будет вдобавок к стандартному алгоритму дизассемблировать код и грубой силой зачищать в нем операции проверки. Вдобавок можно заставить программу падать, если она запущена под отладчиком. Эта пара методов спасет от 99% взломщиков.

Главное помнить, что стоит делать не идеальную защиту, а такую, чтобы взлом был невыгодным.
Tags:
spiiin: (Default)
Smurfs' Village


Вспомнилось, как в детстве играл с племянницей в такую же игру, используя фигурки из "Киндер-Сюрпризов", игральные кубики, нити, пуговицы, шашки, детский конструктор, несколько колод карт и фантазию. Деревни разрастались на полкомнаты, а сейвы с перечнем имущества занимали пару тетрадных листов в клеточку.
Tags:
spiiin: (Default)
.. а бывают такие, знакомиться с которыми лучше сразу с раздела Troubleshooting.
Геймдизайнер прислал описание интересного бага – игра падает, если сменить дислокацию. То есть, если физически перейти с айфоном с одного места в другое. Один из программистов вспомнил, что когда он ходил в соседний офис, игра тоже один раз упала. Сначала подумал, что в код закралась какая-то глупая незамеченная ошибка – недавно реализовали много мелких фич в движке. Оказалось – нет, действительно, если играть, положив девайс перед собой, то все будет нормально, а если ходить с ним по офису туда-сюда, то игра рано или поздно падает, не оставляя в логах никакой полезной информации, кроме того, что произошло разыменование нулевого указателя. При том, что игру уже давно пора было релизить, ситуация вызвала не улыбку, а истерический смех.
Где-то полтора дня потратил на изучение поведения приложения с отключением добавленных фич, изучение добавленной игровой логики, исследование поведения игры при запущенных профилирующих инструментах XCode и построение фантастических теорий, как акселерометр может ронять игру. А потом - наткнулся на объяснение феномена в FAQ по интеграции использованной нами библиотеки Crystal, так и озаглавленное - crash when rotating device. Не вдаваясь в детальное описание возникующей ситуации, библиотека сама пытается отслеживать изменение ориентации устройства для того, чтобы рисоваться "лицом" к пользователю. Падения лечатся простой установкой свойства класса либы CrystalSettingShouldAutorotateWorkaround в @"Yes".
Почему не поставить для параметра это значение по дефолту, если разработчикам известно, что может возникнуть такая ошибка – загадка.
Tags:
spiiin: (Default)
Статья-пример с обзором компонента UIWebView на русском.
Сообщество разработчиков под iphone очень напоминает сообщество разработчиков на Delphi и Builder - есть куча статей, описывающих трюки с определенными компонентами, есть куча форумов, где народ спрашивает, как решать возникающие вновь и вновь проблемы, и половина из спрашивающих не понимает, как воспользоваться полученными советами.
Tags:
spiiin: (Default)
Писать на Objective C пришлось намного быстрее, чем хотелось :)
Сегодня занимался налаживанием отношений между OpenKODE и Crystal SDK. В мануале по интеграции Crystal очень доступно, с иллюстрациями описывается, как добавить библиотеку в стандартный XCode проект. Только после проведения описанных действий не работает часть кнопок и залогиниться невозможно.

Наводку на решение нашел тут - http://permalink.gmane.org/gmane.comp.lib.sdl/46505. Там на первый взгляд другая проблема - интеграция OpenFeint и SDL, а решение такое же.
Надо сделать в главном цикле приложения OpenKODE (скорее всего в kdMain) дополнительную проверку, активно ли окно Crystal и если нужно, вызвать дополнительную обработку сообщений, чтобы дать возможность библиотеке отреагировать на тапы по экрану.
Как-то так:
void kdAdditionalUpdate()
{   
    if( achivLib->IsActive() )
    {
        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, TRUE);
    };
}


А для отрисовки сообщений внутри игры надо еще сказать Crystal'у, что в приложении используется OpenGL (точнее ему надо сказать, что Cocos, он поймет). Как это сделать, сказано тут - http://devsupport.crystalsdk.com/default.asp?W24 (доступно только при регистрации).

Тогда взлетит.

<upd> Взлетит, но упадет. Чтобы полет шел без осложнений, надо еще установать свойство CrystalSession activateCrystalSetting в @"YES", чтобы Crystal не пытался поворачивать свой интерфейс при повороте устройства, потому что иначе приложение может упасть, если начать танцевать с айфоном (см. http://spiiin.livejournal.com/14190.html).
Tags:
Nov. 16th, 2009 11:18 pm

Ура!

spiiin: (Default)
Наконец-то вышла наша первая игра под iPhone!

Judgement Day War

JD WAR

Игра - стратегия на тему шестидневной войны, ненапрягающее (впрочем, судя по отзывам, некоторых все-таки сеттинг напрягает) рубилово с участием танков и вертолетов, и с дикой музыкой =). Выглядит вот так:
Tags:

Profile

spiiin: (Default)
spiiin

September 2017

S M T W T F S
     1 2
34 567 89
101112131415 16
17181920212223
24252627282930

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 19th, 2017 11:33 am
Powered by Dreamwidth Studios