アプリストアに必要なスクリーンショットをリサイズで一気に作成するコマンド

Screen Shot 2015-06-05 at 8.08.22 PM

こんにちは。

前回アプリを公開したとき(2015年4月)に使った小技ですので、いま有効かどうか未確認ですが、サイズの異なるスクリーンショットを一気に作るコマンドの紹介です。

使用した環境

OS: Mac OS X 10.10.3

準備するもの

自分の場合はiPhone6 に合わせて 750×1336 pixel で、元となるスクリーンショットを5枚作成しました。(今考えると、640×1136 pixel で作っておけば、十分だったかもしれませんが、iPhone6 で 640×1136 のみ対応のアプリを動かすと、ピクセルが拡大されているのが見てわかってしまうので、こだわってしまいました。

 

機種 画面サイズ [Pixel] 必須? 備考
iPhone4s 640×960 必須 そろそろサポートしなくてもよくなるらしい。(もうなっているかも)
iPhone5/5s 640×1136 必須
iPhone6 750×1336 オプション
iPad 1536×2048 iPad対応アプリには必須 とりあえず左記のサイズを用意したら、iPad対応としてサブミットできた。

 

例えば、ss1.png 〜 ss5.png という名前の 750×1336 のスクリーンショット画像を、iphone6という名前のディレクトリに置きます。

Screen Shot 2015-07-24 at 2.23.16 PM

コマンド実行

 

この状態で、ディレクトリ丸ごと、iphone4, iphone5, ipad という名前でコピーします。

 

Screen Shot 2015-07-24 at 2.32.46 PM

サイズの変換には sips コマンドを使います。iPhone6 -> iPhone5 のサイズ変換は、アスペクト比がほぼ等しいので、sips の -z オプションでサイズを指定するだけです。

 

 

iPhone4 や iPad へのサイズ変換は、アスペクト比が異なるので、まず -z オプションでアスペクト比を保つようなサイズに変換したのち、-p オプションでゼロうめをしてサイズを合わせます。こうしないと、単純な引き伸ばしになってしまいます。

 

 

結果

 

プレビューなどで結果を確認します。

ss1 ss1 ss1 ss1

これで、一応は各サイズ用のスクリーンショットが用意できました!(サイドの黒塗りが気になる方は、何か別の手段を使う必要がありますが)

 


Cocos2d-x 公式ソースコードに自分のバグフィックスが取り込まれた

img-cocos2djs

先日 Cocos2d-x の一部、Cocos2d-JS のバグ(彼らは仕様と言うかもしれない)を見つけたので、修正案を GitHub 上で公式に提案(プルリクエスト)してみました。

結果、取り込んでもらえましたので、その時やったことを紹介します。

バクの内容

JS の機能の一つに、JavaScript 側から Objective-C の関数が呼び出せるというものがあります。Cocos2d-JS v3. 6.1 現在、その引数が BOOL 型だったときに値がうまくわたらないので、NSNumber型 を使わなければならないという制限がありました。

[参考]
HOW TO CALL OBJECTIVE-C FUNCTIONS USING JS ON IOS/MAC
http://cocos2d-x.org/docs/manual/framework/html5/v3/reflection-oc/en

JavaScript には int と float の区別はなく、数値は “number” 型なので、int や float はNSNumber を使わなければならないのはよいです。しかし JavaScript でも bool は “boolean” 型があるので、NSNumber を使わなければならないのは違和感がありました。

ソースコードを確認したところ、以下の部分で JavaScript から受けた引数を NSInvocation の引数に変換しているのですが、数値も bool も区別せずに処理していました。

<cocos2d-x/cocos/scripting/js-bindings/manual/platform/ios/JavaScriptObjCBridge.mm>

[gistcode data_gist_id=”d694618edd6f08a811a3″ data_gist_highlight_line=”114″ data_gist_line=”110-119″]

これを isKindOfClass を使い、bool の時だけ特別扱いします。これで BOOL 型を引数とする C++ の関数を、修正することなく呼べるようになりました。

[gistcode data_gist_id=”0b75dc16272371a4e2a5″ data_gist_highlight_line=”114-125″ data_gist_line=”110-129″]

やったこと

バグを見つけるまではよくあることですが、今回は修正案を公式に提案するところまでやってみました。会社のコードとかではよくやってましたが、天下の Cocos2d-x 公式レポジトリに修正案を出すのは緊張します。変な日本人と思われたくない。

修正のコミット

前述の修正を、自分のローカルレポジトリでコミットし、GitHub の自分のクローンしたレポジトリ(自分の場合はshinhirota/cocos2d-x)に push しておきます。

プルリクエスト

フォーク(クローン)してある自分のレポジトリで修正のコミットを済ませていれば、Web上で簡単にできます。Cocos2d-x の開発元は中国の会社なので、レポジトリの管理も中国人エンジニアが行っているようです。詳しいコミットの説明を、英語(か中国語)で添える必要があります。

ss

ss2

説明はマークダウンで記述できるので便利です。十分な説明を書かないと英語で質問メールが来て、それに返事をしたりして時間がかかるか、最悪、無視される恐れがあります。

 

自分の場合は「こんな問題があって、このように直したら動作しました」のようなことを、サンプルコードを添えて、30分くらいかけて書きました。100行の説明より1つのサンプルコードです。

Screen Shot 2015-07-02 at 11.27.30 AM

 

プルリクエストを登録すると、レポジトリの管理者に通知が行くので、運が良ければあとは何もしなくてよいです。

自分の場合は、最初 Cocos2d-x とCocos2d-JSのレポジトリが統合されていたのをしらずに Cocos2d-JS のほうにプルリクエストを登録したら「Cocos2d-xのほうに登録してくれ」と言われてしまいましたが、あとは何もせずにすみました。

Cocos2d-x の管理者が、担当者にレビューを依頼し、その担当者のオーケーが出たので管理者がメインブランチである “v3” にマージしてくれました。やった!

 

 

Fixed iOS/JS-Bind callStaticMethod() with bool arg
https://github.com/cocos2d/cocos2d-x/pull/12598

Screen Shot 2015-07-02 at 11.58.35 AM

Cocos2d-JS の次のバージョン (v3.6.2?) には取り込まれるはずなので楽しみです。

[2015年8月27日 追記] 本修正が Cocos2d-x v3.8 (JSの一部がxに統合されたため、x からのリリース) に取り込まれてリリースされました!

まとめ

Unity人気に押され気味の印象がある Cocos2d-x/JS ですが、オープンソースであると言うのは Unity にはない魅力ですね!


Cocos2d-JS で広告を表示する (iOS編) その2

img-cocos2djs

Cocos2d-JS で広告を表示する (iOS編) その1で単純な表示の方法を紹介したので、今回は位置の調整、表示/非表示を行う手順をまとめます。

Cocos2d-JS が生成するプロジェクトファイルは Interface Builer / Storyboard を使用していないので、ここでも使用しませず、ソースコードのみで実現します。

使用した環境

OS: Mac OS X 10.10.3
Xcode: 6.3.2
Cocos2d-JS: v3.6.1
Google Mobile Ads SDK iOS: 7.3.1

位置の調整

固定の位置で良い場合は、GADBannerView の frame プロパティ を設定すれば反映されます。以下は、画面の下部中央に配置する場合の例です。

<./ios/AppController.mm>

    {
        GADBannerView *gadView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];

        gadView.adUnitID = @"ca-app-pub-3940256099942544/2934735716";  // Official Test ID
        gadView.rootViewController = viewController;
        [gadView loadRequest:[GADRequest request]];

        [viewController.view addSubview:gadView];

        // gadView を画面下部の中心に配置
        CGRect contentFrame = viewController.view.bounds;
        CGRect bannerFrame = gadView.frame;
        bannerFrame.origin.y = contentFrame.size.height - bannerFrame.size.height;
        bannerFrame.origin.x = contentFrame.size.width / 2 - bannerFrame.size.width / 2;
        gadView.frame = bannerFrame;
    }

