D3D游戏编程系列(七):自己动手编写rpg游戏之第三人称视角的构建
2013-10-13 10:40
351 查看
终于迎来了自己的最后一个游戏,RPG冒险游戏,这个应该也是当前在单机领域最火的游戏类型了吧,丰富的剧情配上动听的音乐,在加上华丽的画面和带劲的打斗,实在是一个让人心旷神怡的游戏啊,本文旨在塑造一个简单的rpg游戏,希望和大家一起分享这美妙的游戏编程世界。
当前的大部分rpg游戏都是以第三人称视角作为基础的,这个和第一人称略有不同,在Camera的构建上也不尽相同,所以我带大家走进第三人称视角的世界。
第三人称视角需要满足哪些需求,视角的水平旋转,视角的垂直旋转和视角的缩放,于是便有了RotateY,RotateAxis和Scale三个函数,还要注意这里有两个成员变量:
m_vEye代表玩家视角,就是当前Camera所处的位置,而m_vAt便是需要观察的点,说白了就是游戏里玩家操控的人物所处的位置,这样,有了Eye和At便可以形成一个视图矩阵了。
那么我们首先来看下RotateY是怎么实现的:
大家可以看到,我这里没有自己计算,而是全部用了D3DX的函数来做的,首先将当前用户平移玩家视角所在的位置平移,以使玩家的观察点位于原点,然后让Y轴旋转一定角度,最后在平移回来,这样我们就可以产生玩家视角围绕当前人物(观察点)旋转的效果。好,我们再看一下RotateAxis函数是怎么实现的:
垂直旋转的话相对来说比较复杂,但是我仔细分析下原理也很简单,首先我们根据观察点到用户视角的向量与婧观察点并且垂直于XZ平面的向量做叉乘,得到的便是垂直于这两条向量的一条向量,然后利用D3DXMatrixRotationAxis这样一个旋转轴函数便可以得出新的玩家视角位置。最后我们看一下Scale缩放视角是怎么实现的:
缩放的操作很简单,没有用到什么函数,就是一个简单的插值处理而已,效果还不错。好了,下面我们继续介绍Walk是如何实现的:
因为行走只是在x和z方向上的位移(y上也会有移动,但必须根据地图来算出当前x和z所处的位置y的大小),所以我们只要构建一个二维方向向量,单位化后它的长度便为1,然后和当前的Eye和At相加下便可得到新的位置大小了。于是Walk(1)便是向前走,那么Walk(-1)便是向后走了,这样就可以少写一个函数了。最后我们再来看下Left是如何实现的:
有了上面的基础,这段代码我相信大家应该很容易就可以看懂了吧。恩,下一节我将带给大家的是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游戏里战斗部分的重点:粒子系统。
本文有不足之处,还望大家多多指正。
相关文章推荐
- D3D游戏编程系列(四):自己动手编写即时战略游戏之网络同步
- D3D游戏编程系列(六):自己动手编写第一人称射击游戏之第一人称视角的构建
- D3D游戏编程系列(六):自己动手编写第一人称射击游戏之第一人称视角的构建
- D3D游戏编程系列(四):自己动手编写即时战略游戏之网络同步
- D3D游戏编程系列(五):自己动手编写第一人称射击游戏之室外场景的构建
- D3D游戏编程系列(八):自己动手编写rpg游戏之粒子系统
- D3D游戏编程系列(九):自己动手编写rpg游戏之lua脚本的引入
- D3D游戏编程系列(三):自己动手编写即时战略游戏之寻路
- D3D游戏编程系列(三):自己动手编写即时战略游戏之寻路
- D3D游戏编程系列(二):自己动手编写即时战略游戏之地图编辑器的制作
- OWIN系列之自己动手编写中间件
- OWIN系列之自己动手编写中间件
- 自己动手写游戏引擎二(D3D游戏场景)
- [转载]自己动手编写嵌入式Bootloader之(3)
- 自己动手系列——实现一个简单的ArrayList
- 自己动手写操作系统之环境构建篇
- 自己动手设计一款iOS自动构建发布工具
- 自己动手写搜索引擎系列【目录】
- [置顶] ajax实时任务提示功能的实现 -- vb2005xu自己动手系列(1)
- 教程 | 如何在Ethereum上编写自己的CryptoKitties风格的游戏