« 球が動きます | トップページ | FlatTable アニメーションの流れ »

2012年7月14日 (土)

衝突のスキャン

「アニメーション機能の実装、その前に」で球の速度の式が求まったので、下図を参考にして、速度を求めるコードを見て行きましょう。



図中、手球の速度を求めるためには、1番の速度が必要になります。そして、1番の速度を求めるには2番の速度が必要になります。これは、球の衝突をスキャンすることになります。その最初の部分が次のコードです。

    // 衝突のスキャンの入り口
    var trig = animPage.childNodes[(nBall - 1 - 0)*2 + 3];    // (1)
    var mask = 1 << ballNum(trig);
    var propose = ballList & ~mask;
    var clusterMem = clusterCheck(trig, propose) | mask;
    propose &= ~clusterMem;    // (2)
    for (var i = 0; i < nBall; i++){
        if (clusterMem & (1 << i)){
            var ball = animPage.childNodes[(nBall - 1 - i)*2 + 3];
            var nextBall = knotAry[0][i].next;
            if (nextBall){
                scanCollision(knotAry[0][i], propose);    // (3)
                ball.speed = nextBall.fJump ?
                    knotAry[0][i].speed*coRestit_B : knotAry[0][i].speed;
                if (nextBall.fCurve){
                    setCurve(ball, nextBall);
                } else {
                    ball.angle = Math.atan2(nextBall.y - ball.y, nextBall.x - ball.x);
                }
                runList.push(ball);
            }
        }
    }
animPageはアニメーション用のページです。childNodes[(nBall - 1 - 0)*2 + 3] は手球を表しています。(1) は、その手球がアニメーションの起点となる球であることを意味しています。propose は何か処理してほしい球のリストを表しています。(2)では、初期配置で手球に接触している球が propose から除外されています(未使用の球は除く)。i は球の番号です。 scanCollision() は衝突をスキャンしながら球の速度を求める関数です。これを実行すると、第1引数のプロパティ speed に速度が代入されて帰って来ます。 knotAry[0][i] はアニメーションで使用する球を表しています。(3) は、 knotAry[0][i] を起点として propose を対象に衝突のスキャンを実行しています。上図の場合、
    scanCollision(knotAry[0][0], propose);
が実行されます。この時点で knotAry[0][0] は手球です。

次に、scanCollision() の動作を見て行きます。


function scanCollision(trig, propose){
    var speed = 0;
    var ent = trig.next;
    if (ent){
        var length = dist(ent, trig);
        ・・・
        propose &= ~clusterMem;
/*(4)*/ if (clusterMem){
            var target;
            for (var i = 0; i < nBall; i++){
                if (clusterMem & (1 << i)){
                    target = knotAry[0][i];
/*(5)*/             if (scanCollision(target, propose)){
                        sin, cos を計算してから・・・
                        totalSpeedV += target.speed*sin;
                        totalSpeedH += target.speed*cos;
                    }
                }
            }
            var totalSpeed = Math.sqrt(totalSpeedH*totalSpeedH + totalSpeedV*totalSpeedV);
            if (totalSpeedH){
                tan = totalSpeedV/totalSpeedH;
/*(6)*/         ent.speed = totalSpeed*Math.sqrt(1 + tan*tan)/coRestit_B;
            } else {
                ・・・
            }
/*(7)*/ } else {
            if ("0" != ent.decel){
/*(8)*/         scanCollision(ent, propose);
                if (fCushion(ent))
                    ent.speed /= coRestit_C;
                } else {
                   ent.speed = 0;
                }
            }
            ・・・
/*(9)*/     speed = ent.fCurve ? curveToSpeed(ent) : lenToSpeed(ent, length);
        }
    }
    return trig.speed = speed;    // (10)
}

trig, ent, target は、上図に示した関係になっています。起点となる trig が入って来て、次の節点が ent となり、それの衝突している球が target です。

scanCollision(trig, propose) では trig の進んだ先で他の球に衝突する (4) と、しない (7) に分けて処理を進めます。

(5) は、衝突された球 target を新たな起点として scanCollision(target, propose) を実行し、 target の速度を求めています(速度は target.speed に入って戻って来ます)。衝突された球 target の速度が求まると、「アニメーション機能の実装、その前に」の式(2) を用いて衝突した球 ent の速度が求まります。それが (6) です。

(8) は衝突しなかった場合の処理で、主にクッションでの反射に対応しています。

ent の速度が求まれば、「アニメーション機能の実装、その前に」の式(1) を用いて trig の速度が求まります。それが (9) および (11) です。

// 経路長から速度を得る
function lenToSpeed(ball, length){
    var eAccel = ball.decel ? accel*ball.decel : accel;
    return Math.sqrt(ball.speed*ball.speed + 2*eAccel*length);    // (11)
}

scanCollision() 内で求まった速度は、 (10) で trig.speed に代入して返します。素直に「 return speed; 」にしなかった理由は忘れました。 scanCollision() の戻り値を受け取れない個所が有ったのかも知れません。

--------
ここまでの動作およびコードは、本ブログのサイドバー「Link」の「SVG+JavaScript 版 FlatTable の試作品」で確認できます。

« 球が動きます | トップページ | FlatTable アニメーションの流れ »

ビリヤードの配置図ソフト」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/584699/55192181

この記事へのトラックバック一覧です: 衝突のスキャン:

« 球が動きます | トップページ | FlatTable アニメーションの流れ »