ひっさしぶりにCocos2d-xでも触ってみようかなと思って、チャレンジしてみた。今からC++はないよな…てことでJavaScriptで作ってみる。

SDKのセットアップ

  • ダウンロード:Download Cocos2d-x Cocos2d-html5 Cocos Studio | Cocos2d-xの「Cocos2d-x」をダウンロードする(2015/10/18現在 v3.8.1)
  • Zipファイルを展開して都合のいいパスに配置
  • コマンドラインツールのパス $/tools/cocos-console/bin にパスを通して、 cocos コマンドを使えるようにする

ドキュメント

プロジェクトの作成

  • cocos new プロジェクト名 -p バンドルID -l js -d 生成先ディレクトリ で新規プロジェクト作成

実行

  • cocos run -p {web|android|ios}
  • webを指定するとサーバが走り、ブラウザが開いてそれ上で動く。プログラムを変更した場合リロードしてやれば変更が反映される。
  • Androidでの実行にはUSBで端末を繋いで、iOSでの実行はシミュレータで走る

iOSの実機で動かす場合には、 $/frameworks/runtime-src/proj.ios_mac/${YOUR_PROJECT}.xcodeproj がXcodeのプロジェクト

ファイル構成

  • $/project.json : プロジェクトの定義ファイル。JavaScriptのソースを追加するときは jsList に追加する。
  • $/src/ : JavaScriptのコードはこの中に入れる。
  • $/res/ : 画像などのリソースはこの中に入れる。リソースを追加する場合には、$/src/resource.jsで定義されているグローバル変数resに追加する。

プログラム

シーンごとにLayerクラスを継承して、そのコンストラクタ内でオブジェクトを階層構造で構築するのがCocos2d-xでのアプリの作り方。

// app.js
var HelloWorldLayer = cc.Layer.extend({
  ctor:function () {
    this._super();
    ...
  }
});

スプライト

// app.js
    var sprite = new cc.Sprite(res.sprite_png);
    sprite.setPosition(x, y);
    this.addChild(sprite, 10);

スプライトフレームキャッシュ・スプライトフレーム

スプライトをアニメーションさせる場合、スプライトフレームというものを使ってそれを切り替えることで見た目を変えてやる。スプライトフレームは都度作りなおさずに済むように、キャッシュさせてやる。

cc.spriteFrameCacheaddSpriteFrameで名前に対応するスプライトフレームを登録しておいて、スプライト作成時に登録したスプライトフレームから作成したり、任意のタイミングで切り替えてやることができる

// app.js
    var spriteFrame = new cc.SpriteFrame(res.character, cc.rect(x, y, w, h));
    cc.spriteFrameCache.addSpriteFrame(spriteFrame, 'char-walk1');
    ...
    var sprite = new cc.Sprite(cc.spriteFrameCache.getSpriteFrame('char-walk1'));
    ...
    sprite.setSpriteFrame(cc.spriteFrameCache.getSpriteFrame('char-walk2'));

試してないけどC++版からの推測によれば cc.spriteFrameCache.addSpriteFramesでスプライトシートからスプライトフレームが作れると思う。

メニュー・ボタン

メニューのボタンを配置して、押されたらなんか反応させるには、ボタン用の画像を用意して

// app.js
    var menuBtn = new cc.MenuItemImage(res.button_png, res.button_png, function() {
      console.log('Pressed!');
    });
    menuBtn.setPosition(200, 100);
    var menu = new cc.Menu(menuBtn);
    menu.setPosition(0, 0);
    this.addChild(menu, 100);

シーンの遷移

cc.director シングルトンがシーンを管理していて、シーンを遷移させるには(行ったっきり)

// app.js
      cc.director.runScene(new DestinationScene());

戻ってこれるようにするには、試してないけど Director#pushScene が使えると思う。

cc.TransitionSceneを継承した各エフェクトのクラスを使ってやれば、シーンの遷移が一瞬で切り替わるんじゃなくエフェクトをさせながら遷移させる、はず。

キー入力

イベントマネージャ(cc.eventManager)を使ってキー入力を受け取る

// app.js
    if ('keyboard' in cc.sys.capabilities) {
      cc.eventManager.addListener({
        event: cc.EventListener.KEYBOARD,
        onKeyPressed: function(key, event) {
          switch (key) {
            ...
          }
        },
        onKeyReleased: function(key, event) {
          ...
        },
      }, this);
    }

タッチ入力

キーボードと同様にイベントマネージャを使う

// app.js
    cc.eventManager.addListener({
      event: cc.EventListener.TOUCH_ONE_BY_ONE,  // or TOUCH_ALL_AT_ONCE
      onTouchBegan: function(touch, event) {
        ...
        return true;  // キャプチャする
      },
      onTouchMoved: function(touch, event) {
        var x = touch.getLocationX(), y = touch.getLocationY();
        ...
      },
      onTouchEnded: function(touch, event) {
        ...
      },
    }, this);

ブラウザで動かした場合にはマウスにも反応してくれる。

毎フレームなんか処理する

初期化時にノードのscheduleUpdateを呼び出してやると、その後updateメソッドが毎フレーム呼び出される。

// app.js
  ctor: function() {
    ...
    this.scheduleUpdate();
  },

  update: function() {
    // 毎フレーム呼び出される
  },

注意点

cc.Rectの作成はnewじゃなくてcc.rectで

cc.Rectの作成にnew cc.Rectとすると、ブラウザでは動くけどAndroidなどで動かそうとするとエラーが出る:

D/cocos2d-x debug info(24118): JS: assets/src/game.js:157:TypeError: cc.Rect is not a constructor

ドキュメントにもcc.rectを使え、と書いてある

please do not use its constructor to create rects, use cc.rect() alias function instead.

TODO

  • サウンド
  • ネイティブ連携
  • SDKBOXサードパーティのSDKが簡単に組み込めるという話

参考

.