使用 XNA 创建简单的 3D 游戏/添加 NPC
外观
创建其他鱼最简单的方法是复制模型文件并修改其本地纹理。在我的例子中,我在“Content”/“Models”文件夹中创建了一个名为“OtherFish”的新文件夹,并修改了纹理,使所有纹理都变成橙色而不是蓝色。确保新的纹理文件与之前的纹理文件同名,并且“内容处理器”设置为“SkinnedModelProcessor”,它将正常工作。
接下来,在你的其他类变量旁边创建一个新的用户制作的“ModelRenderer”类型数组,名为 OtherFishes。
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”更新方法调用一起放置;
for (int i = 0; i < OtherFishes.Length; i++)
{
OtherFishes[i].Update(gameTime);
}
以及它调用绘制时。
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");
}
并在你的初始化例程中调用它,如下所示。
//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 条初始化的鱼游过可控鱼,除此之外没有别的。
为了确保鱼无限地游动,请将以下更改添加到“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");
为了检查玩家和敌人之间的碰撞,创建以下两个新方法。
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");
现在玩它,你应该看到鱼在你触碰它们时发生变化。