查看: 3871|回复: 17

无用教程第(二)集 sky1811

[复制链接]

该用户从未签到

发表于 2011-9-7 03:10:32 | 显示全部楼层 |阅读模式
本帖最后由 sky11811 于 2011-9-7 03:51 编辑

CS模式操作器









     80后应该对CS游戏十分熟悉,键盘上WSAD键估计多数已字迹模糊。除了轨迹球外,个人最喜欢CS模式操作器,我不知道这种操作器叫什么中文名字,第一人称射击游戏操作器有些繁琐,就暂时叫CS操作器吧。在OSG2.8.0后的某个版本,出现了这个FirstPersonManipulator,但是稀奇的是代码里有
  1. /// Move camera right by distance parameter.
  2. void FirstPersonManipulator::moveRight( const double distance )
  3. {
  4. assert( 0 && "Not implemented yet." );
  5. }
复制代码

直到最新版本,这个还是Not implemented yet。呵呵,既然人家不implemented ,那就自己来吧。估计作者对这个操作器有很高的期望值,想做的完美,所以暂时没有实现。我在这里先替作者完成个初稿吧,当然不完美,期待电脑前的您把它做的完美。我在办公室的计算机里对这个操作器做了很详细的改进,可恶的是无法导出,所以不能和大家分享成果,实在是遗憾,今天利用2个多小时的时间,整理思路,又重新在家里做了一次,由于时间短只对重要的部分进行了梳理,并写出来粗糙的文档,请原谅这粗糙的文字。
现在是凌晨2:40,写完就不知道几点啦,老婆孩子0点睡了。我写程序在家是被禁止的,所以只能等老婆孩子睡熟了才能偷爬起来干。

---------------------------------------------------------------------正事开始------------------------------------------------------------------------------------
第一步,你需要最新版的OSG源代码,并编译通过,记得要编译示例程序。因为要用其中某些程序来测试修改后的操作器。
第二步,修改osgGA部分的一些代码,重新编译osgGA。
第三步,修改示例程序中的osgPick代码,把FirstPersonManipulator填进去,重新编译,用来测试修改效果。
第四步,运行osgPick,感受CS的操作体验,记得把osg的数据模型文件拷贝到与osgPick.exe同一目录。

现在开始详细的说明步骤。
打开vc2005,别的版本也可以。修改FirstPersonManipulator.cpp,将
  1. /// Move camera right by distance parameter.
  2. void FirstPersonManipulator::moveRight( const double distance )
  3. {
  4. assert( 0 && "Not implemented yet." );
  5. }
复制代码

修改为,
  1. /// Move camera right by distance parameter.
  2. void FirstPersonManipulator::moveRight( const double distance )
  3. {
  4. _eye += _rotation * Vec3d( distance, 0., 0. );
  5. }
复制代码

至于为什么,我暂时先不解释,以后的教程里会详细介绍相关的数学知识。
在FirstPersonManipulator.h文件里添加
virtual bool handleKeyDown( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us );
最好添加在protected:段落里。
在FirstPersonManipulator.cpp添加
  1. /// Handles GUIEventAdapter::KEYDOWN event.
  2. bool FirstPersonManipulator::handleKeyDown( const GUIEventAdapter& ea, GUIActionAdapter& us )
  3. {
  4. if( ea.getKey() == GUIEventAdapter::KEY_Space )
  5. {
  6. flushMouseEventStack();
  7. _thrown = false;
  8. home(ea,us);
  9. return true;
  10. }
  11. if( ea.getKey() == 'w' )
  12. {
  13. moveForward(5.0);
  14. return true;
  15. }
  16. if( ea.getKey() == 's' )
  17. {
  18. moveForward(-5.0);
  19. return true;
  20. }
  21. if( ea.getKey() == 'a' )
  22. {
  23. moveRight(-5.0);
  24. return true;
  25. }
  26. if( ea.getKey() == 'd' )
  27. {
  28. moveRight(5.0);
  29. return true;
  30. }
  31. return false;

  32. }
复制代码

生成osgGA。

在osgPick的代码里添加
keyswitchManipulator->addMatrixManipulator( '5', "fps", new osgGA::FirstPersonManipulator() );
记住,在
keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
这一行紧后面添加。就怕新手不会弄。
生成oskPick,运行它。可以在bin目录里直接双击osgPick.exe.
按下数字5切换至CS操作器,按下WSAD键,体会下,有没有CS的感觉。千万记住fountain.osgt要与osgPick.exe放在一起,新手急死人啊,呵呵。
如果不出差错的话,就应该能体验CS的感觉啦。
我这里是可以体验的,但是效果很差强人意,有明显的卡、顿,不流畅。

