[Cocos Creaotr] cc.Spriteの動的生成とSpriteFrameの読み込み

2017 年 12 月 21 日 Categories: JavaScript | Tags: ,

大前提

Cocos Creatorは、Cocos2d-xのための開発環境ではない

ひとつの独立した環境で、ソースコードのライブラリ部分(API)もCocos2d-xと互換性がない面もある。

生成方法

new cc.Sprite()では生成できない。

cc.Node#addComponent(cc.Sprite)を使う。

var node = new cc.Node();
var sprite = node.addComponent(cc.Sprite);

これで、該当NodeにSpriteが入った状態になる。

Cocos Creatorでは、SpriteをaddChild()できない。名前が同じでも、Cocos2d-xのSpriteとは中身が異なるため。

なおこの際、Spriteは左下にアンカーポイントがあるとみなして、該当Nodeの位置に設置される。そして、NodeのアンカーポイントはSpriteの中心位置になる。

Cocos Creatorの座標系に関しては、くわしくはこちら

実際の画像を適用:SpriteFrameを使う

上記のままだと、空のSpriteで何も表示されない。

この場合、cc.Sprite.spriteFrameプロパティに新規に生成したSpriteFrameを適用する。

SpriteFrameとは、一般的な用語でいうスプライトシートのこと。

該当画像のSpriteFrameを読み込む

ただしCocos Creatorでは、SpriteFrameをnewで生成するのは非推奨。

ネイティブコード(C++)版との互換性が一部失われるため。

C++にはガベージコレクションの機能がないため、自分でretain()・release()して参照カウンタによってメモリ管理する必要があるが、JavaScript版ではその必要がない。

実際にnew SpriteFrame()を使うと、警告が出る。SpriteFrame#clone()も同様。

そこでCocos Creatorでは、cc.loader.loadRes(path)で該当ファイルを読み込んで使う。

SpriteFrameを直接読み込む=ロードしてインスタンスを生成するには、基本的にこの方法しかない。cc.loader.load()を使うと、画像ファイルはcc.Texture2Dオブジェクトとして読み込まれてしまうため。

なお、この関数で読み込む画像は「assets/resources」以下にかならず設置する必要がある

しかも非常に混乱しやすいが、指定するパスはassetsだけでなくresourcesも省く必要がある。

(おそらくは、Cocos2d-JSの名残。Cocos CreatorはファイルI/O周りがすっきりとせず、わかりづらい部分が多い)

// パスは"resources/images/sample.png"ではない
cc.loader.loadRes("images/sample.png",  cc.SpriteFrame, function (err, spriteFrame) {
    if (err) {
        cc.error(err);
        throw new Error("loading error");
    }
    
    sprite.spriteFrame = spriteFrame;
});

なお、SpriteFrame#setRect()を使えば、テクスチャ画像の特定の領域のみを表示させることができる。

sprite.spriteFrame.setRect(new cc.Rect(0, 0, 15, 15));

該当画像のTexture2Dを読み込む

cc.loader.load()を使う。

ただし! このload()関数ではパスを指定するとき、assets/resourcesディレクトリ内のファイルであっても、resourcesを含める必要がある

つまり、assets内ならばresourcesディレクトリ以外にファイルがあってもかまわない。

非常にトリッキーなので要注意。

cc.loader.load("resources/images/sample.png", function (err, tex) {
    if (err) {
        cc.error(err);
        throw new Error("loading error");
    }
    
    sprite.spriteFrame.setTexture(tex);
});