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);
}