ただし画面回転に対応したり、親ビューがレイアウトを変更したりする場合、ビューコントローラーの viewDidLayoutSubviews メソッドをオーバーライドするなどの対処が必要ですが、ここでは省略します。

うまく動作すれば、広告が画面の下部中央に表示されます。

実行結果Screen Shot 2015-06-21 at 1.27.51 PM

表示/非表示

やっと Cocos2d-JS 特有の話になります。

ゲームなどで、タイトル画面では広告を表示し、ゲーム中は広告を非表示にしたりしたいことがあると思います。そのために、まずは JavaScript から C++ の関数を呼ぶ必要があります。Cocos2d-JS では JavaScript 側に jsb.reflection.callStaticMethod という関数が用意されています。名前の通り、スタティックメソッドしか呼びだせません。

C++側

まずC++側で、任意のクラスのスタティックメソッドを用意します。

そのためのクラスを作っても良いですが、ここでは変更を少なく抑えるため既存のクラス AppController isAdVisible と setAdVisible というスタティックメソッドを追加します。

C++側では、戻り値、引数として BOOL, 数値 (NSNumber), 文字列 (NSString) が使用できます。ただし現在の Cocos2d-JS の実装の制限として、BOOL の引数を受ける場合、NSNumber* で受けて boolValue に変換しないとうまく動作しないので注意してください。(将来改善されるかもしれません)

