XNA 3.0 Game Programming Recipes翻译2-3

2-3.创建一个第一人称射击相机:振动式相机

问题

        你想创建一个像许多第一人称射击游戏里的相机。你想用鼠标旋转,用键盘移动。

方案

2-2介绍的方法开始,每当检测到用户输入就更新相机的位置或旋转。您的相机旋转矩阵的改变将依照鼠标的移动。按上或下方向键,相机将前进或后退,按左或右方向键,相机将左右平移。

如何运作

通常,第一人称游戏,玩家可以自由地四处看。这些运动相对应的分别旋转上和右向量,甚至更详细的绕(0,1,0)和(1,0,0)向量旋转。

围绕着前向量旋转,但是这是不允许的。这会导致玩家弯曲他的脖子到左边或右边,也没有采用第一人称,除了当玩家被枪杀并躺在地上。

继续之前,最好能读一下4-2'矩阵乘法规则',那会对你有帮助。你最少要知道是相乘的顺序很重要,因为当你组合两次旋转,第二次旋转的轴被第一次的旋转改变了。

第一次旋转对第二次旋转的影响称为‘Gimbal lock;它有时可能是真正的痛苦,但它有时也能如你所愿。在第一人称中,你是幸运的:你将先绕向上的轴旋转,再绕向右的轴旋转。先绕着你的向上向量旋转很好,你可以想像站起来伸展你的右手。如果你向右转,你的手臂和你一起转,现在,你可以很好地绕着您的手臂的方向上下看。

总之,你要存储两个变量:顺着右和顺着上方向旋转的量。接下来,你要计算总的旋转,绕向上的轴旋转,再绕向右的轴旋转。这样就算出总旋转。

现在你知道的第一人称视点轮换背后的概念,你仍然需要持有用户输入的旋转量的两个变量。这里给出鼠标输入的例子。你要决定两次鼠标更新之间值的改变。所以代码如下:

 

float leftrightRot;

float updownRot;

Vector3 cameraPosition;

Matrix viewMatrix;

MouseState originalMouseState;

 

        MouseState包含鼠标指针的位置,说明自上次调用Mouse.GetState方法鼠标按键是否按下。在Initialize方法给每个变量起始值:

 

        leftrightRot = 0.0f;

        updownRot = 0.0f;

        cameraPosition = new Vector3(1,1,10);

        UpdateViewMatrix();

        Mouse.SetPosition(Window.ClientBounds.Width/2, Window.ClientBounds.Height/2,);

        originalMouseState = Mouse.GetState();

       

        你先把旋转值设为0并给相机选个初始位置。你会很快创建UpdateViewMatrix方法,用来简单初始化viewMatrix变量。

    接下来,你设置鼠标指针到屏幕中心。最后一行储存MouseState,它包含鼠标的位置,在更新周期之间,你可以检查两个状态之间的变化,就知道鼠标是否被移动。

    让我们查看更新历程。如果状态有变化,旋转值就更新,鼠标回到窗口中心:

    float rotationSpeed = 0.005f;

    MouseState currentMouseState = Mouse.GetState();

    if(currentMouseState != originalMouseState)

    {

        float  xDifference = currentMouseState.X – originalMouseState.X;

        float  yDifference = currentMouseState.Y – originalMouseState.Y;

        leftrightRot -= rotationSpeed * xDifference;

        updownRot -= rotationSpeed * yDifference;

        Mouse.SetPosition(Window.ClientBounds.Width/2, Window.ClientBounds.Height/2);

    }

    UpdateViewMatrix();

   

    rotationSpeed变量定义相机旋转的速度。你用鼠标两次状态之间的不同来旋转相机的右和上向量。最后一行重置鼠标到窗口中心。

 

注意 另一种做法可能是您存储currentMouseStateoriginalMouseState来比较下次更新的新currentMouseState。但是,如果鼠标移到窗口边缘就无效了。例如,鼠标指针已经碰到窗口右边界,用户再向右移动,鼠标的X位置不会变化。所以每次把鼠标重置到窗口中心。

 

最后,调用UpdateViewMatrix方法,更新旋转值。你可以前面章节找到详细的解释。基于矩阵存储相机的旋转和位置,这方法计算目标和上向量,需要创建视图矩阵。

 

Matrix cameraRotation = Matrix.CreateRotationX(updownRot) * Matrix.CreateRotationY(leftrightRot);

 

            Vector3 cameraOriginalTarget = new Vector3(0, 0, -1);

            Vector3 cameraOriginalUpVector = new Vector3(0, 1, 0);

 

            Vector3 cameraRotatedTarget = Vector3.Transform(cameraOriginalTarget, cameraRotation);

            Vector3 cameraFinalTarget = cameraPosition + cameraRotatedTarget;

 

            Vector3 cameraRotatedUpVector = Vector3.Transform(cameraOriginalUpVector, cameraRotation);

            Vector3 cameraFinalUpVector = cameraPosition + cameraRotatedUpVector;

 

   viewMatrix = Matrix.CreateLookAt(cameraPosition, cameraFinalTarget, cameraRotatedUpVector);

 

右向量是(1,0,0),所以是沿着X轴的。这是用CreateRotationX方法的原因。上向量是(0,1,0) 所以是沿着Y轴的。这是用CreateRotationY方法的原因。M1*M2,表示先M2M1,就是先左右,后上下。

当你移动鼠标指针这将让你的相机旋转。之后,当你按上方向键,相机前进。更新期间,先检查按键来决定相机位置:

 

KeyboardState keyState = Keyboard.GetState();

            if (keyState.IsKeyDown(Keys.Up))

                AddToCameraPosition(new Vector3(0, 0, -1));

            if (keyState.IsKeyDown(Keys.Down))

                AddToCameraPosition(new Vector3(0, 0, 1));

            if (keyState.IsKeyDown(Keys.Right))

                AddToCameraPosition(new Vector3(1, 0, 0));

            if (keyState.IsKeyDown(Keys.Left))

                AddToCameraPosition(new Vector3(-1, 0, 0));

 

QuakeCamera

这在第一人称类型的游戏中很常用的类,我把他从本章分离出来,他在本书的很多例子中用到,你也能很容易的把他添加到自己的项目中。

 

 

 

 

转载于:https://www.cnblogs.com/XNAconglele/archive/2009/08/25/1553290.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值