D3D游戏编程系列(七):自己动手编写rpg游戏之第三人称视角的构建

来源:互联网 发布:c 高级编程教程 编辑:程序博客网 时间:2024/05/09 11:14

        终于迎来了自己的最后一个游戏,RPG冒险游戏,这个应该也是当前在单机领域最火的游戏类型了吧,丰富的剧情配上动听的音乐,在加上华丽的画面和带劲的打斗,实在是一个让人心旷神怡的游戏啊,本文旨在塑造一个简单的rpg游戏,希望和大家一起分享这美妙的游戏编程世界。

       当前的大部分rpg游戏都是以第三人称视角作为基础的,这个和第一人称略有不同,在Camera的构建上也不尽相同,所以我带大家走进第三人称视角的世界。

class CDXThirdCamera{public:void Create(D3DXVECTOR3 vEye,D3DXVECTOR3 vAt);void RorateY(float fAngle);void RorateAxis(float fAngle);void Scale(float fParam);void GetTransform(D3DXMATRIX *Matrix);void Walk(float fWalk);void Left(float fLeft);D3DXVECTOR3 GetEye();D3DXVECTOR3 GetAt();void SetEyeHeight(float iY);void SetAtHeight(float iY);void SetEye(D3DXVECTOR3 Eye);void SetAt(D3DXVECTOR3 At);private:D3DXVECTOR3 m_vEye;D3DXVECTOR3 m_vAt;};

       第三人称视角需要满足哪些需求,视角的水平旋转,视角的垂直旋转和视角的缩放,于是便有了RotateY,RotateAxis和Scale三个函数,还要注意这里有两个成员变量:

D3DXVECTOR3 m_vEye;D3DXVECTOR3 m_vAt;
      m_vEye代表玩家视角,就是当前Camera所处的位置,而m_vAt便是需要观察的点,说白了就是游戏里玩家操控的人物所处的位置,这样,有了Eye和At便可以形成一个视图矩阵了。

      那么我们首先来看下RotateY是怎么实现的:

void CDXThirdCamera::RotateY( float fAngle ){D3DXMATRIX mat,matY,matTrans;D3DXMatrixTranslation(&mat,-m_vAt.x,-m_vAt.y,-m_vAt.z);D3DXMatrixRotationY(&matY,fAngle*D3DX_PI/180);D3DXMatrixTranslation(&matTrans,m_vAt.x,m_vAt.y,m_vAt.z);mat=mat*matY*matTrans;D3DXVec3TransformCoord(&m_vEye,&m_vEye,&mat);}

       大家可以看到,我这里没有自己计算,而是全部用了D3DX的函数来做的,首先将当前用户平移玩家视角所在的位置平移,以使玩家的观察点位于原点,然后让Y轴旋转一定角度,最后在平移回来,这样我们就可以产生玩家视角围绕当前人物(观察点)旋转的效果。好,我们再看一下RotateAxis函数是怎么实现的:

void CDXThirdCamera::RotateAxis( float fAngle ){D3DXVECTOR3 u=m_vEye-m_vAt;D3DXVECTOR3 v=D3DXVECTOR3(m_vAt.x,0,m_vAt.z)-m_vAt;D3DXVECTOR3 out;D3DXVec3Cross(&out,&u,&v);D3DXVec3Normalize(&out,&out);D3DXMATRIX mat,matAxis,matTrans;D3DXMatrixTranslation(&mat,-m_vAt.x,-m_vAt.y,-m_vAt.z);D3DXMatrixRotationAxis(&matAxis,&out,fAngle*D3DX_PI/180);D3DXMatrixTranslation(&matTrans,m_vAt.x,m_vAt.y,m_vAt.z);mat=mat*matAxis*matTrans;D3DXVec3TransformCoord(&m_vEye,&m_vEye,&mat);}

        垂直旋转的话相对来说比较复杂,但是我仔细分析下原理也很简单,首先我们根据观察点到用户视角的向量与婧观察点并且垂直于XZ平面的向量做叉乘,得到的便是垂直于这两条向量的一条向量,然后利用D3DXMatrixRotationAxis这样一个旋转轴函数便可以得出新的玩家视角位置。最后我们看一下Scale缩放视角是怎么实现的:

void CDXThirdCamera::Scale( float fParam ){D3DXVECTOR3 vScale=m_vAt-m_vEye;m_vEye+=vScale*(1-fParam);}
        缩放的操作很简单,没有用到什么函数,就是一个简单的插值处理而已,效果还不错。好了,下面我们继续介绍Walk是如何实现的:

void CDXThirdCamera::Walk( float fWalk ){D3DXVECTOR2 Normal=D3DXVECTOR2(m_vAt.x,m_vAt.z)-D3DXVECTOR2(m_vEye.x,m_vEye.z);D3DXVec2Normalize(&Normal,&Normal);m_vAt+=D3DXVECTOR3(fWalk*Normal.x,0,fWalk*Normal.y);m_vEye+=D3DXVECTOR3(fWalk*Normal.x,0,fWalk*Normal.y);}

        因为行走只是在x和z方向上的位移(y上也会有移动,但必须根据地图来算出当前x和z所处的位置y的大小),所以我们只要构建一个二维方向向量,单位化后它的长度便为1,然后和当前的Eye和At相加下便可得到新的位置大小了。于是Walk(1)便是向前走,那么Walk(-1)便是向后走了,这样就可以少写一个函数了。最后我们再来看下Left是如何实现的:

void CDXThirdCamera::Left( float fLeft ){D3DXVECTOR3 u=m_vEye-m_vAt;D3DXVECTOR3 v=D3DXVECTOR3(m_vAt.x,0,m_vAt.z)-m_vAt;D3DXVECTOR3 out;D3DXVec3Cross(&out,&u,&v);D3DXVec3Normalize(&out,&out);m_vAt+=D3DXVECTOR3(fLeft*out.x,0,fLeft*out.z);m_vEye+=D3DXVECTOR3(fLeft*out.x,0,fLeft*out.z);}

        有了上面的基础,这段代码我相信大家应该很容易就可以看懂了吧。恩,下一节我将带给大家的是rpg游戏里战斗部分的重点:粒子系统。

        本文有不足之处,还望大家多多指正。
       









原创粉丝点击