サンプルプログラム

具体的なアルゴリズムの書き方がわかりにくい方は以下にサンプルコードを2つ用意しましたのでご参考ください。

 

SampleA.js

function DecisionCommand ()
{
    // 遠距離射撃目標設定
    arrow_x = enemy_x;
    arrow_z = enemy_z;
    
    // 近距離砲射撃角調整
    shot_F_angle = 0;
    shot_M_angle = 90;
    shot_B_angle = 180;
    
    // 移動アルゴリズム
    effect = 0; // 特殊効果フラグ
    anchorage = false; // 停泊フラグ
    
    if(hitpoint<=50){ // ヒットポイントが少ない場合退避する
        go_x = -0.5*enemy_x + 1.5*now_x ;
        go_z = -0.5*enemy_z + 1.5*now_z ;
    }else{ // 島に接近する
        go_x = 0;
        go_z = 0;
        anchorage = true; // 停泊可能になったら停泊する
    }
    
    //最後のここは変更禁止
    DecisionSend ();

}

 

anchorage = true; になっていても停泊条件(原点(0,0)から距離5以内)を満足していない場合停泊しません。

ですが、常に anchorage = true; としていると島に停泊した後、島から離れることができなくなります。

基本的には anchorage = false; を指定し、本当に必要な時だけ true を指定することをおすすめします。

 

SampleB.js

function DecisionCommand ()
{
    // 遠距離射撃目標設定
    arrow_x = enemy_x;
    arrow_z = enemy_z;
    
    // 近距離砲射撃角調整
    var v_f : Vector3 = (new Vector3(now_dir_x,0,now_dir_z)).normalized;
    var v_e : Vector3 = (new Vector3(enemy_x-now_x,0,enemy_z-now_z)).normalized;
    var v_n : Vector3 = (new Vector3(0,1,0));
    shot_F_angle = Mathf.Atan2(Vector3.Dot(v_n,Vector3.Cross(v_f,v_e)),Vector3.Dot(v_f,v_e))*Mathf.Rad2Deg;
    shot_M_angle = Mathf.Atan2(Vector3.Dot(v_n,Vector3.Cross(v_f,v_e)),Vector3.Dot(v_f,v_e))*Mathf.Rad2Deg;
    shot_B_angle = Mathf.Atan2(Vector3.Dot(v_n,Vector3.Cross(v_f,v_e)),Vector3.Dot(v_f,v_e))*Mathf.Rad2Deg;
    
    // 極座標系変換
    now_r = Mathf.Sqrt(now_x*now_x + now_z*now_z);
    now_theta = Mathf.Atan2(now_z,now_x);
        
    // 移動アルゴリズム
    effect = 0; // 特殊効果フラグ
    anchorage = false; // 停泊フラグ
    
    if(hitpoint<=50){ // ヒットポイントが少ない場合退避する
        effect = 1; // 移動速度2xで回復しながら逃げる
        go_x = -0.5*enemy_x + 1.5*now_x ;
        go_z = -0.5*enemy_z + 1.5*now_z ;
    }else{ // 旋回しながら少しずつ島に接近する
        go_r = now_r - 5;
        go_theta = now_theta + 0.5;
        go_x = go_r * Mathf.Cos(go_theta);
        go_z = go_r * Mathf.Sin(go_theta);
        anchorage = true; // 停泊可能になったら停泊する
    }
        
    if((new Vector2(enemy_x,enemy_z)).magnitude<=5.0){ // 敵機停泊圏内の場合敵機中心に旋回攻撃
        slide_theta = Mathf.Atan2(now_z-enemy_z,now_x-enemy_x);
        tgt_s_theta = slide_theta - 0.5;
        tgt_s_r = 18;
        go_x = tgt_s_r * Mathf.Cos(tgt_s_theta) + enemy_x;
        go_z = tgt_s_r * Mathf.Sin(tgt_s_theta) + enemy_z;
        anchorage = false;
    }
    
    // 最優先アルゴリズム
    // - ボーダー処理
    var move_island_dist : float = (new Vector2(go_x,go_z)).magnitude; // 移動目標点の中心からの距離
    if(move_island_dist>(1.0*(180 - now_time)/120)*(50 - 10) + 15){
        go_x = 0;
        go_z = 0;
    }
    
    //最後のここは変更禁止
    DecisionSend ();

}

フィールドが円形である都合上、極座標を経由して移動目標を計算すると便利である場合が多くあります。

また、座標原点をスライドさせて極座標を考えることで敵機を中心に旋回移動なども可能になります。