XNA 4.0 3D 游戏开发之世界漫游
通过自己做的一个例子程序,终于明白了游戏中的3D世界坐标是怎么回事。
1、做3D 游戏首先要做模型,用blender做模型时,最后导出的fbx文件,就是一堆坐标数据, 也就是说在blender里制作模型所处的位置,就是xna 游戏场景中的初始位置。
例如做个小人, 在blender制作中的初始位置是{0,0,0} ,那么在游戏中出现的默认位置也是{0,0,0}, 要想在游戏中改动位置, 通过对模型进行平移,旋转操作就好。
例如我在blender 里做了一个带贴图的大楼,要在游戏中显示,那么做平移操作就可以了。由于blender的坐标系是Z轴向上,而xna的坐标系是z轴指向屏幕外,所以显示模型时需要先做翻转操作,然后再平移。
private void DrawBuilding()
{
foreach( Vector3 positonBulid in buildingList)
{
DrawModel(building, Matrix.CreateRotationX(-(float)Math.PI / 2.0f) * Matrix.CreateTranslation(positonBulid));
}
}

2. 模型的位置明白以后,就是确定摄像机的位置。建立摄像机位置有两个参数, 相机机身位置,和相机镜头位置。相机位置决定了游戏画面中的场景和小人是拉近还是拉远,而镜头的位置,决定了是仰望还是俯视。
摄像机有两种状态,运动状态和静止状态。 在运动状态中,场景和小人一起动。 在静止状态中,场景动,小人不动。如果让摄像机跟着小人同步运动,就是3D空间内的漫游。
camera.Target = avatarPosition + Vector3.TransformNormal(cameraOffset, avatarRotation);
camera.Position = camera.Target + Vector3.TransformNormal(new Vector3(0, 0, 1), avatarRotation); camera.viewMarix = Matrix.CreateLookAt(Position, Target, Vector3.Up);
显示模型时,把ViewMatrix填上就可以了
Matrix[] bones = animationPlayer.GetSkinTransforms();
// Render the skinned mesh.
foreach (ModelMesh mesh in currentModel.Meshes)
{
foreach (SkinnedEffect effect in mesh.Effects)
{
effect.SetBoneTransforms(bones);
effect.View = camera.ViewMatrix;
effect.Projection = camera.ProjectionMatrix;
effect.EnableDefaultLighting();
effect.SpecularColor = new Vector3(0.25f);
effect.SpecularPower = 16;
}
mesh.Draw();
}
昨天碰到一个问题,就是小人走路时转身正常,但前进的方向不正常。 经过调试,发现前进的方向计算错了。新的前进方向要始终用原始参数做旋转操作就好了。
做一个游戏的乐趣,比玩一个游戏的乐趣更大。
下面代码是用键盘控制小人的前进和旋转。
/// <summary> /// Press left or right key make avatar turn around /// </summary> /// <param name="gameTime"></param> /// <param name="keystate"></param> private void UpdateAvatar(GameTime gameTime, KeyboardState keystate) { // Press key up,left, down, right ,av change to walk state if (keystate.IsKeyDown(Keys.Up)) { if(animationPlayer.CurrentClip != clipofWalk) animationPlayer.StartClip(clipofWalk); avatarDirection.Normalize(); avatarPosition += avatarDirection* camera.KeySensi; } if (keystate.IsKeyUp(Keys.Up) && animationPlayer.CurrentClip != clipofHand) { animationPlayer.StartClip(clipofHand); } if (keystate.IsKeyDown(Keys.Left)) { avatarLeftRightRot += camera.MouseSensi*10; if (avatarLeftRightRot > Math.PI * 2) avatarLeftRightRot = avatarLeftRightRot - (float) Math.PI * 2; } if (keystate.IsKeyDown(Keys.Right)) { avatarLeftRightRot -= camera.MouseSensi*10; if (avatarLeftRightRot < -Math.PI * 2) avatarLeftRightRot = avatarLeftRightRot + (float)Math.PI * 2; } avatarRotation = Matrix.CreateRotationY(avatarLeftRightRot); avatarDirection = Vector3.TransformNormal(new Vector3(0,0,-1), avatarRotation); avatarDirection.Normalize(); // Update animation matrix animationPlayer.Update(gameTime.ElapsedGameTime, true, Matrix.Identity*Matrix.CreateRotationY(avatarLeftRightRot)*Matrix.CreateTranslation(avatarPosition)); }
现在已经实现小人在3D世界漫游了。
下一步 需要加上碰撞检测,地形匹配,粒子效果,鼠标点选, 3D 游戏涉及的东西真多,好在都已经成熟了。
浙公网安备 33010602011771号