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 游戏涉及的东西真多,好在都已经成熟了。

  

posted @ 2014-01-09 09:43  银龙  阅读(419)  评论(0)    收藏  举报