XNAを使用したシンプルな3Dゲームの作成/NPCの追加

他の魚の作成 編集

他の魚を作成する最も簡単な方法は、モデルファイルをコピーして、ローカルテクスチャを変更することです。 私の場合、 'Content'/'Models' フォルダ内に 'OtherFish'という名前の新しいフォルダを作成し、テクスチャ全体が青の代わりにオレンジ色になるようにテクスチャを変更しました。 新しいテクスチャファイルが前のものと同じ名前であることを確認して、 'Content Processor' を 'SkinnedModelProcessor'に設定すれば、動作するはずです。

次は、他のクラス変数と並行して、OtherFishesという名前の usermadeの 'ModelRenderer' 型の新しい配列を作成します。

ModelRenderer[] OtherFishes = new ModelRenderer[16];

そして、他のものと並行してLoadContent()メソッド内に次の 'for' 文を配置することで、それらを初期化します。

//Initialises the NPC fish
currentModel = Content.Load<Model>("Models\\OtherFish\\FishModel");
for (int i = 0; i < OtherFishes.Length; i++)
{
    OtherFishes[i] = new ModelRenderer(currentModel);
    OtherFishes[i].Translation = new Vector3(0f);//Move it to the centre
}

私たちが作成したオリジナルの魚と同様の方法で、これらの魚それぞれの描画メソッドとアップデートメソッドを呼び出す必要があります。 次の文を配置して、これを 'FishMen' Update メソッドと並行して呼び出します。

for (int i = 0; i < OtherFishes.Length; i++)
{
    OtherFishes[i].Update(gameTime);
}

そしてこれと並んでいるのが、そのDraw呼び出しです。

for (int i = 0; i < OtherFishes.Length; i++)
{
    OtherFishes[i].ModelDraw(GraphicsDevice, cameraPosition, cameraTarget, farPlaneDistance);
}

これは、魚を表示する方位のルーチンを扱います。

魚を動かす 編集

以下のように 'ResetNPCFish' という新しいメソッドを作成します。

//Resets NPC fishes
void ResetNPCFish(int input)
{
    Random random = new Random();//Allows for the creation of random numbers
    Vector2 Boundarys = new Vector2(14f);//Defines the boundarys of where the fish start

    //Rotates the fish so they rotate towards the screen
    OtherFishes[input].Rotation.Y = (float)((Math.PI / 180.0) * 180);//Put simply, this will rotate it by 180 degrees
    OtherFishes[input].Rotation.Z = (float)((Math.PI / 180.0) * 180);
    //Moves the fish into a random position defined by the 'Boundarys' variable
    OtherFishes[input].Translation.X = random.Next((int)Boundarys.X * -1, (int)Boundarys.X);
    OtherFishes[input].Translation.Y = random.Next((int)Boundarys.Y * -1, (int)Boundarys.Y);
    //Moves the fish beyond the viewing horizon
    OtherFishes[input].Translation.Z = random.Next((int)farPlaneDistance + 100);

    OtherFishes[input].PlayAnimation("Frown");
}

そして以下のように、initialisaionルーチンの中でそれを呼び出します。

//Initialises the NPC fish
currentModel = Content.Load<Model>("Models\\OtherFish\\FishModel");
for (int i = 0; i < OtherFishes.Length; i++)
{
    OtherFishes[i] = new ModelRenderer(currentModel);
    OtherFishes[i].Translation = new Vector3(0f);//Move it to the centre
    OtherFishes[i].PlayAnimation("Swim");//Play the default swimming animation
    ResetNPCFish(i);
}

そのままゲームを実行すると、初期化された魚16匹ともう少しが、コントロール可能な魚を泳いで通り過ぎてゆくところが見えるはずです。

ファイル:XNA Orange Fish.gif

魚が無限に泳ぐことを保証するために、 'OtherFishes'のアップデートコードに次のような変更を加え、画面上の魚の位置をチェックするようにし、必要であれば、それを再スタートさせます。

for (int i = 0; i < OtherFishes.Length; i++)
{
    float speed = 0.02f;

    OtherFishes[i].Translation.Z -= speed * (float)gameTime.ElapsedGameTime.TotalMilliseconds;

    if (OtherFishes[i].Translation.Z < -10f)
        ResetNPCFish(i);

    OtherFishes[i].Update(gameTime);
}

今それを実行すると、無期限に実行されるはずです。

魚との衝突 編集

次に配置していくコードは、魚のしかめ面の表示をデフォルトにし、それがプレーヤーにぶつかったとき、魚しかめ面を逆さまに変更するものです。 'ResetNPCFish'メソッドの下部に次の行を追加します。

OtherFishes[input].PlayAnimation("Frown");

プレイヤーと敵との間の衝突をチェックするために、次の2つの新しいメソッドを作成します。

bool CheckCollision(Vector3 PlayerPosition, Vector3 NPCPosition)
{
    double DifferenceNeeded = 4;//Feel free to adjust, affects how close the NPC has to be before the expression changes

    double X = Difference(PlayerPosition.X, NPCPosition.X);
    X *= X;
    double Y = Difference(PlayerPosition.Y, NPCPosition.Y);
    Y *= Y;
    double Z = Difference(PlayerPosition.Z, NPCPosition.Z);
    Z *= Z;
    if (Math.Sqrt(X + Y + Z) < DifferenceNeeded)
        return true;

    return false;
}

float Difference(float int1, float int2)
{
    if (int1 > int2)
        return int1 - int2;
    else
        return int2 - int1;
}

そして他のアップデートコードのピースと一緒に次のものを。

if(CheckCollision(FishMen.Translation, OtherFishes[i].Translation))
    OtherFishes[i].PlayAnimation("Smile");

今プレイすると、触れたときの魚の変化が見えるはずです。