Redpoll's 60
 Home / 3Dプログラミング入門 / 第2章 $§$2-30
第2章 2D空間におけるオブジェクトの運動
$§$2-1 オブジェクトの初期状態$§$2-17 衝突判定 5
$§$2-2 行列による変換の詳細 1$§$2-18 初期状態における頂点情報の取得について
$§$2-3 行列による変換の詳細 2$§$2-19 衝突判定 6 (軸平行な長方形同士の衝突)
$§$2-4 自転と公転$§$2-20 衝突判定 7 (円盤 vs 長方形)
$§$2-5 一体化したオブジェクトの運動 1$§$2-21 衝突判定 8 (回転した長方形同士の衝突)
$§$2-6 一体化したオブジェクトの運動 2$§$2-22 衝突判定 9 (「倉庫番」プログラムの作成)
$§$2-7 一体化したオブジェクトの運動 3$§$2-23 衝突判定 10 (円盤 vs 三角形)
$§$2-8 指定方向へのオブジェクトの移動 1$§$2-24 衝突判定 11 (直線 vs 長方形、円盤、直線)
$§$2-9 指定方向へのオブジェクトの移動 2$§$2-25 円と直線による補間曲線 1
$§$2-10 指定方向へのオブジェクトの移動 3$§$2-26 円と直線による補間曲線 2
$§$2-11 指定方向へのオブジェクトの移動 4 (連射プログラムの実装)$§$2-27 その他の重要事項 1 (UnityのTransformクラスによる記述 ; カメラ移動の基本)
$§$2-12 指定方向へのオブジェクトの移動 5$§$2-28 その他の重要事項 2 (画面に表示されるXY平面の範囲 ; ミニマップの実装)
$§$2-13 衝突判定 1 (点 vs 円盤、長方形 ; ローカル座標からワールド座標への変換 2D)$§$2-29 その他の重要事項 3 (スクリーン座標からワールド座標への変換 2D; スクリーンショットの撮影範囲)
$§$2-14 衝突判定 2$§$2-30 課題 1
$§$2-15 衝突判定 3$§$2-31 課題 2
$§$2-16 衝突判定 4

$§$2-30 課題 1


本節は読者用の課題である。
本節の課題はオブジェクトから弾を発射するプログラムの作成である。



オブジェクトから弾を発射するプログラムについては本章の2-11節から2-17節にかけて扱ったが、そこで使われた弾は図1に示される Shell というオブジェクトであり、Shellの形状は円盤(実際には正8角形)なのでShellをどの方向に発射してもShellの向きを変える必要はなかった (図2 ; Shellはその移動中 位置だけが変化し、向きは初期状態から変わらない)。

図1 Shell 初期状態 (正8角形)
図2 Shellの発射 (どの方向に発射しても向きは初期状態のまま)

しかし、今回使用するShellは下図3に示される縦に細長い形状のもので、このShellには向きがあり初期状態においては y軸プラス方向を向いている。今回のShellには向きがあるので上記の円盤型のShellと異なり、発射する際には適切な向きに回転した状態で発射しなければならない。
例えば下図4に示されるオブジェクト Plane からこのShellを発射するとしよう。図4はPlaneの初期状態であり、初期状態ではPlaneは y軸プラス方向を向いており、初期状態においてはPlaneとShellの向きは同じである。

図3 Shell 初期状態
図4 Plane 初期状態

下図5はPlaneに何も回転を行っていない状態でこの細長いShellを発射しているときの様子である。Planeには回転が行われていないのでその向きは y軸プラス方向であり、Shellの発射方向も同じく y軸プラス方向である。図5のShellにも回転は行われておらず、毎フレーム y軸プラス方向に進んでいるだけである。図に示されるように、この場合にはShellに何も回転を行わなくても特に不自然ではない。
図6はPlaneに $-45^\circ$ の回転を行った状態でShellを発射しているときの様子であるが、ここで発射されるShellに対しても何も回転は行われていないのでShellの向きは初期状態の向きである y軸プラス方向のまま飛んでいくことになる。図に示されるように、この場合においては明らかにShellの向きは不自然である。