<./ios/AppController.h>

@interface AppController : NSObject <UIAccelerometerDelegate, UIAlertViewDelegate, UITextFieldDelegate,UIApplicationDelegate>
{
    UIWindow *window;
    RootViewController    *viewController;
}

// 追加
+ (void) setAdVisible:(NSNumber*) isVisible;
+ (BOOL) isAdVisible;

@end

<./ios/AppController.mm>

// gadView をローカル変数ではなくスタティック変数にする
static GADBannerView* gadView = nullptr;
@implementation AppController
 :
(中略)
 :
+ (void) setAdVisible:(NSNumber*) isVisible {
    gadView.hidden = ([isVisible boolValue] == false);
}

+ (BOOL) isAdVisible {
    return gadView.hidden == false;
}

@end

JavaScript側

Cocos2d-JSのサンプルのメニューボタンを押したときに、先ほど作成したC++ のメソッドを呼び出し、表示/非表示をトグルできるようにします。

<./src/app.js>


var HelloWorldLayer = cc.Layer.extend({
    sprite:null,
    ctor:function () {
        //////////////////////////////
        // 1. super init first
        this._super();

        /////////////////////////////
        // 2. add a menu item with "X" image, which is clicked to quit the program
        //    you may modify it.
        // ask the window size
        var size = cc.winSize;

        // add a "close" icon to exit the progress. it's an autorelease object
        var closeItem = new cc.MenuItemImage(
            res.CloseNormal_png,
            res.CloseSelected_png,
            function () {
                cc.log("Menu is clicked!");

                // 現在の表示状態を取得
                var isVisible = jsb.reflection.callStaticMethod(
                    "AppController",
                    "isAdVisible"
                );

                // 表示/非表示を設定
                jsb.reflection.callStaticMethod(
                    "AppController",
                    "setAdVisible:",
                    isVisible == false
                );

            }, this);
        closeItem.attr({
            x: size.width - 20,
            y: 20,
            anchorX: 0.5,
            anchorY: 0.5
        });

        var menu = new cc.Menu(closeItem);
        menu.x = 0;
        menu.y = 0;
        this.addChild(menu, 1);

うまくいけば右下のメニューボタンを押すたびに広告の非常/非表示が切り替わります!

Screen Shot 2015-06-21 at 7.16.56 PMScreen Shot 2015-06-21 at 1.27.51 PM

参考

HOW TO CALL OBJECTIVE-C FUNCTIONS USING JS ON IOS/MAC
http://cocos2d-x.org/docs/manual/framework/html5/v3/reflection-oc/en

 


Cocos2d-JS で広告を表示する (iOS編) その1

img-cocos2djs

こんにちは。Cocos2d-JS で広告を表示したときの手順をまとめます。

概要

今回は、とりあえず AdMob を表示するまでをまとめます。実際のアプリに組み込む場合、位置の調整、表示・非表示などの制御が必要だと思いますが、それについては次回以降。

使用した環境

OS: Mac OS X 10.10.3
Xcode: 6.3.2
Cocos2d-JS: v3.6.1
Google Mobile Ads SDK iOS: 7.3.1

手順

ただ単にバナー広告をずっと表示していればよい場合は、JavaScript 側ではなにもせず、iOS 上の Objective-C++ 側の View に AdMob の GADBannerView を貼り付ければよいです。

JavaScript (Cococs2d-JS) とは関係のない話になってしまいますが、以下のように AdMob を組み込みます。

AdMob SDK をダウンロード

以下のページから googlemobileadssdkios.zip をダウンロードし、解凍します。

Downloads | Mobile Ads SDK | Google Developers
https://developers.google.com/mobile-ads-sdk/download?hl=ja#downloadios

Screen Shot 2015-06-19 at 9.56.32 AM

zip の中身はこのようになっています。

Screen Shot 2015-06-19 at 10.05.38 AM

Xcode プロジェクトに追加

広告を表示したい Cocos2d-JS プロジェクトに含まれる Xcode プロジェクトに、ダウンロードした SDK を追加します。

(参考:Cocos2d-JS のサンプルを動かしてみる (iOS編))

Xcode でプロジェクトを右クリックし、[Add Files to “xxxx”…] を選びます。

Screen Shot 2015-06-19 at 10.20.48 AM

先ほどダウンロードし、展開しておいた GoogleMobileAds.framework を選びます。この際、Copy items if needed のチェックはON、Added folders は Create groups、Add to targets は xxxxx iOS のみチェック、にします。

ss

Framework の追加

AdMob 公式ページの最新の手順では @import 文を使えば Framework は自動的に追加されると書かれていますが、Cocos2d-JS/x のプロジェクトでは Objective-C++ (.mmファイル) を使っているからわかりませんが、@import がうまくいきませんでした。

ここでは手動で Framework を追加する方法でやります。以下の Framework を プロジェクト設定からリンク対象に追加します。

  • SystemConfiguration
  • StoreKit
  • MessageUI
  • EventKitUI
  • EventKit
  • AdSupport
  • CoreTelephony
  • CoreMedia

Screen Shot 2015-06-20 at 8.58.00 AM

AdView 表示コードを追加

最低限、AppController.mm に以下のコードを追加すれば AdMob 広告が表示されます。

./ios/AppController.mm

 

#import "GoogleMobileAds/GADRequest.h"    //追加
#import "GoogleMobileAds/GADBannerView.h" //追加

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    // didFinishLaunchingWithOptions 内に以下のコードを追加
    {
        GADBannerView *gadView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];

        gadView.adUnitID = @"ca-app-pub-3940256099942544/2934735716";  // Official Test ID
        gadView.rootViewController = viewController;
        [gadView loadRequest:[GADRequest request]];

        [viewController.view addSubview:gadView];
    }

}

 実行結果

うまくいけば画面左上部に AdMob のテストバナーが表示されます。

Screen Shot 2015-06-20 at 9.36.59 AM

次回「状況に応じて表示/非表示を切り替える場合」についてまとめる予定です。

参考

AdMob iOS ガイド (オフィシャルドキュメント)
https://developers.google.com/mobile-ads-sdk/docs/admob/ios/quick-start?hl=ja