这个问题其实很简单,因为系统对handleKeyDown的调用频率并不高,所以造成不流畅。我们必须让WSAD拥有绝对的优先被处理权。
FirstPersonManipulator继承自StandardManipulator,所以要修改StandardManipulator的代码,让我们亲爱的WSAD最先被执行,有消息就执行。
为此,在StandardManipulator头文件的protected段落中添加
virtual bool DoItEveryEvent(){return true;};
然后再改动StandardManipulator.cpp
在bool StandardManipulator::handle( const GUIEventAdapter& ea, GUIActionAdapter& us )函数
一开始添加一句DoItEveryEvent();
变为下面的样子。
  1. /** Handles events. Returns true if handled, false otherwise.*/
  2. bool StandardManipulator::handle( const GUIEventAdapter& ea, GUIActionAdapter& us )
  3. {
  4. DoItEveryEvent();
  5. switch( ea.getEventType() )
  6. {

  7. case GUIEventAdapter::FRAME:
  8. return handleFrame( ea, us );

  9. case GUIEventAdapter::RESIZE:
  10. return handleResize( ea, us );

  11. default:
  12. break;
  13. }

  14. if( ea.getHandled() )
  15. return false;

  16. switch( ea.getEventType() )
  17. {
  18. case GUIEventAdapter::MOVE:
  19. return handleMouseMove( ea, us );

  20. case GUIEventAdapter::DRAG:
  21. return handleMouseDrag( ea, us );

  22. case GUIEventAdapter::PUSH:
  23. return handleMousePush( ea, us );

  24. case GUIEventAdapter::RELEASE:
  25. return handleMouseRelease( ea, us );

  26. case GUIEventAdapter::KEYDOWN:
  27. return handleKeyDown( ea, us );

  28. case GUIEventAdapter::KEYUP:
  29. return handleKeyUp( ea, us );

  30. case GUIEventAdapter::SCROLL:
  31. if( _flags & PROCESS_MOUSE_WHEEL )
  32. return handleMouseWheel( ea, us );
  33. else
  34. return false;

  35. default:
  36. return false;
  37. }
  38. }
复制代码


其实就加了一句函数调用。为了新手方便就不计较篇幅了。
然后在
FirstPersonManipulator头文件的protected段落中添加
virtual bool DoItEveryEvent();
在FirstPersonManipulator.cpp中添加
  1. bool FirstPersonManipulator::DoItEveryEvent()
  2. {
  3. if(GetKeyState('W') & 0x80)
  4. {
  5. moveForward(5.0);
  6. }
  7. if(GetKeyState('S') & 0x80)
  8. {
  9. moveForward(-5.0);
  10. }
  11. if(GetKeyState('A') & 0x80)
  12. {
  13. moveRight(-5.0);
  14. }
  15. if(GetKeyState('D') & 0x80)
  16. {
  17. moveRight(5.0);
  18. }
  19. return true;
  20. }
复制代码

把原来的handleKeyDown函数在头文件和cpp文件中注释掉,删了也行。
生成osgGA,在bin目录里双击osgPick.exe,按5,然后按WSAD试试,一切变得很顺滑,呵呵呵。

好啦,写完啦,该睡觉啦,再不睡就翘辫子啦。

该用户从未签到

 楼主| 发表于 2011-9-7 03:54:05 | 显示全部楼层
走啦,睡啦。

该用户从未签到

发表于 2011-9-7 08:20:06 | 显示全部楼层
顶起,支持。

该用户从未签到

发表于 2011-9-7 08:25:42 | 显示全部楼层
谢谢发帖共享,不过楼主为什么不考虑把自己的更改提交给osg-submissions呢,呵呵

该用户从未签到

发表于 2011-9-7 11:01:50 | 显示全部楼层
楼主也要注意休息啊~~~~

该用户从未签到

发表于 2011-9-7 11:24:10 | 显示全部楼层
多谢楼主了

该用户从未签到

 楼主| 发表于 2011-9-7 20:13:30 | 显示全部楼层
如果GetKeyState函数找不到,请加上这一句 #include <windows.h>

该用户从未签到

发表于 2011-9-8 10:48:33 | 显示全部楼层
是真名士自风流。

该用户从未签到

发表于 2011-9-13 12:24:39 | 显示全部楼层
楼主精神可嘉。

该用户从未签到

发表于 2011-9-13 14:54:23 | 显示全部楼层
身体重要,还是要先休息好啊

该用户从未签到

发表于 2012-2-7 12:53:34 | 显示全部楼层
敬佩楼主的精神,向您学习,敬礼!

该用户从未签到

发表于 2012-2-17 13:39:52 | 显示全部楼层
向LZ学习。

该用户从未签到

发表于 2012-7-1 17:31:41 | 显示全部楼层
谢谢楼主分享!

该用户从未签到

发表于 2012-7-1 17:31:46 | 显示全部楼层
谢谢楼主分享!

该用户从未签到

发表于 2012-7-1 17:31:54 | 显示全部楼层
谢谢楼主分享!

该用户从未签到

发表于 2012-7-23 17:15:55 | 显示全部楼层
好东西 mark 下!话说我这水平还只是学习怎么用!还没深入到了解库里门的函数!

该用户从未签到

发表于 2012-8-19 11:32:58 | 显示全部楼层
osg的最新trunk版,实现了这个类,但是我在android上运行,没效果,不知道为什么

该用户从未签到

发表于 2012-9-23 13:03:38 | 显示全部楼层
精神可嘉,可嘉。努力学习
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表