図5 回転の行われていないPlaneからShellを発射
図6  -45°の回転の行われたPlaneからShellを発射

Planeが $-45^\circ$ 回転した状態でShellを発射する際には、(y軸から) $-45^\circ$ の方向にShellが進んでいくことになるが(図7)、その場合にはShellも $-45^\circ$ 回転した状態で進んで行かなければならない (図8、図9)。

  • 図7
  • 図8
  • 図9

同様にPlaneが $60^\circ$ 回転した状態でShellを発射する際には、(y軸から) $60^\circ$ の方向にShellが進んでいくことになるが(図10)、その場合にはShellも $60^\circ$ 回転した状態で進んで行かなければならない (図11、図12)。

  • 図10
  • 図11
  • 図12





# Code1
ここでの課題は上図3の細長い形のShellをオブジェクトから連射するプログラムの作成である。
プログラムで使用するオブジェクトは下図13の Jet である。Jetは初期状態では上記のPlaneと同じく y軸プラス方向を向いている。今までの連射プログラムと今回のプログラムの主な違いは上で述べたShellの形状の他にもう1つあり、それは今回使用するJetにはShellの発射口が2箇所あることである。

図13 Jet 初期状態
図14 発射口が2つある

図14は初期状態におけるJetの発射開始位置と発射方向であるが、発射口が2箇所あるため図に示されるように発射開始位置が2つになっている (初期状態における発射方向はいずれも y軸プラス方向)。
したがって今回はJetからShellを発射する際にはこの2箇所の発射口から同時に2つのShellが発射されるようにしなければならない。具体的には以下のような実行結果になればよい。

図15


そして今回の課題では使用するインスタンス変数や定数については読者の側で用意するものとする
2-11節~2-17節で使用したオブジェクトは THAlphaObject2D クラスのオブジェクトであり、Shellは THShell2D クラスのオブジェクトであったが、これらのクラスにはあらかじめ連射に必要なプロパティ(lastShootFrameshootIntervalinitShootPosition など)が用意されていた。
しかしここで使用する Jet は CustomJet、Shell は CustomShell というクラスのオブジェクトであり、これらのクラスは以下に示されるようにコンストラクタ以外は何もない空のクラスである。


public class CustomJet : THObject2D
{
    public CustomJet(GameObject go) : base(go) { }

}



public class CustomShell : THObject2D
{
    public CustomShell(GameObject go) : base(go) { }

}


したがって、今回の連射プログラムに必要なプロパティはこれらのクラスに追加しなければならない (もちろん CustomJetCustomShell の2つのクラスに何も追加しないで、独自にインスタンス変数などを用意する形でも構わない)。

(CustomJetCustomShell はいずれも THObject2D クラスを継承しているので今までのプログラムで使用した SetMatrix(..)GetMatrix()SetPosition()GetPosition() などのメソッドは使うことができる。)

また Jetを動かす際には次のキー操作によるものとする (2-14節、2-17節のものと同じである)。
H  :  Jetの向きを反時計周りに回転
L  :  Jetの向きを時計周りに回転
S  :  Jetの移動/停止用スイッチ
A  :  Shellの連射


プログラムは Code1 に作成するものとする。Code1は始めの段階では初期化ブロックのみが記述されている。
[Code1]
if (!i_INITIALIZED)
{
    
    i_INITIALIZED = true;
}



ここで用意されている CustomJet クラスや CustomShell クラスは上記のように空のクラスであるが、プログラム中で使用するオブジェクト Jet や Shell はもちろん null ではない。例えば初期化ブロックで以下のように記述すると、
if (!i_INITIALIZED)
{
    Jet.SetMatrix(THMatrix3x3.identity);    

    for(int i=0; i<Shell.Length; i++)
    {
        Shell[i].SetMatrix(THMatrix3x3.identity);    
    }                             
    
    i_INITIALIZED = true;
}


JetとすべてのShellが原点に置かれた状態になる (プログラム中のShellは要素数 $60$ の配列である)。


(解答例については Sec230_Ans.txt  Code1 を参照)


















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