DefaultFrameListener.cpp

 

//==========================================================================//
// Ogre A* Example - December 2009                                          //
//                                                                          //
// Author: Daniel Soltyka                                                   //
// E-Mail: dsoltyka [at] gmail [dot] com                                    //
//                                                                          //
// This example demonstrates the A* pathfinding algorithm in a 3D           //
// environment.                                                             //
//                                                                          //
// Modified A* routines based off of A* Algorithm Implementation using STL  //
// by Justin Heyes-Jones.                                                   //
//                                                                          //
// Original Routines can be found at http://www.heyes-jones.com/astar.html  //
//==========================================================================//

#include "DefaultFrameListener.h"

using namespace std;

DefaultFrameListener::DefaultFrameListener(RenderWindow* win, Camera* cam, SceneManager* sm, SceneNode *sn,
					 Entity *ent, WorldMap* map, PathFinder* pathFinder)
					 : ExampleFrameListener(win, cam, false, false), mSceneMgr(sm), mNode(sn), mEntity(ent), mMap(map), mPathFinder(pathFinder)
{
	// set default variables
	mWalkSpeed = 150.0f;
	mDirection = Vector3::ZERO;

	// find our path
	findPath();

	mStartPoint = mWalkList.front(); // get the vector from the front
	mEndPoint = mWalkList.back(); // get the vector from the back
	mWalkList.pop_front(); // remove waypoint from the front

	// position start and end markers
	setStartEnd();

	mNode->setPosition(mStartPoint);
}

// This function is called to start the object moving to the next position in mWalkList.
bool DefaultFrameListener::nextLocation()
{
	if (mWalkList.empty())
		return false;

	mDestination = mWalkList.front(); // get the vector from the front
	mWalkList.pop_front(); // remove from the front

	mDirection = mDestination - mNode->getPosition();
	mDistance = mDirection.normalise();

	return true;
} // nextLocation()

// Per frame logic.  Called before each frame is rendered
bool DefaultFrameListener::frameStarted(const FrameEvent &evt)
{
	if (mEntity)
	{
		if (mDirection == Vector3::ZERO)
		{
			if (nextLocation())
			{
				// set walking anim
				mAnimationState = mEntity->getAnimationState("Walk");
				mAnimationState->setLoop(true);
				mAnimationState->setEnabled(true);

				// set initial rotation
				Vector3 src = mNode->getOrientation() * Vector3::UNIT_X;
				if ((1.0f + src.dotProduct(mDirection)) < 0.0001f)
				{
					mNode->yaw(Degree(180));
				}
				else
				{
					Ogre::Quaternion quat = src.getRotationTo(mDirection);
					mNode->rotate(quat);
				} // else
			}
		}
		else
		{
			Real move = mWalkSpeed * evt.timeSinceLastFrame;
			mDistance -= move;

			if (mDistance <= 0.0f)
			{
				mNode->setPosition(mDestination);
				mDirection = Vector3::ZERO;

				//set animation based on if the robot has another point to walk to
				if (!nextLocation())
				{
					// set idle anim
					mAnimationState = mEntity->getAnimationState("Idle");
					mAnimationState->setLoop(true);
					mAnimationState->setEnabled(true);

					// find a new path
					findPath(&mEndPoint);

					mStartPoint = mWalkList.front(); // get the vector from the front
					mEndPoint = mWalkList.back(); // get the vector from the back
					mWalkList.pop_front(); // remove waypoint from the front

					// position start and end markers
					setStartEnd();
				}
				else
				{
					// rotation code
					Vector3 src = mNode->getOrientation() * Vector3::UNIT_X;
					if ((1.0f + src.dotProduct(mDirection)) < 0.0001f)
					{
						mNode->yaw(Degree(180));
					}
					else
					{
						Ogre::Quaternion quat = src.getRotationTo(mDirection);
						mNode->rotate(quat);
					} // else

				}
			}
			else
			{
				mNode->translate(mDirection * move);
			}
		}

		mAnimationState->addTime(evt.timeSinceLastFrame);
	}

	return ExampleFrameListener::frameStarted(evt);
}

// Generate a new path in our maze
void DefaultFrameListener::findPath()
{
	// create pathfinder
	mPathFinder = new PathFinder(mMap);

	// generate path
	mPathFinder->Run();

	// get path
	mPathFinder->GetResults(&mWalkList);
}

// Generate a new path in our maze using a specified starting point
void DefaultFrameListener::findPath(Vector3 *startingPoint)
{
	// create pathfinder
	mPathFinder = new PathFinder(mMap, startingPoint);

	// generate path
	mPathFinder->Run();

	// get path
	mPathFinder->GetResults(&mWalkList);
}

// Positions the start/end markers at their respective positions
void DefaultFrameListener::setStartEnd()
{
	SceneNode* node;

	node = mSceneMgr->getSceneNode("StartNode");
	node->setPosition(mStartPoint);

	node = mSceneMgr->getSceneNode("EndNode");
	node->setPosition(mEndPoint);
}