码迷,mamicode.com
首页 > 其他好文 > 详细

HiCharacter

时间:2014-09-01 19:22:53      阅读:347      评论:0      收藏:0      [点我收藏+]

标签:android   style   blog   http   os   io   ar   for   2014   

bubuko.com,布布扣

  • SinbadCharacterController.h
  • /***************************************************
        ©2014 Pf_D. All rights reserved.
    ***************************************************/
    #pragma once
    #include "OGRE\Ogre.h"
    #include "OIS\OIS.h"
    
    using namespace Ogre;
    
    #define NUM_ANIMS 13           // number of animations the character has
    #define CHAR_HEIGHT 5          // height of character‘s center of mass(质心) above ground
    #define CAM_HEIGHT 2           // height of camera above character‘s center of mass
    #define RUN_SPEED 17           // character running speed in units per second
    #define TURN_SPEED 500.0f      // character turning in degrees per second
    #define ANIM_FADE_SPEED 7.5f   // animation crossfade speed in % of full weight per second
    #define JUMP_ACCEL 30.0f       // character jump acceleration in upward units per squared second
    #define GRAVITY 90.0f          // gravity in downward units per squared second
    
    class SinbadCharacterController
    {
    private:
    
    	// all the animations our character has, and a null ID
    	// some of these affect separate body parts and will be blended together
    	enum AnimID
    	{
    		ANIM_IDLE_BASE,
    		ANIM_IDLE_TOP,
    		ANIM_RUN_BASE,
    		ANIM_RUN_TOP,
    		ANIM_HANDS_CLOSED,
    		ANIM_HANDS_RELAXED,
    		ANIM_DRAW_SWORDS,
    		ANIM_SLICE_VERTICAL,
    		ANIM_SLICE_HORIZONTAL,
    		ANIM_DANCE,
    		ANIM_JUMP_START,
    		ANIM_JUMP_LOOP,
    		ANIM_JUMP_END,
    		ANIM_NONE
    	};
    
    public:
    	
    	SinbadCharacterController(Camera* cam)
    	{
    		setupBody(cam->getSceneManager());
    		setupCamera(cam);
    		setupAnimations();
    	}
    
    	void addTime(Real deltaTime)
    	{
    		updateBody(deltaTime);
    		updateAnimations(deltaTime);
    		updateCamera(deltaTime);
    	}
    
    	void injectKeyDown(const OIS::KeyEvent& evt)
    	{
    		if (evt.key == OIS::KC_Q && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
    		{
    			// take swords out (or put them back, since it‘s the same animation but reversed)
    			setTopAnimation(ANIM_DRAW_SWORDS, true);
    			mTimer = 0;
    		}
    		else if (evt.key == OIS::KC_E && !mSwordsDrawn)
    		{
    			if (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP)
    			{
    				// start dancing
    				setBaseAnimation(ANIM_DANCE, true);
    				setTopAnimation(ANIM_NONE);
    				// disable hand animation because the dance controls hands
    				mAnims[ANIM_HANDS_RELAXED]->setEnabled(false);
    			}
    			else if (mBaseAnimID == ANIM_DANCE)
    			{
    				// stop dancing
    				setBaseAnimation(ANIM_IDLE_BASE);
    				setTopAnimation(ANIM_IDLE_TOP);
    				// re-enable hand animation
    				mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
    			}
    		}
    
    		// keep track of the player‘s intended direction
    		else if (evt.key == OIS::KC_W) mKeyDirection.z = -1;
    		else if (evt.key == OIS::KC_A) mKeyDirection.x = -1;
    		else if (evt.key == OIS::KC_S) mKeyDirection.z = 1;
    		else if (evt.key == OIS::KC_D) mKeyDirection.x = 1;
    
    		else if (evt.key == OIS::KC_SPACE && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
    		{
    			// jump if on ground
    			setBaseAnimation(ANIM_JUMP_START, true);
    			setTopAnimation(ANIM_NONE);
    			mTimer = 0;
    		}
    
    		if (!mKeyDirection.isZeroLength() && mBaseAnimID == ANIM_IDLE_BASE)
    		{
    			// start running if not already moving and the player wants to move
    			setBaseAnimation(ANIM_RUN_BASE, true);
    			if (mTopAnimID == ANIM_IDLE_TOP) setTopAnimation(ANIM_RUN_TOP, true);
    		}
    	}
    
    	void injectKeyUp(const OIS::KeyEvent& evt)
    	{
    		// keep track of the player‘s intended direction
    		if (evt.key == OIS::KC_W && mKeyDirection.z == -1) mKeyDirection.z = 0;
    		else if (evt.key == OIS::KC_A && mKeyDirection.x == -1) mKeyDirection.x = 0;
    		else if (evt.key == OIS::KC_S && mKeyDirection.z == 1) mKeyDirection.z = 0;
    		else if (evt.key == OIS::KC_D && mKeyDirection.x == 1) mKeyDirection.x = 0;
    
    		if (mKeyDirection.isZeroLength() && mBaseAnimID == ANIM_RUN_BASE)
    		{
    			// stop running if already moving and the player doesn‘t want to move
    			setBaseAnimation(ANIM_IDLE_BASE);
    			if (mTopAnimID == ANIM_RUN_TOP) setTopAnimation(ANIM_IDLE_TOP);
    		}
    	}
    
    #if (OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS) || (OGRE_PLATFORM == OGRE_PLATFORM_ANDROID)
    	void injectMouseMove(const OIS::MultiTouchEvent& evt)
    	{
    		// update camera goal based on mouse movement
    		updateCameraGoal(-0.05f * evt.state.X.rel, -0.05f * evt.state.Y.rel, -0.0005f * evt.state.Z.rel);
    	}
    
    	void injectMouseDown(const OIS::MultiTouchEvent& evt)
    	{
    		if (mSwordsDrawn && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
    		{
    			// if swords are out, and character‘s not doing something weird, then SLICE!
                setTopAnimation(ANIM_SLICE_VERTICAL, true);
    			mTimer = 0;
    		}
    	}
    #else
    	void injectMouseMove(const OIS::MouseEvent& evt)
    	{
    		// update camera goal based on mouse movement
    		updateCameraGoal(-0.05f * evt.state.X.rel, -0.05f * evt.state.Y.rel, -0.0005f * evt.state.Z.rel);
    	}
    
    	void injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
    	{
    		if (mSwordsDrawn && (mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
    		{
    			// if swords are out, and character‘s not doing something weird, then SLICE!
    			if (id == OIS::MB_Left) setTopAnimation(ANIM_SLICE_VERTICAL, true);
    			else if (id == OIS::MB_Right) setTopAnimation(ANIM_SLICE_HORIZONTAL, true);
    			mTimer = 0;
    		}
    	}
    #endif
    
    private:
    
    	void setupBody(SceneManager* sceneMgr)
    	{
    		// create main model
    		// 让角色踩在平面上
    		mBodyNode = sceneMgr->getRootSceneNode()->createChildSceneNode(Vector3::UNIT_Y * CHAR_HEIGHT);
    		mBodyEnt = sceneMgr->createEntity("SinbadBody", "Sinbad.mesh");
    		mBodyNode->attachObject(mBodyEnt);
    
    		// create swords and attach to sheath
    		LogManager::getSingleton().logMessage("Creating swords");
    		mSword1 = sceneMgr->createEntity("SinbadSword1", "Sword.mesh");
    		mSword2 = sceneMgr->createEntity("SinbadSword2", "Sword.mesh");
    		mBodyEnt->attachObjectToBone("Sheath.L", mSword1);
    		mBodyEnt->attachObjectToBone("Sheath.R", mSword2);
    
    		LogManager::getSingleton().logMessage("Creating the chains");
    		// create a couple of ribbon trails for the swords, just for fun
    		NameValuePairList params;
    		params["numberOfChains"] = "2";
    		params["maxElements"] = "80";
    		mSwordTrail = (RibbonTrail*)sceneMgr->createMovableObject("RibbonTrail", &params);
    		mSwordTrail->setMaterialName("Examples/LightRibbonTrail");
    		mSwordTrail->setTrailLength(20);
    		mSwordTrail->setVisible(false);
    		sceneMgr->getRootSceneNode()->attachObject(mSwordTrail);
    
    
    		for (int i = 0; i < 2; i++)
    		{
    			mSwordTrail->setInitialColour(i, 1, 0.8, 0);
    			mSwordTrail->setColourChange(i, 0.75, 1.25, 1.25, 1.25);
    			mSwordTrail->setWidthChange(i, 1);
    			mSwordTrail->setInitialWidth(i, 0.5);
    		}
    
    		mKeyDirection = Vector3::ZERO;
    		mVerticalVelocity = 0;
    	}
    
    	void setupAnimations()
    	{
    		// this is very important due to the nature of the exported animations
    		mBodyEnt->getSkeleton()->setBlendMode(ANIMBLEND_CUMULATIVE);
    
    		String animNames[] =
    		{"IdleBase", "IdleTop", "RunBase", "RunTop", "HandsClosed", "HandsRelaxed", "DrawSwords",
    		"SliceVertical", "SliceHorizontal", "Dance", "JumpStart", "JumpLoop", "JumpEnd"};
    
    		// populate our animation list
    		for (int i = 0; i < NUM_ANIMS; i++)
    		{
    			mAnims[i] = mBodyEnt->getAnimationState(animNames[i]);
    			mAnims[i]->setLoop(true);
    			mFadingIn[i] = false;
    			mFadingOut[i] = false;
    		}
    
    		// start off in the idle state (top and bottom together)
    		setBaseAnimation(ANIM_IDLE_BASE);
    		setTopAnimation(ANIM_IDLE_TOP);
    
    		// relax the hands since we‘re not holding anything
    		mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
    
    		mSwordsDrawn = false;
    	}
    
    	void setupCamera(Camera* cam)
    	{
    		// create a pivot at roughly the character‘s shoulder
    		mCameraPivot = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
    		// this is where the camera should be soon, and it spins around the pivot
    		mCameraGoal = mCameraPivot->createChildSceneNode(Vector3(0, 0, 15));
    		// this is where the camera actually is
    		mCameraNode = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
    		mCameraNode->setPosition(mCameraPivot->getPosition() + mCameraGoal->getPosition());
    
    		mCameraPivot->setFixedYawAxis(true);
    		mCameraGoal->setFixedYawAxis(true);
    		mCameraNode->setFixedYawAxis(true);
    
    		// our model is quite small, so reduce the clipping planes
    		cam->setNearClipDistance(0.1);
    		cam->setFarClipDistance(100);
    		mCameraNode->attachObject(cam);
    
    		mPivotPitch = 0;
    	}
    
    	void updateBody(Real deltaTime)
    	{
    		mGoalDirection = Vector3::ZERO;   // we will calculate this
    
    		if (mKeyDirection != Vector3::ZERO && mBaseAnimID != ANIM_DANCE)
    		{
    			// calculate actually goal direction in world based on player‘s key directions
    			mGoalDirection += mKeyDirection.z * mCameraNode->getOrientation().zAxis();
    			mGoalDirection += mKeyDirection.x * mCameraNode->getOrientation().xAxis();
    			mGoalDirection.y = 0;
    			mGoalDirection.normalise();
    
    			Quaternion toGoal = mBodyNode->getOrientation().zAxis().getRotationTo(mGoalDirection);
    
    			// calculate how much the character has to turn to face goal direction
    			Real yawToGoal = toGoal.getYaw().valueDegrees();
    			// this is how much the character CAN turn this frame
    			Real yawAtSpeed = yawToGoal / Math::Abs(yawToGoal) * deltaTime * TURN_SPEED;
    			// reduce "turnability" if we‘re in midair
    			if (mBaseAnimID == ANIM_JUMP_LOOP) yawAtSpeed *= 0.2f;
    
    			// turn as much as we can, but not more than we need to
    			if (yawToGoal < 0) yawToGoal = std::min<Real>(0, std::max<Real>(yawToGoal, yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, yawAtSpeed, 0);
    			else if (yawToGoal > 0) yawToGoal = std::max<Real>(0, std::min<Real>(yawToGoal, yawAtSpeed)); //yawToGoal = Math::Clamp<Real>(yawToGoal, 0, yawAtSpeed);
    			
    			mBodyNode->yaw(Degree(yawToGoal));
    
    			// move in current body direction (not the goal direction)
    			mBodyNode->translate(0, 0, deltaTime * RUN_SPEED * mAnims[mBaseAnimID]->getWeight(),
    				Node::TS_LOCAL);
    		}
    
    		if (mBaseAnimID == ANIM_JUMP_LOOP)
    		{
    			// if we‘re jumping, add a vertical offset too, and apply gravity
    			mBodyNode->translate(0, mVerticalVelocity * deltaTime, 0, Node::TS_LOCAL);
    			mVerticalVelocity -= GRAVITY * deltaTime;
    			
    			Vector3 pos = mBodyNode->getPosition();
    			if (pos.y <= CHAR_HEIGHT)
    			{
    				// if we‘ve hit the ground, change to landing state
    				pos.y = CHAR_HEIGHT;
    				mBodyNode->setPosition(pos);
    				setBaseAnimation(ANIM_JUMP_END, true);
    				mTimer = 0;
    			}
    		}
    	}
    
    	void updateAnimations(Real deltaTime)
    	{
    		Real baseAnimSpeed = 1;
    		Real topAnimSpeed = 1;
    
    		mTimer += deltaTime;
    
    		if (mTopAnimID == ANIM_DRAW_SWORDS)
    		{
    			// flip the draw swords animation if we need to put it back
    			topAnimSpeed = mSwordsDrawn ? -1 : 1;
    
    			// half-way through the animation is when the hand grasps the handles...
    			if (mTimer >= mAnims[mTopAnimID]->getLength() / 2 &&
    				mTimer - deltaTime < mAnims[mTopAnimID]->getLength() / 2)
    			{
    				// so transfer the swords from the sheaths to the hands
    				mBodyEnt->detachAllObjectsFromBone();
    				mBodyEnt->attachObjectToBone(mSwordsDrawn ? "Sheath.L" : "Handle.L", mSword1);
    				mBodyEnt->attachObjectToBone(mSwordsDrawn ? "Sheath.R" : "Handle.R", mSword2);
    				// change the hand state to grab or let go
    				mAnims[ANIM_HANDS_CLOSED]->setEnabled(!mSwordsDrawn);
    				mAnims[ANIM_HANDS_RELAXED]->setEnabled(mSwordsDrawn);
    
    				// toggle sword trails
    				if (mSwordsDrawn)
    				{
    					mSwordTrail->setVisible(false);
    					mSwordTrail->removeNode(mSword1->getParentNode());
    					mSwordTrail->removeNode(mSword2->getParentNode());
    				}
    				else
    				{
    					mSwordTrail->setVisible(true);
    					mSwordTrail->addNode(mSword1->getParentNode());
    					mSwordTrail->addNode(mSword2->getParentNode());
    				}
    			}
    
    			if (mTimer >= mAnims[mTopAnimID]->getLength())
    			{
    				// animation is finished, so return to what we were doing before
    				if (mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
    				else
    				{
    					setTopAnimation(ANIM_RUN_TOP);
    					mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
    				}
    				mSwordsDrawn = !mSwordsDrawn;
    			}
    		}
    		else if (mTopAnimID == ANIM_SLICE_VERTICAL || mTopAnimID == ANIM_SLICE_HORIZONTAL)
    		{
    			if (mTimer >= mAnims[mTopAnimID]->getLength())
    			{
    				// animation is finished, so return to what we were doing before
    				if (mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
    				else
    				{
    					setTopAnimation(ANIM_RUN_TOP);
    					mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
    				}
    			}
    
    			// don‘t sway hips from side to side when slicing. that‘s just embarrassing.
    			if (mBaseAnimID == ANIM_IDLE_BASE) baseAnimSpeed = 0;
    		}
    		else if (mBaseAnimID == ANIM_JUMP_START)
    		{
    			if (mTimer >= mAnims[mBaseAnimID]->getLength())
    			{
    				// takeoff animation finished, so time to leave the ground!
    				setBaseAnimation(ANIM_JUMP_LOOP, true);
    				// apply a jump acceleration to the character
    				mVerticalVelocity = JUMP_ACCEL;
    			}
    		}
    		else if (mBaseAnimID == ANIM_JUMP_END)
    		{
    			if (mTimer >= mAnims[mBaseAnimID]->getLength())
    			{
    				// safely landed, so go back to running or idling
    				if (mKeyDirection == Vector3::ZERO)
    				{
    					setBaseAnimation(ANIM_IDLE_BASE);
    					setTopAnimation(ANIM_IDLE_TOP);
    				}
    				else
    				{
    					setBaseAnimation(ANIM_RUN_BASE, true);
    					setTopAnimation(ANIM_RUN_TOP, true);
    				}
    			}
    		}
    
    		// increment the current base and top animation times
    		if (mBaseAnimID != ANIM_NONE) mAnims[mBaseAnimID]->addTime(deltaTime * baseAnimSpeed);
    		if (mTopAnimID != ANIM_NONE) mAnims[mTopAnimID]->addTime(deltaTime * topAnimSpeed);
    
    		// apply smooth transitioning between our animations
    		fadeAnimations(deltaTime);
    	}
    
    	void fadeAnimations(Real deltaTime)
    	{
    		for (int i = 0; i < NUM_ANIMS; i++)
    		{
    			if (mFadingIn[i])
    			{
    				// slowly fade this animation in until it has full weight
    				Real newWeight = mAnims[i]->getWeight() + deltaTime * ANIM_FADE_SPEED;
    				mAnims[i]->setWeight(Math::Clamp<Real>(newWeight, 0, 1));
    				if (newWeight >= 1) mFadingIn[i] = false;
    			}
    			else if (mFadingOut[i])
    			{
    				// slowly fade this animation out until it has no weight, and then disable it
    				Real newWeight = mAnims[i]->getWeight() - deltaTime * ANIM_FADE_SPEED;
    				mAnims[i]->setWeight(Math::Clamp<Real>(newWeight, 0, 1));
    				if (newWeight <= 0)
    				{
    					mAnims[i]->setEnabled(false);
    					mFadingOut[i] = false;
    				}
    			}
    		}
    	}
    
    	void updateCamera(Real deltaTime)
    	{
    		// place the camera pivot roughly at the character‘s shoulder
    		mCameraPivot->setPosition(mBodyNode->getPosition() + Vector3::UNIT_Y * CAM_HEIGHT);
    		// move the camera smoothly to the goal
    		Vector3 goalOffset = mCameraGoal->_getDerivedPosition() - mCameraNode->getPosition();
    		mCameraNode->translate(goalOffset * deltaTime * 9.0f);
    		// always look at the pivot
    		mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(), Node::TS_WORLD);
    	}
    
    	void updateCameraGoal(Real deltaYaw, Real deltaPitch, Real deltaZoom)
    	{
    		mCameraPivot->yaw(Degree(deltaYaw), Node::TS_WORLD);
    
    		// bound the pitch
    		if (!(mPivotPitch + deltaPitch > 25 && deltaPitch > 0) &&
    			!(mPivotPitch + deltaPitch < -60 && deltaPitch < 0))
    		{
    			mCameraPivot->pitch(Degree(deltaPitch), Node::TS_LOCAL);
    			mPivotPitch += deltaPitch;
    		}
    		
    		Real dist = mCameraGoal->_getDerivedPosition().distance(mCameraPivot->_getDerivedPosition());
    		Real distChange = deltaZoom * dist;
    
    		// bound the zoom
    		if (!(dist + distChange < 8 && distChange < 0) &&
    			!(dist + distChange > 25 && distChange > 0))
    		{
    			mCameraGoal->translate(0, 0, distChange, Node::TS_LOCAL);
    		}
    	}
    
    	void setBaseAnimation(AnimID id, bool reset = false)
    	{
    		if (mBaseAnimID >= 0 && mBaseAnimID < NUM_ANIMS)
    		{
    			// if we have an old animation, fade it out
    			mFadingIn[mBaseAnimID] = false;
    			mFadingOut[mBaseAnimID] = true;
    		}
    
    		mBaseAnimID = id;
    
    		if (id != ANIM_NONE)
    		{
    			// if we have a new animation, enable it and fade it in
    			mAnims[id]->setEnabled(true);
    			mAnims[id]->setWeight(0);
    			mFadingOut[id] = false;
    			mFadingIn[id] = true;
    			if (reset) mAnims[id]->setTimePosition(0);
    		}
    	}
    
    	void setTopAnimation(AnimID id, bool reset = false)
    	{
    		if (mTopAnimID >= 0 && mTopAnimID < NUM_ANIMS)
    		{
    			// if we have an old animation, fade it out
    			mFadingIn[mTopAnimID] = false;
    			mFadingOut[mTopAnimID] = true;
    		}
    
    		mTopAnimID = id;
    
    		if (id != ANIM_NONE)
    		{
    			// if we have a new animation, enable it and fade it in
    			mAnims[id]->setEnabled(true);
    			mAnims[id]->setWeight(0);
    			mFadingOut[id] = false;
    			mFadingIn[id] = true;
    			if (reset) mAnims[id]->setTimePosition(0);
    		}
    	}
    
    	SceneNode* mBodyNode;
    	SceneNode* mCameraPivot;
    	SceneNode* mCameraGoal;
    	SceneNode* mCameraNode;
    	Real mPivotPitch;
    	Entity* mBodyEnt;
    	Entity* mSword1;
    	Entity* mSword2;
    	RibbonTrail* mSwordTrail;
    	AnimationState* mAnims[NUM_ANIMS];    // master animation list
    	AnimID mBaseAnimID;                   // current base (full- or lower-body) animation
    	AnimID mTopAnimID;                    // current top (upper-body) animation
    	bool mFadingIn[NUM_ANIMS];            // which animations are fading in
    	bool mFadingOut[NUM_ANIMS];           // which animations are fading out
    	bool mSwordsDrawn;
    	Vector3 mKeyDirection;      // player‘s local intended direction based on WASD keys
    	Vector3 mGoalDirection;     // actual intended direction in world-space
    	Real mVerticalVelocity;     // for jumping
    	Real mTimer;                // general timer to see how long animations have been playing
    };
    
  • Graphics.h
  • /***************************************************
        ©2014 Pf_D. All rights reserved.
    ***************************************************/
    #pragma once
    #include "OGRE\Ogre.h"
    #include "OIS\OIS.h"
           
    enum CameraStyle
    {
        CS_FREELOOK,
        CS_ORBIT,
        CS_MANUAL
    };
           
    class cCameraManager
    {
    private:
        Ogre::Camera *mCamera;
        CameraStyle mStyle;
        Ogre::SceneNode *mTarget;
        bool mOrbiting;
        bool mZooming;
        Ogre::Real mTopSpeed;
        Ogre::Vector3 mVelocity;
        bool mGoingForward;
        bool mGoingBack;
        bool mGoingLeft;
        bool mGoingRight;
        bool mGoingUp;
        bool mGoingDown;
        bool mFastMove;
           
    public:
        cCameraManager(Ogre::Camera *cam);
           
        void setCamera(Ogre::Camera *cam);
        Ogre::Camera *getCamera();
           
        void manualStop();
           
        void setStyle(CameraStyle style);
        CameraStyle getStyle();
           
        void setYawPitchDist(Ogre::Radian yaw, Ogre::Radian pitch, Ogre::Real dist);
           
        void setTarget(Ogre::SceneNode *target);
        Ogre::SceneNode *getTarget();
           
        void setTopSpeed(Ogre::Real topSpeed);
        Ogre::Real getTopSpeed();
           
        bool frameRenderingQueued(const Ogre::FrameEvent& evt);
           
        // Processes key press for free-look style movement.
        void injectKeyDown(const OIS::KeyEvent &evt);
        void injectKeyUp(const OIS::KeyEvent &evt);
           
        // Processes mouse movement differently for each style.
        void injectMouseMove(const OIS::MouseEvent &evt);
           
        // Processes mouse presses. Only applies for orbit style.
        // Left button is for orbiting, and right button is for zooming.
        void injectMouseDown(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
        void injectMouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
    };
    
  • Graphics.cpp
  • /***************************************************
        ©2014 Pf_D. All rights reserved.
    ***************************************************/
    #include "Graphics.h"
           
    cCameraManager::cCameraManager(Ogre::Camera *cam)
        :mCamera(0),
        mStyle(CameraStyle::CS_FREELOOK),
        mTarget(0),
        mOrbiting(false),
        mZooming(false),
        mTopSpeed(150),
        mVelocity(Ogre::Vector3::ZERO),
        mGoingForward(false),
        mGoingBack(false),
        mGoingLeft(false),
        mGoingRight(false),
        mGoingUp(false),
        mGoingDown(false),
        mFastMove(false)
    {
        setCamera(cam);
        setStyle(CS_FREELOOK);
    }
           
    void cCameraManager::setCamera(Ogre::Camera *cam)
    {
        mCamera = cam;
    }
           
    Ogre::Camera *cCameraManager::getCamera()
    {
        return mCamera;
    }
           
    void cCameraManager::setYawPitchDist(Ogre::Radian yaw, Ogre::Radian pitch, Ogre::Real dist)
    {
        mCamera->setPosition(mTarget->_getDerivedPosition());
        mCamera->setOrientation(mTarget->_getDerivedOrientation());
        mCamera->yaw(yaw);
        mCamera->pitch(pitch);
        mCamera->moveRelative(Ogre::Vector3(0, 0, dist));
    }
           
    void cCameraManager::setTarget(Ogre::SceneNode *target)
    {
        if(target != mTarget)
        {
            mTarget = target;
            if(target)
            {
                setYawPitchDist(Ogre::Degree(0), Ogre::Degree(15), 150);
                mCamera->setAutoTracking(true, mTarget);
            }
            else
                mCamera->setAutoTracking(false);
        }
    }
               
    Ogre::SceneNode *cCameraManager::getTarget()
    {
        return mTarget;
    }
           
    void cCameraManager::manualStop()
    {
        if(mStyle == CS_FREELOOK)
        {
            mVelocity = Ogre::Vector3::ZERO;
            mGoingForward = false;
            mGoingBack = false;
            mGoingLeft = false;
            mGoingRight = false;
            mGoingUp = false;
            mGoingDown = false;
        }
    }
           
    void cCameraManager::setStyle(CameraStyle style)
    {
        if(mStyle != CS_ORBIT && style == CS_ORBIT)
        {
            setTarget(mTarget ? mTarget : mCamera->getSceneManager()->getRootSceneNode());
            mCamera->setFixedYawAxis(true);
            manualStop();
            setYawPitchDist(Ogre::Degree(0), Ogre::Degree(15), 150);
        }
        else if(mStyle != CS_FREELOOK && style == CS_FREELOOK)
        {
            mCamera->setAutoTracking(false);
            mCamera->setFixedYawAxis(true);
        }
        else if(mStyle != CS_MANUAL && style == CS_MANUAL)
        {
            mCamera->setAutoTracking(false);
            manualStop();
        }
        mStyle = style;
    }
           
    CameraStyle cCameraManager::getStyle()
    {
        return mStyle;
    }
           
    void cCameraManager::setTopSpeed(Ogre::Real topSpeed)
    {
        mTopSpeed = topSpeed;
    }
           
    Ogre::Real cCameraManager::getTopSpeed()
    {
        return mTopSpeed;
    }
           
    bool cCameraManager::frameRenderingQueued(const Ogre::FrameEvent& evt)
    {
        if (mStyle == CS_FREELOOK)
        {
            // build our acceleration vector based on keyboard input composite
            Ogre::Vector3 accel = Ogre::Vector3::ZERO;
            if (mGoingForward) accel += mCamera->getDirection();
            if (mGoingBack) accel -= mCamera->getDirection();
            if (mGoingRight) accel += mCamera->getRight();
            if (mGoingLeft) accel -= mCamera->getRight();
            if (mGoingUp) accel += mCamera->getUp();
            if (mGoingDown) accel -= mCamera->getUp();
           
            // if accelerating, try to reach top speed in a certain time
            Ogre::Real topSpeed = mFastMove ? mTopSpeed * 20 : mTopSpeed;
            if (accel.squaredLength() != 0)
            {
                accel.normalise();
                mVelocity += accel * topSpeed * evt.timeSinceLastFrame * 10;
            }
            // if not accelerating, try to stop in a certain time
            else mVelocity -= mVelocity * evt.timeSinceLastFrame * 10;
           
            Ogre::Real tooSmall = std::numeric_limits<Ogre::Real>::epsilon();
           
            // keep camera velocity below top speed and above epsilon
            if (mVelocity.squaredLength() > topSpeed * topSpeed)
            {
                mVelocity.normalise();
                mVelocity *= topSpeed;
            }
            else if (mVelocity.squaredLength() < tooSmall * tooSmall)
                mVelocity = Ogre::Vector3::ZERO;
           
            if (mVelocity != Ogre::Vector3::ZERO) mCamera->move(mVelocity * evt.timeSinceLastFrame);
        }
           
        return true;
    }
           
    void cCameraManager::injectKeyDown(const OIS::KeyEvent &evt)
    {
        if(mStyle != CS_FREELOOK)
            return;
        if (evt.key == OIS::KC_W || evt.key == OIS::KC_UP) mGoingForward = true;
        else if (evt.key == OIS::KC_S || evt.key == OIS::KC_DOWN) mGoingBack = true;
        else if (evt.key == OIS::KC_A || evt.key == OIS::KC_LEFT) mGoingLeft = true;
        else if (evt.key == OIS::KC_D || evt.key == OIS::KC_RIGHT) mGoingRight = true;
        else if (evt.key == OIS::KC_PGUP) mGoingUp = true;
        else if (evt.key == OIS::KC_PGDOWN) mGoingDown = true;
        else if (evt.key == OIS::KC_LSHIFT) mFastMove = true;
    }
           
    void cCameraManager::injectKeyUp(const OIS::KeyEvent &evt)
    {
        if(mStyle != CS_FREELOOK)
            return;
        if (evt.key == OIS::KC_W || evt.key == OIS::KC_UP) mGoingForward = false;
        else if (evt.key == OIS::KC_S || evt.key == OIS::KC_DOWN) mGoingBack = false;
        else if (evt.key == OIS::KC_A || evt.key == OIS::KC_LEFT) mGoingLeft = false;
        else if (evt.key == OIS::KC_D || evt.key == OIS::KC_RIGHT) mGoingRight = false;
        else if (evt.key == OIS::KC_PGUP) mGoingUp = false;
        else if (evt.key == OIS::KC_PGDOWN) mGoingDown = false;
        else if (evt.key == OIS::KC_LSHIFT) mFastMove = false;
    }
           
    void cCameraManager::injectMouseMove(const OIS::MouseEvent &evt)
    {
        if (mStyle == CS_ORBIT)
        {
            Ogre::Real dist = (mCamera->getPosition() - mTarget->_getDerivedPosition()).length();
           
            if (mOrbiting)   // yaw around the target, and pitch locally
            {
                mCamera->setPosition(mTarget->_getDerivedPosition());
           
                mCamera->yaw(Ogre::Degree(-evt.state.X.rel * 0.25f));
                mCamera->pitch(Ogre::Degree(-evt.state.Y.rel * 0.25f));
           
                mCamera->moveRelative(Ogre::Vector3(0, 0, dist));
           
                // don‘t let the camera go over the top or around the bottom of the target
            }
            else if (mZooming)  // move the camera toward or away from the target
            {
                // the further the camera is, the faster it moves
                mCamera->moveRelative(Ogre::Vector3(0, 0, evt.state.Y.rel * 0.004f * dist));
            }
            else if (evt.state.Z.rel != 0)  // move the camera toward or away from the target
            {
                // the further the camera is, the faster it moves
                mCamera->moveRelative(Ogre::Vector3(0, 0, -evt.state.Z.rel * 0.0008f * dist));
            }
        }
        else if (mStyle == CS_FREELOOK)
        {
            mCamera->yaw(Ogre::Degree(-evt.state.X.rel * 0.15f));
            mCamera->pitch(Ogre::Degree(-evt.state.Y.rel * 0.15f));
        }
    }
           
    void cCameraManager::injectMouseDown(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
    {
        if (mStyle == CS_ORBIT)
        {
            if (id == OIS::MB_Left) mOrbiting = true;
            else if (id == OIS::MB_Right) mZooming = true;
        }
    }
           
    void cCameraManager::injectMouseUp(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
    {
        if (mStyle == CS_ORBIT)
        {
            if (id == OIS::MB_Left) mOrbiting = false;
            else if (id == OIS::MB_Right) mZooming = false;
        }
    }
    
  • System.h
  • /***************************************************
        ©2014 Pf_D. All rights reserved.
    ***************************************************/
    #pragma once
    #include "Graphics.h"
    #include "OGRE\Ogre.h"
    #include "OIS\OIS.h"
    #include "MyGUI.h"
    #include "MyGUI_OgrePlatform.h"
         
    class cApplication : public Ogre::FrameListener, public OIS::KeyListener, public OIS::MouseListener
    {
    protected:
        MyGUI::Gui          *mGUI;
        MyGUI::OgrePlatform *mPlatform;
            
        Ogre::Root          *mRoot;
        Ogre::RenderWindow  *mWindow;
        Ogre::SceneManager  *mSceneMgr;
        Ogre::Camera        *mCamera;
        Ogre::Viewport      *mVp;
         
        cCameraManager      *mCameraMgr;
        OIS::InputManager   *mInputMgr;
        OIS::Keyboard       *mKeyboard;
        OIS::Mouse          *mMouse;
        bool mDragLook;
        
    public:
        cApplication()
            :mDragLook(false)
        {
        }
       
        virtual bool frameStarted(const Ogre::FrameEvent &evt);
        virtual bool frameRenderingQueued(const Ogre::FrameEvent &evt);
        virtual bool frameEnded(const Ogre::FrameEvent &evt);
           
        virtual bool keyPressed(const OIS::KeyEvent &arg);
        virtual bool keyReleased(const OIS::KeyEvent &arg);
            
        virtual bool mouseMoved(const OIS::MouseEvent &arg);
        virtual bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id);
        virtual bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id);
         
        virtual void setupResources();
        virtual void createInput();
        virtual void chooseSceneMgr();
        virtual void setupView();
        virtual void loadResources();
        virtual void createScene() {}
           
        bool setup();
        void go();
         
        void setDragLook(bool enabled);
    };
    
  • System.cpp
  • /***************************************************
        ©2014 Pf_D. All rights reserved.
    ***************************************************/
    #include "System.h"
         
    bool cApplication::frameStarted(const Ogre::FrameEvent &evt)
    {
        mKeyboard->capture();
        mMouse->capture();
        return true;
    }
           
    bool cApplication::frameRenderingQueued(const Ogre::FrameEvent &evt)
    {
        mCameraMgr->frameRenderingQueued(evt);
        return true;
    }
           
    bool cApplication::frameEnded(const Ogre::FrameEvent &evt)
    {
        return true;
    }
          
    bool cApplication::keyPressed(const OIS::KeyEvent &arg)
    {
        if(arg.key == OIS::KC_ESCAPE)
            exit(0);
        MyGUI::InputManager::getInstance().injectKeyPress(
            MyGUI::KeyCode::Enum(arg.key), arg.text);
        mCameraMgr->injectKeyDown(arg);
        // ...
        return true;
    }
           
    bool cApplication::keyReleased(const OIS::KeyEvent &arg)
    {
        MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(arg.key));
        mCameraMgr->injectKeyUp(arg);
        // ...
        return true;
    }
           
    bool cApplication::mouseMoved( const OIS::MouseEvent &arg )
    {
        bool ret = MyGUI::InputManager::getInstance().injectMouseMove(
            arg.state.X.abs, arg.state.Y.abs, arg.state.Z.abs);
        if(!ret)
            mCameraMgr->injectMouseMove(arg);
        // ...
        return true;
    }
           
    bool cApplication::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
    {
        bool ret = MyGUI::InputManager::getInstance().injectMousePress(
            arg.state.X.abs, arg.state.Y.abs, MyGUI::MouseButton::Enum(id));
        if(!ret)
            mCameraMgr->injectMouseDown(arg, id);
        if(mDragLook && id == OIS::MB_Left) 
        {
            mCameraMgr->setStyle(CS_FREELOOK);
            MyGUI::Gui::getInstance().hidePointer();
        }
        // ...
        return true;
    }
           
    bool cApplication::mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
    {
        bool ret = MyGUI::InputManager::getInstance().injectMouseRelease(
            arg.state.X.abs, arg.state.Y.abs, MyGUI::MouseButton::Enum(id));
        if(!ret)
            mCameraMgr->injectMouseUp(arg, id);
        if(mDragLook && id == OIS::MB_Left) 
        {
            mCameraMgr->setStyle(CS_MANUAL);
            MyGUI::Gui::getInstance().showPointer();
        }
        // ...
        return true;
    }
          
    void cApplication::setupResources()
    {
        Ogre::ConfigFile cf;
    #if OGRE_DEBUG_MODE
        cf.load("resources_d.cfg");
    #else
        cf.load("resources.cfg");
    #endif
        Ogre::ConfigFile::SectionIterator secIter = cf.getSectionIterator();
        Ogre::String secName, typeName, archName;
        while(secIter.hasMoreElements())
        {
            secName = secIter.peekNextKey();
            Ogre::ConfigFile::SettingsMultiMap *settings = secIter.getNext();
            Ogre::ConfigFile::SettingsMultiMap::iterator i;
            for(i=settings->begin(); i!=settings->end(); i++)
            {
                typeName = i->first;
                archName = i->second;
                Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
                    archName, typeName, secName);
            }
        }
    }
          
    void cApplication::createInput()
    {
        OIS::ParamList parameters;
        unsigned int windowHandle = 0;
        std::ostringstream windowHandleString;
        mWindow->getCustomAttribute("WINDOW", &windowHandle);
        windowHandleString << windowHandle;
        parameters.insert(std::make_pair("WINDOW", windowHandleString.str()));
        parameters.insert(std::make_pair("w32_mouse", std::string("DISCL_FOREGROUND")));
        parameters.insert(std::make_pair("w32_mouse", std::string("DISCL_NONEXCLUSIVE")));
        mInputMgr = OIS::InputManager::createInputSystem(parameters);
        mKeyboard = static_cast<OIS::Keyboard*>(mInputMgr->createInputObject(OIS::OISKeyboard, true));
        mKeyboard->setEventCallback(this);
        mMouse = static_cast<OIS::Mouse*>(mInputMgr->createInputObject(OIS::OISMouse, true));
        const OIS::MouseState &mouseState = mMouse->getMouseState();
        mouseState.width = mWindow->getWidth();
        mouseState.height = mWindow->getHeight();
        mMouse->setEventCallback(this);
    }
         
    void cApplication::chooseSceneMgr()
    {
        mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC);
    }
          
    void cApplication::setupView()
    {
        // Create camera
        mCamera = mSceneMgr->createCamera("Camera");
        //mCamera->setPosition(Ogre::Vector3(0, 0, 50));
        //mCamera->lookAt(Ogre::Vector3(0, 0, -300));
        mCamera->setNearClipDistance(5);
        mCameraMgr = new cCameraManager(mCamera);
        // Create viewports
        mVp = mWindow->addViewport(mCamera);
        mVp->setBackgroundColour(Ogre::ColourValue(0, 0, 0));
        mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth())/Ogre::Real(mVp->getActualHeight()));
    }
          
    void cApplication::loadResources()
    {
        Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
    }
          
    bool cApplication::setup()
    {
    #ifndef OGRE_STATIC_LIB
    #if OGRE_DEBUG_MODE
        mRoot = OGRE_NEW Ogre::Root("plugins_d.cfg");
    #else
        mRoot = OGRE_NEW Ogre::Root("plugins.cfg");
    #endif
    #endif
        setupResources();
        if(!mRoot->showConfigDialog())
            return false;
        mWindow = mRoot->initialise(true);
        createInput();
        ShowCursor(false);
        chooseSceneMgr();
        setupView();
        loadResources();
        createScene();
        mRoot->addFrameListener(this);
        return true;
    }
           
    void cApplication::go()
    {
        if(!setup())
            return;
        mRoot->startRendering();
    }
         
    void cApplication::setDragLook(bool enabled)
    {
        if(enabled)
        {
            mCameraMgr->setStyle(CS_MANUAL);
            mDragLook = true;
        }
        else
        {
            mCameraMgr->setStyle(CS_FREELOOK);
            mDragLook = false;
        }
    }
    
  • Main.cpp
  • /***************************************************
        ©2014 Pf_D. All rights reserved.
    ***************************************************/
    #include "System.h"
    #include "SinbadCharacterController.h"
    
    class cMyApplication : public cApplication
    {
    private:
    	SinbadCharacterController* mChara;
    
    public:
    	bool frameRenderingQueued(const Ogre::FrameEvent &evt)
    	{
    		mChara->addTime(evt.timeSinceLastFrame);
    		return cApplication::frameRenderingQueued(evt);
    	}
    
    	bool keyPressed(const OIS::KeyEvent &arg)
    	{
    		mChara->injectKeyDown(arg);
    		return cApplication::keyPressed(arg);
    	}
    
    	bool keyReleased(const OIS::KeyEvent &arg)
    	{
    		mChara->injectKeyUp(arg);
    		return cApplication::keyReleased(arg);
    	}
    
    	bool mouseMoved(const OIS::MouseEvent &arg)
    	{
    		mChara->injectMouseMove(arg);
    		return cApplication::mouseMoved(arg);
    	}
    
    	bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
    	{
    		mChara->injectMouseDown(arg, id);
    		return cApplication::mousePressed(arg, id);
    	}
    
        void createScene()
        {
            // MyGUI
            mPlatform = new MyGUI::OgrePlatform();
            mPlatform->initialise(mWindow, mSceneMgr);
            mGUI = new MyGUI::Gui();
            mGUI->initialise();
    		MyGUI::Gui::getInstance().hidePointer();
    
    		// set background and some fog
    		mVp->setBackgroundColour(Ogre::ColourValue(1.0f, 1.0f, 0.8f));
    		mSceneMgr->setFog(Ogre::FOG_LINEAR, Ogre::ColourValue(1.0f, 1.0f, 0.8f), 0, 15, 100);
    
    		// set shadow properties
    		mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_MODULATIVE);
    		mSceneMgr->setShadowColour(Ogre::ColourValue(0.5, 0.5, 0.5));
    		mSceneMgr->setShadowTextureSize(1024);
    		mSceneMgr->setShadowTextureCount(1);
    
    		// disable default camera control so the character can do its own
    		mCameraMgr->setStyle(CS_MANUAL);
    
    		// use a small amount of ambient lighting
    		mSceneMgr->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.3));
    
    		// add a bright light above the scene
    		Ogre::Light* light = mSceneMgr->createLight();
    		light->setType(Ogre::Light::LT_POINT);
    		light->setPosition(-10, 40, 20);
    		light->setSpecularColour(Ogre::ColourValue::White);
    
    		// create a floor mesh resource
    		Ogre::MeshManager::getSingleton().createPlane("floor", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
    			Ogre::Plane(Ogre::Vector3::UNIT_Y, 0), 100, 100, 10, 10, true, 1, 10, 10, Ogre::Vector3::UNIT_Z);
    
    		// create a floor entity, give it a material, and place it at the origin
            Ogre::Entity* floor = mSceneMgr->createEntity("Floor", "floor");
            floor->setMaterialName("Examples/Rockwall");
    		floor->setCastShadows(false);
            mSceneMgr->getRootSceneNode()->attachObject(floor);
    
    		mChara = new SinbadCharacterController(mCamera);
        }
    };
          
    int main()
    {
        cMyApplication App;
        App.go();
        return 0;
    }
    

HiCharacter

标签:android   style   blog   http   os   io   ar   for   2014   

原文地址:http://www.cnblogs.com/mynamepfd/p/3949769.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!