• 2004-04-22

    [原创] 本人设计的第一人称三维角色类,请高手指点。 - [OpenGL开发专辑]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://junglesong.yourblog.org/logs/156455.html

    一般情况下实现第一人称视角游戏有两种方法,一是移动场景,二是移动眼坐标.移动场景方法比较简单,使用glTranslatef与glRotatef配合即可,但一般只在简单场景和单角色的情况下使用,而且角色的各种计算(如实时坐标、碰撞)不好实现,所以不推荐使用;移动眼坐标的方法就非常灵活,它对场景和角色的状态未做任何操作,一般只要设置成跟随主角色移动旋转即可实现第一人称视角视觉效果,在OpenGL中主要用gluLookAt函数来实现,其函数原形如下。 用途:定义视图变换 包含文件:<glu.h> 描述:根据眼睛的位置,场景中心的位置和从观察者的角度往上指的矢量,定义一个视图变换. 句法:void gluLookAt(Gldouble eyex, Gldouble eyey, Gldouble eyez, Gldouble aimx, Gldouble aimy, Gldouble aimz, Gldouble upx, Gldouble upy, Gldouble upz); 参数: eyex, eyey, eyez:眼睛的三维坐标 aimx, aimy, aimz:被观察的场景中心的三维坐标 upx, upy, upz:指定向上矢量的三维坐标. 除了空战游戏,要实现角色在三维场景中漫游,只需要改变眼睛的三维坐标(eyex, eyey, eyez)和被观察的场景中心的三维坐标(aimx, aimy, aimz)就可以了,指定向上矢量的三维坐标(upx, upy, upz)保持不变,其中又以眼睛的三维坐标为主, 被观察的场景中心的三维坐标为次,本人制作了一个类,粗略实现了漫游功能.首先将三维坐标数据统一成一个结构,如下: //三维点结构。 struct Point{ float x; float y; float z; Point(){ x=y=z=0.0f; } Point(float InputX,float InputY,float InputZ){ x=InputX;y=InputY;z=InputZ; } ~Point(){ } }; //角色类如下 class Dat_Roll { public: Dat_Roll(); ~Dat_Roll(); void TurnLeft(const float InputAngle){//角色左旋 m_fViewAngle-=InputAngle*PI/180; RefreshAimPos(); }; void TurnRight(const float InputAngle){//角色右旋 m_fViewAngle+=InputAngle*PI/180; RefreshAimPos(); }; void TurnUp(const float InputAngle){//向上看 if(m_fViewAngleVertical>PI/2) //防止翻转 m_fViewAngleVertical=PI/2; if(m_fViewAngleVertical<-PI/2) m_fViewAngleVertical=-PI/2; m_fViewAngleVertical-=InputAngle*PI/180; RefreshAimPos(); }; void TurnDown(const float InputAngle){//向下看 if(m_fViewAngleVertical>PI/2) //防止翻转 m_fViewAngleVertical=PI/2; if(m_fViewAngleVertical<-PI/2) m_fViewAngleVertical=-PI/2; m_fViewAngleVertical+=InputAngle*PI/180; RefreshAimPos(); }; void MoveForward(){//向前移动 m_NextEyePos.x+=cos(m_fViewAngle)*m_fMoveSpeed; m_NextEyePos.z+=sin(m_fViewAngle)*m_fMoveSpeed; RefreshAimPos(); }; void MoveBackward(){//向后移动 m_NextEyePos.x-=cos(m_fViewAngle)*m_fMoveSpeed; m_NextEyePos.z-=sin(m_fViewAngle)*m_fMoveSpeed; RefreshAimPos(); }; void MoveLeft(){ //向左移动 m_NextEyePos.x+=sin(m_fViewAngle)*m_fMoveSpeed; m_NextEyePos.z+=cos(m_fViewAngle)*m_fMoveSpeed; RefreshAimPos(); }; void MoveRight(){ //向右移动 m_NextEyePos.x-=sin(m_fViewAngle)*m_fMoveSpeed; m_NextEyePos.z-=cos(m_fViewAngle)*m_fMoveSpeed; RefreshAimPos(); }; void RefreshAimPos(){//刷新目标点,重新计算目标点的三维坐标 m_AimPos.x=m_EyePos.x+m_fEyeAimDis*cos(m_fViewAngle)*cos(m_fViewAngleVertical); m_AimPos.y=m_EyePos.y+m_fEyeAimDis*sin(m_fViewAngleVertical); m_AimPos.z=m_EyePos.z+m_fEyeAimDis*sin(m_fViewAngle)*cos(m_fViewAngleVertical); }; Point GetEyePos(){ return m_EyePos; }; Point GetAimPos(){ return m_AimPos; }; Point GetHoverPos(){ return m_HoverPos; }; private: Point m_EyePos;//眼睛的三维坐标 Point m_NextEyePos;//眼睛下一位置的三维坐标,用于碰撞检测 Point m_AimPos;//被观察的场景中心的三维坐标 Point m_HoverPos;//指定向上矢量的三维坐标. float m_fViewAngle;//水平角度 float m_fViewAngleVertical;//垂直角度 float m_fMoveSpeed;//移动速度 float m_fEyeAimDis;//眼睛到中心的距离 }; Dat_Roll::Dat_Roll(){ m_EyePos=Point(5.0f,4.0f,5.0f); m_AimPos=Point(0.0f,0.0f,0.0f); m_HoverPos=Point(0.0f,1.0f,0.0f); m_fViewAngle=-90.0f*PI/180.0f; m_fViewAngleVertical=0.0f; m_fMoveSpeed=10.0f; m_fEyeAimDis=10; m_NextEyePos=Point(0,0,0); } Dat_Roll::~Dat_Roll(){ } 此文属本人原创,转载请著名作者和出处.

    收藏到:Del.icio.us




发表评论

您将收到博主的回复邮件
记住我