// Generic Character class class Character { // Attributes ------------------------------------------------------------------------------ protected: SceneNode *mMainNode; // Main character node SceneNode *mSightNode; // "Sight" node - The character is supposed to be looking here SceneNode *mCameraNode; // Node for the chase camera Entity *mEntity; // Character entity SceneManager *mSceneMgr; public: // Methods --------------------------------------------------------------------------------- protected: public: // Updates the character (movement...) virtual void update (Real elapsedTime, InputReader *input) = 0; // The three methods below returns the two camera-related nodes, // and the current position of the character (for the 1st person camera) SceneNode *getSightNode () { return mSightNode; } SceneNode *getCameraNode () { return mCameraNode; } Vector3 getWorldPosition () { return mMainNode->getWorldPosition (); } Entity* getEntity() { return mEntity; } }; // Specialization of the Character class - Our dear Ogre :D class OgreCharacter : public Character { // Attributes ------------------------------------------------------------------------------ protected: String mName; public: // Methods --------------------------------------------------------------------------------- protected: public: OgreCharacter (String name, SceneManager *sceneMgr) { // Setup basic member references mName = name; mSceneMgr = sceneMgr; // Setup basic node structure to handle 3rd person cameras mMainNode = mSceneMgr->getRootSceneNode ()->createChildSceneNode (mName); mSightNode = mMainNode->createChildSceneNode (mName + "_sight", Vector3 (0, 0, 100)); mCameraNode = mMainNode->createChildSceneNode (mName + "_camera", Vector3 (0, 50, -100)); // Give this character a shape :) mEntity = mSceneMgr->createEntity (mName, "butterfly_bones_animated.mesh"); mMainNode->attachObject(mEntity); } ~OgreCharacter () { mMainNode->detachAllObjects (); delete mEntity; mMainNode->removeAndDestroyAllChildren (); mSceneMgr->destroySceneNode (mName); } void update (Real elapsedTime, InputReader *input) { // Handle movement if (input->isKeyDown (KC_W)) { mMainNode->translate (mMainNode->getOrientation () * Vector3 (0, 0, 100.0 * elapsedTime)); } if (input->isKeyDown (KC_S)) { mMainNode->translate (mMainNode->getOrientation () * Vector3 (0, 0, -50.0 * elapsedTime)); } if (input->isKeyDown (KC_PGUP)) { mMainNode->translate (mMainNode->getOrientation () * Vector3 (0, 50 * elapsedTime, 0)); } if (input->isKeyDown (KC_PGDOWN)) { mMainNode->translate (mMainNode->getOrientation () * Vector3 (0, -50 * elapsedTime, 0)); } if (input->isKeyDown (KC_A)) { mMainNode->yaw (Radian (2 * elapsedTime)); } if (input->isKeyDown (KC_D)) { mMainNode->yaw (Radian (-2 * elapsedTime)); } Degree mRotX = Degree(-input->getMouseRelativeX() * 0.13); Degree mRotY = Degree(-input->getMouseRelativeY() * 0.13); mMainNode->yaw(mRotX); mMainNode->pitch(mRotY); } // Change visibility - Useful for 1st person view ;) void setVisible (bool visible) { mMainNode->setVisible (visible); } }; // Our extended camera class class ExtendedCamera { // Attributes ------------------------------------------------------------------------------ protected: SceneNode *mTargetNode; // The camera target SceneNode *mCameraNode; // The camera itself Camera *mCamera; // Ogre camera SceneManager *mSceneMgr; String mName; bool mOwnCamera; // To know if the ogre camera binded has been created outside or inside of this class Real mTightness; // Determines the movement of the camera - 1 means tight movement, while 0 means no movement public: // Methods --------------------------------------------------------------------------------- protected: public: ExtendedCamera (String name, SceneManager *sceneMgr, Camera *camera = 0) { // Basic member references setup mName = name; mSceneMgr = sceneMgr; // Create the camera's node structure mCameraNode = mSceneMgr->getRootSceneNode ()->createChildSceneNode (mName); mTargetNode = mSceneMgr->getRootSceneNode ()->createChildSceneNode (mName + "_target"); mCameraNode->setAutoTracking (true, mTargetNode); // The camera will always look at the camera target mCameraNode->setFixedYawAxis (true); // Needed because of auto tracking // Create our camera if it wasn't passed as a parameter if (camera == 0) { mCamera = mSceneMgr->createCamera (mName); mOwnCamera = true; } else { mCamera = camera; mOwnCamera = false; } mCamera->setFOVy(Radian(Degree(12.0))); // ... and attach the Ogre camera to the camera node mCameraNode->attachObject (mCamera); // Default tightness mTightness = 0.01f; } ~ExtendedCamera () { mCameraNode->detachAllObjects (); if (mOwnCamera) delete mCamera; mSceneMgr->destroySceneNode (mName); mSceneMgr->destroySceneNode (mName + "_target"); } void setFOVy(Ogre::Radian fovy) { mCamera->setFOVy(Radian(Degree(fovy))); } void setTightness (Real tightness) { mTightness = tightness; } Real getTightness () { return mTightness; } Vector3 getCameraPosition () { return mCameraNode->getPosition (); } void instantUpdate (Vector3 cameraPosition, Vector3 targetPosition) { mCameraNode->setPosition (cameraPosition); mTargetNode->setPosition (targetPosition); } void update (Real elapsedTime, Vector3 cameraPosition, Vector3 targetPosition) { // Handle movement Vector3 displacement; displacement = (cameraPosition - mCameraNode->getPosition ()) * mTightness; mCameraNode->translate (displacement); displacement = (targetPosition - mTargetNode->getPosition ()) * mTightness; mTargetNode->translate (displacement); } };