基于OGRE实现一个简单的3D游戏(软件工程作业2)

基于OGRE实现一个简单的3D游戏(软件工程作业2)

学号:2011211910   

同组博客链接:http://thefrp.sinaapp.com/

题目:

实现一个3D游戏


最终效果:

游戏截图:

兽人和机器人敌人

游戏说明:

用WASD控制兽人前左右后移动,空格跳跃,Q拿起武器,鼠标左键和右键为攻击。没击杀一个机器人敌人,就会出现新的机器人敌人,无限模式。

学习体会:

  • 了解了基本的OGRE知识
  • 熟悉了C++编程
  • 结对编程的乐趣还有队友之间的协助,事半功倍
  • 第一次学习了有关游戏编程的东西,有一种创造的成就感

代码:

CharacterSample.h

  1. #ifndef __Character_H__
  2. #define __Character_H__
  3. #include"SdkSample.h"
  4. #include"SinbadCharacterController.h"
  5. usingnamespaceOgre;
  6. usingnamespaceOgreBites;
  7. class_OgreSampleClassExportSample_Character:publicSdkSample
  8. {
  9. public:
  10. Sample_Character()
  11. {
  12. mInfo["Title"]="Character";
  13. mInfo["Description"]="A demo showing 3rd-person character control and use of TagPoints.";
  14. mInfo["Thumbnail"]="thumb_char.png";
  15. mInfo["Category"]="Animation";
  16. mInfo["Help"]="Use the WASD keys to move Sinbad, and the space bar to jump. "
  17. "Use mouse to look around and mouse wheel to zoom. Press Q to take out or put back "
  18. "Sinbad's swords. With the swords equipped, you can left click to slice vertically or "
  19. "right click to slice horizontally. When the swords are not equipped, press E to "
  20. "start/stop a silly dance routine.";
  21. }
  22. bool frameRenderingQueued(constFrameEvent& evt)
  23. {
  24. // let character update animations and camera
  25. mChara->addTime(evt.timeSinceLastFrame);
  26. returnSdkSample::frameRenderingQueued(evt);
  27. }
  28. bool keyPressed(const OIS::KeyEvent& evt)
  29. {
  30. // relay input events to character controller
  31. if(!mTrayMgr->isDialogVisible()) mChara->injectKeyDown(evt);
  32. returnSdkSample::keyPressed(evt);
  33. }
  34. bool keyReleased(const OIS::KeyEvent& evt)
  35. {
  36. // relay input events to character controller
  37. if(!mTrayMgr->isDialogVisible()) mChara->injectKeyUp(evt);
  38. returnSdkSample::keyReleased(evt);
  39. }
  40. #if (OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS) || (OGRE_PLATFORM == OGRE_PLATFORM_ANDROID)
  41. bool touchPressed(const OIS::MultiTouchEvent& evt)
  42. {
  43. // relay input events to character controller
  44. if(!mTrayMgr->isDialogVisible()) mChara->injectMouseDown(evt);
  45. returnSdkSample::touchPressed(evt);
  46. }
  47. bool touchMoved(const OIS::MultiTouchEvent& evt)
  48. {
  49. // relay input events to character controller
  50. if(!mTrayMgr->isDialogVisible()) mChara->injectMouseMove(evt);
  51. returnSdkSample::touchMoved(evt);
  52. }
  53. #else
  54. bool mouseMoved(const OIS::MouseEvent& evt)
  55. {
  56. // relay input events to character controller
  57. if(!mTrayMgr->isDialogVisible()) mChara->injectMouseMove(evt);
  58. returnSdkSample::mouseMoved(evt);
  59. }
  60. bool mousePressed(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
  61. {
  62. // relay input events to character controller
  63. if(!mTrayMgr->isDialogVisible()) mChara->injectMouseDown(evt, id);
  64. returnSdkSample::mousePressed(evt, id);
  65. }
  66. #endif
  67. protected:
  68. void setupContent()
  69. {
  70. // set background and some fog
  71. mViewport->setBackgroundColour(ColourValue(1.0f,1.0f,0.8f));
  72. mSceneMgr->setFog(Ogre::FOG_LINEAR,ColourValue(1.0f,1.0f,0.8f),0,15,100);
  73. // set shadow properties
  74. mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
  75. mSceneMgr->setShadowColour(ColourValue(0.5,0.5,0.5));
  76. mSceneMgr->setShadowTextureSize(1024);
  77. mSceneMgr->setShadowTextureCount(1);
  78. // disable default camera control so the character can do its own
  79. mCameraMan->setStyle(CS_MANUAL);
  80. // use a small amount of ambient lighting
  81. mSceneMgr->setAmbientLight(ColourValue(0.3,0.3,0.3));
  82. // add a bright light above the scene
  83. Light* light = mSceneMgr->createLight();
  84. light->setType(Light::LT_POINT);
  85. light->setPosition(-10,40,20);
  86. light->setSpecularColour(ColourValue::White);
  87. // create a floor mesh resource
  88. MeshManager::getSingleton().createPlane("floor",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
  89. Plane(Vector3::UNIT_Y,0),200,200,10,10,true,1,10,10,Vector3::UNIT_Z);
  90. // create a floor entity, give it a material, and place it at the origin
  91. Entity* floor = mSceneMgr->createEntity("Floor","floor");
  92. floor->setMaterialName("Examples/Instancing/Misc/Grass");
  93. floor->setCastShadows(false);
  94. mSceneMgr->getRootSceneNode()->attachObject(floor);
  95. // LogManager::getSingleton().logMessage("creating sinbad");
  96. // create our character controller
  97. mChara =newSinbadCharacterController(mCamera);
  98. // LogManager::getSingleton().logMessage("toggling stats");
  99. mTrayMgr->toggleAdvancedFrameStats();
  100. // LogManager::getSingleton().logMessage("creating panel");
  101. StringVector items;
  102. items.push_back("Help");
  103. ParamsPanel* help = mTrayMgr->createParamsPanel(TL_TOPLEFT,"HelpMessage",100, items);
  104. help->setParamValue("Help","H / F1");
  105. // LogManager::getSingleton().logMessage("all done");
  106. }
  107. void cleanupContent()
  108. {
  109. // clean up character controller and the floor mesh
  110. if(mChara)
  111. {
  112. delete mChara;
  113. mChara =0;
  114. }
  115. MeshManager::getSingleton().remove("floor");
  116. }
  117. SinbadCharacterController* mChara;
  118. };
  119. #endif

SinbadCharacterController.h

  1. #ifndef __Sinbad_H__
  2. #define __Sinbad_H__
  3. #include"Ogre.h"
  4. #include"OIS.h"
  5. #include<cstdlib>
  6. usingnamespaceOgre;
  7. #define NUM_ANIMS 13// number of animations the character has
  8. #define CHAR_HEIGHT 5// height of character's center of mass above ground
  9. #define CAM_HEIGHT 2// height of camera above character's center of mass
  10. #define RUN_SPEED 17// character running speed in units per second
  11. #define TURN_SPEED 500.0f// character turning in degrees per second
  12. #define ANIM_FADE_SPEED 7.5f// animation crossfade speed in % of full weight per second
  13. #define JUMP_ACCEL 30.0f// character jump acceleration in upward units per squared second
  14. #define GRAVITY 90.0f// gravity in downward units per squared second
  15. classSinbadCharacterController
  16. {
  17. private:
  18. // all the animations our character has, and a null ID
  19. // some of these affect separate body parts and will be blended together
  20. enumAnimID
  21. {
  22. ANIM_IDLE_BASE,
  23. ANIM_IDLE_TOP,
  24. ANIM_RUN_BASE,
  25. ANIM_RUN_TOP,
  26. ANIM_HANDS_CLOSED,
  27. ANIM_HANDS_RELAXED,
  28. ANIM_DRAW_SWORDS,
  29. ANIM_SLICE_VERTICAL,
  30. ANIM_SLICE_HORIZONTAL,
  31. ANIM_DANCE,
  32. ANIM_JUMP_START,
  33. ANIM_JUMP_LOOP,
  34. ANIM_JUMP_END,
  35. ANIM_NONE
  36. };
  37. public:
  38. SinbadCharacterController(Camera* cam)
  39. {
  40. setupBody(cam->getSceneManager());
  41. setupCamera(cam);
  42. setupAnimations();
  43. }
  44. void addTime(Real deltaTime)
  45. {
  46. updateBody(deltaTime);
  47. updateAnimations(deltaTime);
  48. updateCamera(deltaTime);
  49. }
  50. void injectKeyDown(const OIS::KeyEvent& evt)
  51. {
  52. if(evt.key == OIS::KC_Q &&(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
  53. {
  54. // take swords out (or put them back, since it's the same animation but reversed)
  55. setTopAnimation(ANIM_DRAW_SWORDS,true);
  56. mTimer =0;
  57. }
  58. elseif(evt.key == OIS::KC_E &&!mSwordsDrawn)
  59. {
  60. if(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP)
  61. {
  62. // start dancing
  63. setBaseAnimation(ANIM_DANCE,true);
  64. setTopAnimation(ANIM_NONE);
  65. // disable hand animation because the dance controls hands
  66. mAnims[ANIM_HANDS_RELAXED]->setEnabled(false);
  67. }
  68. elseif(mBaseAnimID == ANIM_DANCE)
  69. {
  70. // stop dancing
  71. setBaseAnimation(ANIM_IDLE_BASE);
  72. setTopAnimation(ANIM_IDLE_TOP);
  73. // re-enable hand animation
  74. mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
  75. }
  76. }
  77. // keep track of the player's intended direction
  78. elseif(evt.key == OIS::KC_W) mKeyDirection.z =-1;
  79. elseif(evt.key == OIS::KC_A) mKeyDirection.x =-1;
  80. elseif(evt.key == OIS::KC_S) mKeyDirection.z =1;
  81. elseif(evt.key == OIS::KC_D) mKeyDirection.x =1;
  82. elseif(evt.key == OIS::KC_SPACE &&(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
  83. {
  84. // jump if on ground
  85. setBaseAnimation(ANIM_JUMP_START,true);
  86. setTopAnimation(ANIM_NONE);
  87. mTimer =0;
  88. }
  89. if(!mKeyDirection.isZeroLength()&& mBaseAnimID == ANIM_IDLE_BASE)
  90. {
  91. // start running if not already moving and the player wants to move
  92. setBaseAnimation(ANIM_RUN_BASE,true);
  93. if(mTopAnimID == ANIM_IDLE_TOP) setTopAnimation(ANIM_RUN_TOP,true);
  94. }
  95. }
  96. void injectKeyUp(const OIS::KeyEvent& evt)
  97. {
  98. // keep track of the player's intended direction
  99. if(evt.key == OIS::KC_W && mKeyDirection.z ==-1) mKeyDirection.z =0;
  100. elseif(evt.key == OIS::KC_A && mKeyDirection.x ==-1) mKeyDirection.x =0;
  101. elseif(evt.key == OIS::KC_S && mKeyDirection.z ==1) mKeyDirection.z =0;
  102. elseif(evt.key == OIS::KC_D && mKeyDirection.x ==1) mKeyDirection.x =0;
  103. if(mKeyDirection.isZeroLength()&& mBaseAnimID == ANIM_RUN_BASE)
  104. {
  105. // stop running if already moving and the player doesn't want to move
  106. setBaseAnimation(ANIM_IDLE_BASE);
  107. if(mTopAnimID == ANIM_RUN_TOP) setTopAnimation(ANIM_IDLE_TOP);
  108. }
  109. }
  110. #if (OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS) || (OGRE_PLATFORM == OGRE_PLATFORM_ANDROID)
  111. void injectMouseMove(const OIS::MultiTouchEvent& evt)
  112. {
  113. // update camera goal based on mouse movement
  114. updateCameraGoal(-0.05f* evt.state.X.rel,-0.05f* evt.state.Y.rel,-0.0005f* evt.state.Z.rel);
  115. }
  116. void injectMouseDown(const OIS::MultiTouchEvent& evt)
  117. {
  118. if(mSwordsDrawn &&(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
  119. {
  120. // if swords are out, and character's not doing something weird, then SLICE!
  121. setTopAnimation(ANIM_SLICE_VERTICAL,true);
  122. mTimer =0;
  123. }
  124. }
  125. #else
  126. void injectMouseMove(const OIS::MouseEvent& evt)
  127. {
  128. // update camera goal based on mouse movement
  129. updateCameraGoal(-0.05f* evt.state.X.rel,-0.05f* evt.state.Y.rel,-0.0005f* evt.state.Z.rel);
  130. }
  131. void injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
  132. {
  133. if(mSwordsDrawn &&(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
  134. {
  135. // if swords are out, and character's not doing something weird, then SLICE!
  136. if(id == OIS::MB_Left) setTopAnimation(ANIM_SLICE_VERTICAL,true);
  137. elseif(id == OIS::MB_Right) setTopAnimation(ANIM_SLICE_HORIZONTAL,true);
  138. mTimer =0;
  139. //碰撞检测
  140. AxisAlignedBox mSword1box = mBodyNode->_getWorldAABB();
  141. AxisAlignedBox robotbox = node->_getWorldAABB();
  142. if(mSword1box.intersects(robotbox))
  143. {
  144. //相交
  145. //dra->setVisible(0);
  146. node->setPosition( rand()%50,0,rand()%50);//rand() % 100,rand() % 100,0);
  147. }
  148. }
  149. }
  150. #endif
  151. private:
  152. void setupBody(SceneManager* sceneMgr)
  153. {
  154. // create main model
  155. mBodyNode = sceneMgr->getRootSceneNode()->createChildSceneNode(Vector3::UNIT_Y * CHAR_HEIGHT);
  156. mBodyEnt = sceneMgr->createEntity("SinbadBody","Sinbad.mesh");
  157. mBodyNode->attachObject(mBodyEnt);
  158. // create swords and attach to sheath
  159. LogManager::getSingleton().logMessage("Creating swords");
  160. mSword1 = sceneMgr->createEntity("SinbadSword1","Sword.mesh");
  161. mSword2 = sceneMgr->createEntity("SinbadSword2","Sword.mesh");
  162. mBodyEnt->attachObjectToBone("Sheath.L", mSword1);
  163. mBodyEnt->attachObjectToBone("Sheath.R", mSword2);
  164. //sceneMgr->getRootSceneNode()->attachObject(sceneMgr->createEntity("Head", "ogrehead.mesh"));
  165. // and finally... omg it's a DRAGON!
  166. dra = sceneMgr->createEntity("Robot","robot.mesh");
  167. //sceneMgr->getRootSceneNode()->attachObject(dra);
  168. node = sceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode",Vector3(20,0,0));
  169. node->attachObject(dra);
  170. node->scale(0.1,0.1,0.1);
  171. LogManager::getSingleton().logMessage("Creating the chains");
  172. // create a couple of ribbon trails for the swords, just for fun
  173. NameValuePairListparams;
  174. params["numberOfChains"]="2";
  175. params["maxElements"]="80";
  176. mSwordTrail =(RibbonTrail*)sceneMgr->createMovableObject("RibbonTrail",&params);
  177. mSwordTrail->setMaterialName("Examples/LightRibbonTrail");
  178. mSwordTrail->setTrailLength(20);
  179. mSwordTrail->setVisible(false);
  180. sceneMgr->getRootSceneNode()->attachObject(mSwordTrail);
  181. for(int i =0; i <2; i++)
  182. {
  183. mSwordTrail->setInitialColour(i,1,0.8,0);
  184. mSwordTrail->setColourChange(i,0.75,1.25,1.25,1.25);
  185. mSwordTrail->setWidthChange(i,1);
  186. mSwordTrail->setInitialWidth(i,0.5);
  187. }
  188. mKeyDirection =Vector3::ZERO;
  189. mVerticalVelocity =0;
  190. }
  191. void setupAnimations()
  192. {
  193. // this is very important due to the nature of the exported animations
  194. mBodyEnt->getSkeleton()->setBlendMode(ANIMBLEND_CUMULATIVE);
  195. String animNames[]=
  196. {"IdleBase","IdleTop","RunBase","RunTop","HandsClosed","HandsRelaxed","DrawSwords",
  197. "SliceVertical","SliceHorizontal","Dance","JumpStart","JumpLoop","JumpEnd"};
  198. // populate our animation list
  199. for(int i =0; i < NUM_ANIMS; i++)
  200. {
  201. mAnims[i]= mBodyEnt->getAnimationState(animNames[i]);
  202. mAnims[i]->setLoop(true);
  203. mFadingIn[i]=false;
  204. mFadingOut[i]=false;
  205. }
  206. // start off in the idle state (top and bottom together)
  207. setBaseAnimation(ANIM_IDLE_BASE);
  208. setTopAnimation(ANIM_IDLE_TOP);
  209. // relax the hands since we're not holding anything
  210. mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
  211. mSwordsDrawn =false;
  212. }
  213. void setupCamera(Camera* cam)
  214. {
  215. // create a pivot at roughly the character's shoulder
  216. mCameraPivot = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
  217. // this is where the camera should be soon, and it spins around the pivot
  218. mCameraGoal = mCameraPivot->createChildSceneNode(Vector3(0,0,15));
  219. // this is where the camera actually is
  220. mCameraNode = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
  221. mCameraNode->setPosition(mCameraPivot->getPosition()+ mCameraGoal->getPosition());
  222. mCameraPivot->setFixedYawAxis(true);
  223. mCameraGoal->setFixedYawAxis(true);
  224. mCameraNode->setFixedYawAxis(true);
  225. // our model is quite small, so reduce the clipping planes
  226. cam->setNearClipDistance(0.1);
  227. cam->setFarClipDistance(100);
  228. mCameraNode->attachObject(cam);
  229. mPivotPitch =0;
  230. }
  231. void updateBody(Real deltaTime)
  232. {
  233. mGoalDirection =Vector3::ZERO;// we will calculate this
  234. if(mKeyDirection !=Vector3::ZERO && mBaseAnimID != ANIM_DANCE)
  235. {
  236. // calculate actually goal direction in world based on player's key directions
  237. mGoalDirection += mKeyDirection.z * mCameraNode->getOrientation().zAxis();
  238. mGoalDirection += mKeyDirection.x * mCameraNode->getOrientation().xAxis();
  239. mGoalDirection.y =0;
  240. mGoalDirection.normalise();
  241. Quaternion toGoal = mBodyNode->getOrientation().zAxis().getRotationTo(mGoalDirection);
  242. // calculate how much the character has to turn to face goal direction
  243. Real yawToGoal = toGoal.getYaw().valueDegrees();
  244. // this is how much the character CAN turn this frame
  245. Real yawAtSpeed = yawToGoal /Math::Abs(yawToGoal)* deltaTime * TURN_SPEED;
  246. // reduce "turnability" if we're in midair
  247. if(mBaseAnimID == ANIM_JUMP_LOOP) yawAtSpeed *=0.2f;
  248. // turn as much as we can, but not more than we need to
  249. if(yawToGoal <0) yawToGoal = std::min<Real>(0, std::max<Real>(yawToGoal, yawAtSpeed));//yawToGoal = Math::Clamp<Real>(yawToGoal, yawAtSpeed, 0);
  250. elseif(yawToGoal >0) yawToGoal = std::max<Real>(0, std::min<Real>(yawToGoal, yawAtSpeed));//yawToGoal = Math::Clamp<Real>(yawToGoal, 0, yawAtSpeed);
  251. mBodyNode->yaw(Degree(yawToGoal));
  252. // move in current body direction (not the goal direction)
  253. mBodyNode->translate(0,0, deltaTime * RUN_SPEED * mAnims[mBaseAnimID]->getWeight(),
  254. Node::TS_LOCAL);
  255. }
  256. if(mBaseAnimID == ANIM_JUMP_LOOP)
  257. {
  258. // if we're jumping, add a vertical offset too, and apply gravity
  259. mBodyNode->translate(0, mVerticalVelocity * deltaTime,0,Node::TS_LOCAL);
  260. mVerticalVelocity -= GRAVITY * deltaTime;
  261. Vector3 pos = mBodyNode->getPosition();
  262. if(pos.y <= CHAR_HEIGHT)
  263. {
  264. // if we've hit the ground, change to landing state
  265. pos.y = CHAR_HEIGHT;
  266. mBodyNode->setPosition(pos);
  267. setBaseAnimation(ANIM_JUMP_END,true);
  268. mTimer =0;
  269. }
  270. }
  271. }
  272. void updateAnimations(Real deltaTime)
  273. {
  274. Real baseAnimSpeed =1;
  275. Real topAnimSpeed =1;
  276. mTimer += deltaTime;
  277. if(mTopAnimID == ANIM_DRAW_SWORDS)
  278. {
  279. // flip the draw swords animation if we need to put it back
  280. topAnimSpeed = mSwordsDrawn ?-1:1;
  281. // half-way through the animation is when the hand grasps the handles...
  282. if(mTimer >= mAnims[mTopAnimID]->getLength()/2&&
  283. mTimer - deltaTime < mAnims[mTopAnimID]->getLength()/2)
  284. {
  285. // so transfer the swords from the sheaths to the hands
  286. mBodyEnt->detachAllObjectsFromBone();
  287. mBodyEnt->attachObjectToBone(mSwordsDrawn ?"Sheath.L":"Handle.L", mSword1);
  288. mBodyEnt->attachObjectToBone(mSwordsDrawn ?"Sheath.R":"Handle.R", mSword2);
  289. // change the hand state to grab or let go
  290. mAnims[ANIM_HANDS_CLOSED]->setEnabled(!mSwordsDrawn);
  291. mAnims[ANIM_HANDS_RELAXED]->setEnabled(mSwordsDrawn);
  292. // toggle sword trails
  293. if(mSwordsDrawn)
  294. {
  295. mSwordTrail->setVisible(false);
  296. mSwordTrail->removeNode(mSword1->getParentNode());
  297. mSwordTrail->removeNode(mSword2->getParentNode());
  298. }
  299. else
  300. {
  301. mSwordTrail->setVisible(true);
  302. mSwordTrail->addNode(mSword1->getParentNode());
  303. mSwordTrail->addNode(mSword2->getParentNode());
  304. }
  305. }
  306. if(mTimer >= mAnims[mTopAnimID]->getLength())
  307. {
  308. // animation is finished, so return to what we were doing before
  309. if(mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
  310. else
  311. {
  312. setTopAnimation(ANIM_RUN_TOP);
  313. mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
  314. }
  315. mSwordsDrawn =!mSwordsDrawn;
  316. }
  317. }
  318. elseif(mTopAnimID == ANIM_SLICE_VERTICAL || mTopAnimID == ANIM_SLICE_HORIZONTAL)
  319. {
  320. if(mTimer >= mAnims[mTopAnimID]->getLength())
  321. {
  322. // animation is finished, so return to what we were doing before
  323. if(mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
  324. else
  325. {
  326. setTopAnimation(ANIM_RUN_TOP);
  327. mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
  328. }
  329. }
  330. // don't sway hips from side to side when slicing. that's just embarrassing.
  331. if(mBaseAnimID == ANIM_IDLE_BASE) baseAnimSpeed =0;
  332. }
  333. elseif(mBaseAnimID == ANIM_JUMP_START)
  334. {
  335. if(mTimer >= mAnims[mBaseAnimID]->getLength())
  336. {
  337. // takeoff animation finished, so time to leave the ground!
  338. setBaseAnimation(ANIM_JUMP_LOOP,true);
  339. // apply a jump acceleration to the character
  340. mVerticalVelocity = JUMP_ACCEL;
  341. }
  342. }
  343. elseif(mBaseAnimID == ANIM_JUMP_END)
  344. {
  345. if(mTimer >= mAnims[mBaseAnimID]->getLength())
  346. {
  347. // safely landed, so go back to running or idling
  348. if(mKeyDirection ==Vector3::ZERO)
  349. {
  350. setBaseAnimation(ANIM_IDLE_BASE);
  351. setTopAnimation(ANIM_IDLE_TOP);
  352. }
  353. else
  354. {
  355. setBaseAnimation(ANIM_RUN_BASE,true);
  356. setTopAnimation(ANIM_RUN_TOP,true);
  357. }
  358. }
  359. }
  360. // increment the current base and top animation times
  361. if(mBaseAnimID != ANIM_NONE) mAnims[mBaseAnimID]->addTime(deltaTime * baseAnimSpeed);
  362. if(mTopAnimID != ANIM_NONE) mAnims[mTopAnimID]->addTime(deltaTime * topAnimSpeed);
  363. // apply smooth transitioning between our animations
  364. fadeAnimations(deltaTime);
  365. }
  366. void fadeAnimations(Real deltaTime)
  367. {
  368. for(int i =0; i < NUM_ANIMS; i++)
  369. {
  370. if(mFadingIn[i])
  371. {
  372. // slowly fade this animation in until it has full weight
  373. Real newWeight = mAnims[i]->getWeight()+ deltaTime * ANIM_FADE_SPEED;
  374. mAnims[i]->setWeight(Math::Clamp<Real>(newWeight,0,1));
  375. if(newWeight >=1) mFadingIn[i]=false;
  376. }
  377. elseif(mFadingOut[i])
  378. {
  379. // slowly fade this animation out until it has no weight, and then disable it
  380. Real newWeight = mAnims[i]->getWeight()- deltaTime * ANIM_FADE_SPEED;
  381. mAnims[i]->setWeight(Math::Clamp<Real>(newWeight,0,1));
  382. if(newWeight <=0)
  383. {
  384. mAnims[i]->setEnabled(false);
  385. mFadingOut[i]=false;
  386. }
  387. }
  388. }
  389. }
  390. void updateCamera(Real deltaTime)
  391. {
  392. // place the camera pivot roughly at the character's shoulder
  393. mCameraPivot->setPosition(mBodyNode->getPosition()+Vector3::UNIT_Y * CAM_HEIGHT);
  394. // move the camera smoothly to the goal
  395. Vector3 goalOffset = mCameraGoal->_getDerivedPosition()- mCameraNode->getPosition();
  396. mCameraNode->translate(goalOffset * deltaTime *9.0f);
  397. // always look at the pivot
  398. mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(),Node::TS_WORLD);
  399. }
  400. void updateCameraGoal(Real deltaYaw,Real deltaPitch,Real deltaZoom)
  401. {
  402. mCameraPivot->yaw(Degree(deltaYaw),Node::TS_WORLD);
  403. // bound the pitch
  404. if(!(mPivotPitch + deltaPitch >25&& deltaPitch >0)&&
  405. !(mPivotPitch + deltaPitch <-60&& deltaPitch <0))
  406. {
  407. mCameraPivot->pitch(Degree(deltaPitch),Node::TS_LOCAL);
  408. mPivotPitch += deltaPitch;
  409. }
  410. Real dist = mCameraGoal->_getDerivedPosition().distance(mCameraPivot->_getDerivedPosition());
  411. Real distChange = deltaZoom * dist;
  412. // bound the zoom
  413. if(!(dist + distChange <8&& distChange <0)&&
  414. !(dist + distChange >25&& distChange >0))
  415. {
  416. mCameraGoal->translate(0,0, distChange,Node::TS_LOCAL);
  417. }
  418. }
  419. void setBaseAnimation(AnimID id,bool reset =false)
  420. {
  421. if(mBaseAnimID >=0&& mBaseAnimID < NUM_ANIMS)
  422. {
  423. // if we have an old animation, fade it out
  424. mFadingIn[mBaseAnimID]=false;
  425. mFadingOut[mBaseAnimID]=true;
  426. }
  427. mBaseAnimID = id;
  428. if(id != ANIM_NONE)
  429. {
  430. // if we have a new animation, enable it and fade it in
  431. mAnims[id]->setEnabled(true);
  432. mAnims[id]->setWeight(0);
  433. mFadingOut[id]=false;
  434. mFadingIn[id]=true;
  435. if(reset) mAnims[id]->setTimePosition(0);
  436. }
  437. }
  438. void setTopAnimation(AnimID id,bool reset =false)
  439. {
  440. if(mTopAnimID >=0&& mTopAnimID < NUM_ANIMS)
  441. {
  442. // if we have an old animation, fade it out
  443. mFadingIn[mTopAnimID]=false;
  444. mFadingOut[mTopAnimID]=true;
  445. }
  446. mTopAnimID = id;
  447. if(id != ANIM_NONE)
  448. {
  449. // if we have a new animation, enable it and fade it in
  450. mAnims[id]->setEnabled(true);
  451. mAnims[id]->setWeight(0);
  452. mFadingOut[id]=false;
  453. mFadingIn[id]=true;
  454. if(reset) mAnims[id]->setTimePosition(0);
  455. }
  456. }
  457. SceneNode* mBodyNode;
  458. SceneNode*node;
  459. SceneNode* mCameraPivot;
  460. SceneNode* mCameraGoal;
  461. SceneNode* mCameraNode;
  462. Real mPivotPitch;
  463. Entity* mBodyEnt;
  464. Entity* mSword1;
  465. Entity* mSword2;
  466. Entity* dra;
  467. RibbonTrail* mSwordTrail;
  468. AnimationState* mAnims[NUM_ANIMS];// master animation list
  469. AnimID mBaseAnimID;// current base (full- or lower-body) animation
  470. AnimID mTopAnimID;// current top (upper-body) animation
  471. bool mFadingIn[NUM_ANIMS];// which animations are fading in
  472. bool mFadingOut[NUM_ANIMS];// which animations are fading out
  473. bool mSwordsDrawn;
  474. Vector3 mKeyDirection;// player's local intended direction based on WASD keys
  475. Vector3 mGoalDirection;// actual intended direction in world-space
  476. Real mVerticalVelocity;// for jumping
  477. Real mTimer;// general timer to see how long animations have been playing
  478. };
  479. #endif

CharacterSample.cpp

  1. #include"SamplePlugin.h"
  2. #include"CharacterSample.h"
  3. usingnamespaceOgre;
  4. usingnamespaceOgreBites;
  5. #ifndef OGRE_STATIC_LIB
  6. SamplePlugin* sp;
  7. Sample* s;
  8. Sample* e;
  9. //Sample* s1;
  10. extern"C"_OgreSampleExportvoid dllStartPlugin()
  11. {
  12. s =newSample_Character;
  13. //s1 = new Sample_Character;
  14. //e = new Sample_SkeletalAnimation;
  15. sp = OGRE_NEW SamplePlugin(s->getInfo()["Title"]+" Sample");
  16. sp->addSample(s);
  17. //sp->addSample(s1);
  18. //sp->addSample(e);
  19. Root::getSingleton().installPlugin(sp);
  20. }
  21. extern"C"_OgreSampleExportvoid dllStopPlugin()
  22. {
  23. Root::getSingleton().uninstallPlugin(sp);
  24. OGRE_DELETE sp;
  25. delete s;
  26. //delete s1;
  27. //delete e;
  28. }
  29. #endif

参考资料:

中文OGRE参考网站
OGRE官方文档(英文)
OGRE3D游戏开发框架指南(中文电子书)
[PR]Apress.Pro.OGRE.3D.Programming(英文电子书)

posted @ 2014-04-13 22:28  YUAN园  阅读(738)  评论(0编辑  收藏  举报