前回の第37回「インスタンスの回転と重ね順」は,ふたつの面を前後に置いて,y軸で水平に回した。今回はさらに2面増やし,矩形の画像で四方を囲んで,最後は上下左右に回してみたい(図1)。前回に続き,面の重ね順をどう決めるかが課題だ。
z座標値を調べる仕組みづくり
4面を水平に回すだけなら,前回のスクリプト2と同じように,面が納められた容れ物のSpiteインスタンスの回転角で並べ替えることもできる。しかし,垂直にも回すとなると,ことはそう単純ではない。そこで,4つの面それぞれのz座標で重ね順を決めることにしよう。前回のスクリプト2に手を加えていくことにする。
まず,面のどの位置の座標を調べるかが問題となる。[ライブラリ]のビットマップ(BitmapDataインスタンス)は,Bitmapオブジェクトの基準点が左上角になるように配置された(第37回図2再掲の位置座標参照)。しかし,左上角のz座標値を比べたのでは,それぞれの面の前後はわからない。
比べるなら,それぞれの面の中央の座標がよいだろう。容れ物のSpriteインスタンスの基準点は四方を囲む面の中心なので,各面とxまたはz軸との交点で決めるということだ(図2)。ところが,BitmapDataクラスには位置座標のプロパティがない。つまり,面の左上角がBitmapオブジェクトの基準点であることは動かせない。
そのため,4つの面のBitmapオブジェクトは,それぞれSpriteインスタンスで包むことにする。そして,入れ子のBitmapオブジェクトの位置をずらすことによって,親Spriteインスタンスの基準点を面の中心に定める(図3)。そうすれば,面のSpriteインスタンスのz座標でそれらの前後が決められる。これで面のz座標値を調べる仕組みが整った。
面をつくって返す関数の修正
つぎは,前回のスクリプト2に具体的な手を加えていく。第1に,面のBitmapオブジェクトをつくって返していた関数xCreateFace()だ。これを,Bitmapオブジェクトが入れ子になったSpriteインスタンスで返すよう修正する。引数の宣言はそのままだ。ただし,Spriteインスタンスの基準点が面の中央になるので,関数を呼出すときに渡す座標値がつぎのように変わる。なお,面のSpriteインスタンスを納める変数名も改めた。
// var frontBitmap:Bitmap = xCreateFace(Image0, -nUnit, -nUnit, -nUnit);
// var backBitmap:Bitmap = xCreateFace(Image1, nUnit, -nUnit, nUnit, 180);
var frontSprite:Sprite = xCreateFace(Image0, 0, 0, -nUnit);
var backSprite:Sprite = xCreateFace(Image1, 0, 0, nUnit, 180);
関数xCreateFace()には,以下のように手を加えた。戻り値のデータ型をSpriteで指定し,面のビットマップが納められたBitmapオブジェクトは,新たにつくるSpriteインスタンスで包む。Bitmapオブジェクトの位置は,面の中央にSpriteインスタンスの基準点がくるように,左上にずらす。そのうえで,引数値によりSpriteインスタンスの位置と回転角を定めた。
// function xCreateFace(myBitmapData:Class, nX:Number, nY:Number, nZ:Number, nRotationY:Number = 0):Bitmap {
function xCreateFace(myBitmapData:Class, nX:Number, nY:Number, nZ:Number, nRotationY:Number = 0):Sprite {
var myBitmap:Bitmap = new Bitmap(new myBitmapData(0, 0));
var faceSprite:Sprite = new Sprite();
faceSprite.addChild(myBitmap);
// myBitmap.x = nX;
// myBitmap.y = nY;
// myBitmap.z = nZ;
// myBitmap.rotationY = nRotationY;
myBitmap.x = -myBitmap.width / 2;
myBitmap.y = -myBitmap.height / 2;
faceSprite.x = nX;
faceSprite.y = nY;
faceSprite.z = nZ;
faceSprite.rotationY = nRotationY;
// return myBitmap;
return faceSprite;
}
これで,前回のスクリプト2とムービーの見た目は変わらないものの,ふたつの面のSpriteオブジェクトがつくられ,容れ物の親Spriteインスタンス内に 配置される。この段階で[ムービープレビュー]を確かめる場合は,スクリプト中の面のSpriteオブジェクトの変数名を直す必要がある。また,面の重ね順を整える関数xSetOrder()は,前項で述べたとおり処理を大幅に書替えるので,一旦本体をコメントアウトしておこう。
// mySprite.addChild(frontBitmap);
// mySprite.addChild(backBitmap);
mySprite.addChild(frontSprite);
mySprite.addChild(backSprite);
function xSetOrder():void {
/*
var nTop:uint = mySprite.numChildren - 1;
if (mySprite.rotationX > 90) {
mySprite.setChildIndex(backBitmap, nTop);
} else {
mySprite.setChildIndex(frontBitmap, nTop);
}
*/
}

