はじめに
この記事を見た方。
多分、僕と同じで古臭い技術を使っている方でしょう。
本当ならcocos2d-x
やUnity
などで開発をしたいところが、Swift
を使いたいからなどでSpriteBuilder
を使っているかと思います。
※他の技術を覚えるのが面倒という方もいると思いますが・・・w
(もはやUnity
の一人勝ちの気もしてますが・・・。残念です。)
僕個人的にはSpriteBuilder
はかなり名器だと思っているのですが、スポンサーが抜けたためか更新は止まりAppStoreからも削除されました。
非常に残念です。
僕も現在作っているゲームを最後にSpriteBuilder
をやめる事にしますが、今回は無理やり使おうと思います。
その際に問題となる箇所をここに記載しておきます。
画面遷移
iOS9・・・というか、Capitan
から以下のコードが落ちるようになりました。
(xCodeのバージョンのせいかもしれない。とにかく最新だと落ちます。)
-(void)draw:(CCRenderer *)renderer transform:(const GLKMatrix4 *)transform
{
typedef id (*Func)(id, SEL);
((Func)objc_msgSend)(self, _drawSelector);
}
この箇所は以下のように書き換えると動きます。
-(void)draw:(CCRenderer *)renderer transform:(const GLKMatrix4 *)transform
{
// typedef id (*Func)(id, SEL);
// ((Func)objc_msgSend)(self, _drawSelector);
void (*Func)(id, SEL) = (void(*)(id, SEL)) objc_msgSend;
Func(self, _drawSelector);
}
日本語対応
iOS9より[NSLocale preferredLanguages]
の戻り値が変わります。
そのため独自で言語管理をしていたサービスは軒並み英語
になったり、落ちたりしてます。
(ファイナルファンタジーなどのメジャーどころですら、対応に手間取っていたのを知っている方もいるでしょう。)
SpriteBuilder
も同様です。
最新のCococs2d
のコードを見ると改善されてますが、それでも不完全でしたので僕は以下のようにして対応しました。
- (void) loadStringsFile:(NSString*) file
{
// Load default localization dictionary
NSString* path = [[CCFileUtils sharedFileUtils] fullPathForFilename:file];
// Load strings file
NSDictionary* ser = [NSDictionary dictionaryWithContentsOfFile:path];
// Check that format of file is correct
NSAssert([[ser objectForKey:@"fileType"] isEqualToString:@"SpriteBuilderTranslations"], @"Invalid file format for SpriteBuilder localizations");
// Check that file version is correct
NSAssert([[ser objectForKey:@"fileVersion"] intValue] == 1, @"Translation file version is incompatible with this reader");
// Load available languages
NSArray* languages = [ser objectForKey:@"activeLanguages"];
// Determine which language to use
NSString* userLanguage = NULL;
NSArray* preferredLangs = [NSLocale preferredLanguages];
for (NSString* preferredLang in preferredLangs)
{
if ([languages containsObject:preferredLang])
{
userLanguage = preferredLang;
break;
}
}
// Create dictionary for translations
_translations = [[NSMutableDictionary alloc] init];
// Load translations
if (userLanguage != NULL)
{
NSArray* translations = [ser objectForKey:@"translations"];
for (NSDictionary* translation in translations)
{
NSString* key = [translation objectForKey:@"key"];
NSString* value = [(NSDictionary*)[translation objectForKey:@"translations"] objectForKey:userLanguage];
if (key != NULL && value != NULL)
{
[_translations setObject:value forKey:key];
}
}
}
}
このメソッドを以下のように変更します。
- (void) loadStringsFile:(NSString*) file
{
// Load default localization dictionary
NSString* path = [[CCFileUtils sharedFileUtils] fullPathForFilename:file];
// Load strings file
NSDictionary* ser = [NSDictionary dictionaryWithContentsOfFile:path];
// Check that format of file is correct
NSAssert([[ser objectForKey:@"fileType"] isEqualToString:@"SpriteBuilderTranslations"], @"Invalid file format for SpriteBuilder localizations");
// Check that file version is correct
NSAssert([[ser objectForKey:@"fileVersion"] intValue] == 1, @"Translation file version is incompatible with this reader");
// Load available languages
NSArray* languages = [ser objectForKey:@"activeLanguages"];
// Determine which language to use
NSString* userLanguage = NULL;
NSArray* preferredLangs = [NSLocale preferredLanguages];
for (NSString* preferredLang in preferredLangs)
{
// now loop thru languages from our cocosbuilder
for (NSString *localizedLanguage in languages)
{
// doing range of string as we might have en-GB set in our phone and that will match our en from the activeLanguages
if ([preferredLang rangeOfString:localizedLanguage].location != NSNotFound)
{
userLanguage = localizedLanguage;
break;
}
}
if (userLanguage != NULL) {
break;
}
}
// Create dictionary for translations
_translations = [[NSMutableDictionary alloc] init];
// Load translations
if (userLanguage != NULL)
{
NSArray* translations = [ser objectForKey:@"translations"];
for (NSDictionary* translation in translations)
{
NSString* key = [translation objectForKey:@"key"];
NSString* value = [(NSDictionary*)[translation objectForKey:@"translations"] objectForKey:userLanguage];
if (key != NULL && value != NULL)
{
[_translations setObject:value forKey:key];
}
}
}
}
これでSpriteBuilder
で言語管理ができるようになります。
ワーニング
とにかくワーニングがひたすら出ます。
以下のワーニングが30個くらい出てきます。
ld: warning: object file (/.../Build/Products/Debug-iphonesimulator/libcocos2d.a(IOSVersion.o)) was built for newer iOS version (9.3) than being linked (8.0)
これはこちらのリンクの通りで、以下の対応をすればワーニングが出なくなります。
The culprit is the minimum deployment target for the ObjectAL library -
In Xcode delve into the cocos2d project -> external -> ObjectAL project:
Goto build settings and search for 'deployment target'
and set the value to be <= your main project minimum deployment target.
上記の通りで
「cocos2d project -> external -> ObjectAL」のフォルダをたどってから「build settings」を表示します。
その中の「deployment target」を自分のプロジェクトに合わせた最小ターゲットにすればOKです。
最後に
僕は最近偽りの物語というゲームを作りました。
その資産を使いたいので、今回はこのまま突き進む事にしました。
なので、この記事では困ったことをここに追記していこうと思っています。
同じSpriteBuilder
で困っている方は是非ストック&コメントお願いします。
数少ないSpriteBuilder
を使っている同志同士で頑張りましょう!w
ちなみに偽りの物語のスクリーンショットはこんな感じです。
よければ、遊んでください♪
TownSoft
僕はTownSoftという屋号で仕事をしていますので、何かあればご連絡ください。