Redpoll's 60
 Home / 3Dプログラミング入門 / 第4章 $§$4-24
第4章 3D空間におけるオブジェクトの運動

$§$4-24 衝突判定 3


本節は4-22節及び4-23節を統合したものである。しかしその内容は2-17節のものとほとんど同じである。2-17節ではオブジェクト同士によるShellの撃ち合いを実装したが、ここではShellの撃ち合いの他にオブジェクト同士の衝突処理を追加しただけである。




# Code1
最初のオブジェクトは図1の Disk であり、名前通りの形状である。まずはこのDiskとの撃ち合いを実装する。

図1 Disk 初期状態
図2 Code1 実行結果

実行中のキー操作は次のとおり。
    S  :  前へ進む (Shiftと同時押しの場合は後ろへ進む)
    H  :  Tankを反時計周り(左回り)に回転
    L  :  Tankを時計周り(右周り)に回転
    A  :  Shellの連射

プログラムを以下に示す。
[Code]  (実行結果 図2)
if (!i_INITIALIZED)
{
    Tank.lastShootFrame = 0;
    Tank.shootInterval = 30;
    Tank.initShootDirection = Vector3.forward;
    Tank.initShootPosition = new Vector3(0.0f, 1.5f, 1.0f);
    Tank.shellSpeed = 0.35f;

    for (int i = 0; i < Disk.Length; i++)
    {
        Disk[i].lastShootFrame = 0;
        Disk[i].shootInterval = 24;
        Disk[i].initShootDirection = Vector3.forward;
        Disk[i].initShootPosition = new Vector3(0.0f, 0.0f, 3.0f);
        Disk[i].shellSpeed = 0.15f;
    }

    i_targetObjects = Disk;
    i_shootObjects = Disk;

    i_frameCount = 0;

    i_INITIALIZED = true;
}

i_frameCount++;

UserMotion();
UShellMotion();

EnemyMotion();
EShellMotion();

CollisionTest_ShellPhase(UShell, i_targetObjects);
CollisionTest_ShellPhase(EShell, new THAlphaObject3D[] { Tank });

CollisionTest_ObjectPhase(i_targetObjects);


プログラムの構成は2-17節のものと同じである。初期化ブロックは連射用のプロパティの設定であり、Tankと2つのDisk(ここではDiskは2つ配置されている)に対して適当な値が設定されている。
THAlphaObject3D[]型インスタンス変数の i_targetObjects (19行目)にはTankの衝突相手となるオブジェクトをすべてセットし、同じく THAlphaObject3D[]型インスタンス変数の i_shootObjects (20行目)にはShellを撃ってくる相手オブジェクトをすべてセットする (ここでは2つのDiskが撃ってくるので配列Diskをセットしている)。

28行目以降の UserMotion()UShellMotion()CollisionTest_ShellPhase(..)CollisionTest_ObjectPhase(..) は 4-22節、4-23節で解説したものである。EShellMotion() はこのプログラムに関しては UShellMotion() と内容は変わらない。EnemyMotion() は相手側のオブジェクトの運動が記述されており、今回であれば実行結果(図2)に示されるように同じ位置で往復回転をしているだけである。



# Code2
次に使用するオブジェクトは下図3の SnPart であるが、ここではこの SnPart を図4に示されるように24個連結したものを敵オブジェクトとしている。SnPartの形状は円柱を横に寝かせたものであり、この形状は今までに何度か使われたが衝突モデルは長方形である。

図3 SnPart 初期状態
図4 敵オブジェクトはSnPartを24個連結して構成される

キー操作はCode1と同じであるが、カメラ操作に関してのキーが追加されている。
    V  :  敵オブジェクトが画面内に表示されるようにカメラを移動

    S  :  前へ進む (Shiftと同時押しの場合は後ろへ進む)
    H  :  Tankを反時計周り(左回り)に回転
    L  :  Tankを時計周り(右周り)に回転
    A  :  Shellの連射

今回はカメラが追跡型になっている。そのため状況によっては画面内に敵オブジェクトが表示されない状態が生じるが、その際には V キーを押すことで敵オブジェクトが画面の中心に来るようにカメラが移動する。

プログラムを以下に示す。
[Code2]  (実行結果 図5)
if (!i_INITIALIZED)
{
    Tank.lastShootFrame = 0;
    Tank.shootInterval = 30;
    Tank.initShootDirection = Vector3.forward;
    Tank.initShootPosition = new Vector3(0.0f, 1.5f, 1.0f);
    Tank.shellSpeed = 0.35f;

    SnArray[0].lastShootFrame = 0;
    SnArray[0].shootInterval = 120;
    SnArray[0].initShootDirection = Vector3.forward;
    SnArray[0].initShootPosition = new Vector3(0.0f, 0.0f, 1.0f);
    SnArray[0].shellSpeed = 0.4f;

    i_targetObjects = SnArray;
    i_shootObjects = new THAlphaObject3D[] { SnArray[0] };

    i_frameCount = 0;

    i_INITIALIZED = true;
}


i_frameCount++;

UserMotion();
UShellMotion();

EnemyMotion();
EShellMotion();

CollisionTest_ShellPhase(UShell, i_targetObjects);
CollisionTest_ShellPhase(EShell, new THAlphaObject3D[] { Tank });

CollisionTest_ObjectPhase(i_targetObjects);


今回の敵オブジェクトは上記のSnPartを24個連結したものであるが、24個のSnPartはプログラム中では SnArray という配列として使われている。Shellを発射するのは一番先頭の SnArray[0] のみであるため、初期化ブロックでは SnArray[0] に対して連射用のプロパティ設定が記述されている。
しかしこの敵オブジェクト全体としては、TankやTankが発射するShellの衝突対象であるため i_targetObjects には敵オブジェクト全体を表す SnArray がセットされている。

図5 Code2 実行結果

実行結果に見られるようにこの敵オブジェクトは蛇のような運動を繰り返し、一定の間隔でShellを発射するが、発射されるShellは追跡型であるため常にTankに向かって飛んでくる。また敵オブジェクトのどの部分に当たっても衝突とみなされるので、衝突後のTankにはリバウンド処理が行われる。


















© 2020-2024 Redpoll's 60 (All rights reserved)