【enchant.js】Nodeの表示順 v0.6対応版【Advent Calendar】

はてなのアクセス解析のぞくと、Nodeの表示順で検索されて当方のブログに辿り着く方がいらっしゃるようで。enchant.jsもバージョンが上がったことですし、ここいらで再度まとめてみたいと思います。

まずは基本のおさらい。
enchant.jsでは、addChildをすると手前に、手前にという具合にNodeを重ねていきます。

for (var i = 0; i < 3; i++) {
    var spr = new Sprite(32, 32);
    spr.image = game.assets['chara1.png'];
    spr.frame = i;
    spr.x = i * 8;
    game.rootScene.addChild(spr);
}

上述のコードの場合、最後にaddChildされたframe == 2のSpriteがもっとも手前に表示され、その後ろにframe == 1、frame == 0と続きます。

enchant.jsには、もうひとつNodeをGroupに追加する関数があります。それがinsertBeforeです。上述のコードのfor文の後に、以下のコードを加えて下さい。

var ins = new Sprite(32, 32);
ins.image = game.assets['chara1.png'];
ins.frame = 5;
ins.x = 14;
game.rootScene.insertBefore(ins,game.rootScene.lastChild);

表示されるSpriteの順が、手前からframeの値が2、5、1、0となっているのが分ります。

では、今度はGroupが介在したらどうなるのでしょう。

var grp1 = new Group();
game.rootScene.addChild(grp1);
var grp2 = new Group();
game.rootScene.addChild(grp2);

var spr1 = new Sprite(32, 32);
spr1.image = game.assets['chara1.png'];
spr1.frame = 0;
spr1.x = 0;
grp2.addChild(spr1);
var spr2 = new Sprite(32, 32);
spr2.image = game.assets['chara1.png'];
spr2.frame = 5;
spr2.x = 8;
grp1.addChild(spr2);

Spriteだけに注目するとspr1、spr2の順でaddChildされているわけですから、spr2が手前に来るはずです。しかしGroupはgrp1、grp2の順で追加されており、grp2の方が手前にあります。spr1はgrp2に、spr2はgrp1にaddChildされているわけですから、表示も親NodeであるGroupの表示順に左右されます。

ちなみにGroupにも座標があります。

var grp = new Group();
grp.x = grp.y = 160;
game.rootScene.addChild(grp);

var spr = new Sprite(32, 32);
spr.image = game.assets['chara1.png'];
grp.addChild(spr);

子Nodeは親Nodeの座標に左右されることが分ります。
気になるのは当たり判定ですね。上述のコードに以下を足して下さい。

var obj = new Sprite(32, 32);
obj.image = game.assets['chara1.png'];
obj.y = 160;
game.rootScene.addChild(obj);

grp.onenterframe = function() {
    this.x -= 4;
    if (obj.intersect(spr)) console.log("ok");
}

相対的な座標ではなく、画面上の絶対座標で当たり判定が行われていることが分ります。(前は違ったんだよね。苦労した......)

「同じGroupに所属させつつも表示位置を細かく設定したい」という場合はどうでしょうか。

var grp = new Group();
game.rootScene.addChild(grp);

var node = new Node();
grp.addChild(node);

var spr1 = new Sprite(32, 32);
spr1.image = game.assets['chara1.png'];
spr1.frame = 0;
spr1.x = 0;
grp.addChild(spr1);
var spr2 = new Sprite(32, 32);
spr2.image = game.assets['chara1.png'];
spr2.frame = 5;
spr2.x = 8;
grp.insertBefore(spr2,node);

至極簡単な話でして、マーカーとなる非表示のNodeをまず設置します。そしてそれを軸に表示するNodeを親Nodeに追加してゆきます。上述のコードは2レーンですが、3レーンにする場合はさらに非表示Nodeを追加します。「走れ! ハチ!」の輪っかくぐりはこれの応用なんです(Group分けはしてないですけどね)。

最後にいくつか。
こちらでも指摘したaddChildの問題、未だ健在です。一度addChildされたNodeを再度addChildしなおすと、表示順は変更されるのですが親NodeのchildNodesにカラの領域を残してしまうことになり、childNodes.lengthの値がおかしくなってしまいます。一度addChildされたNodeは、きちんとremoveChildしてから再度addChildしなおしましょう。
私もzindexを操作する裏技を紹介したことがありますが、v0.6から操作できなくなりました。v0.6以降を使う人は注意しましょう。