Beispiel #1
0
bool Pathfinder::pathfind(std::vector<PathfindingAction>& path)
{
#if 0
	pout << "Actor " << actor->getObjId();

	if (targetitem) {
		pout << " pathfinding to item: ";
		targetitem->dumpInfo();
	} else {
		pout << " pathfinding to (" << targetx << "," << targety << "," << targetz << ")" << std::endl;
	}
#endif

#ifdef DEBUG
	if (actor->getObjId() == visualdebug_actor) {
		RenderSurface* screen = GUIApp::get_instance()->getScreen();
		screen->BeginPainting();
		if (targetitem)
			drawbox(targetitem);
		else
			drawdot(targetx, targety, targetz, 2, 0xFF0000FF);
		screen->EndPainting();
	}
#endif


	path.clear();

	PathNode* startnode = new PathNode();
	startnode->state = start;
	startnode->cost = 0;
	startnode->parent = 0;
	startnode->depth = 0;
	startnode->stepsfromparent = 0;
	nodelist.push_back(startnode);
	nodes.push(startnode);

	unsigned int expandednodes = 0;
	const unsigned int NODELIMIT_MIN = 30;	//! constant
	const unsigned int NODELIMIT_MAX = 200;	//! constant
	bool found = false;
	Uint32 starttime = SDL_GetTicks();

	while (expandednodes < NODELIMIT_MAX && !nodes.empty() && !found) {
		PathNode* node = nodes.top(); nodes.pop();

#if 0
		pout << "Trying node: (" << node->state.x << "," << node->state.y
			 << "," << node->state.z << ") target=(" << targetx << ","
			 << targety << "," << targetz << ")" << std::endl;
#endif

		if (checkTarget(node)) {
			// done!

			// find path length
			PathNode* n = node;
			unsigned int length = 0;
			while (n->parent) {
				n = n->parent;
				length++;
			}
#if 0
			pout << "Pathfinder: path found (length = " << length << ")"
				 << std::endl;
#endif

			unsigned int i = length;
			if (length > 0) length++; // add space for final 'stand' action
			path.resize(length);

			// now backtrack through the nodes to assemble the final animation
			while (node->parent) {
				PathfindingAction action;
				action.action = node->state.lastanim;
				action.direction = node->state.direction;
				action.steps = node->stepsfromparent;
				path[--i] = action;
#if 0
				pout << "anim = " << node->state.lastanim << ", dir = "
					 << node->state.direction << ", steps = "
					 << node->stepsfromparent << std::endl;
#endif

				//TODO: check how turns work
				//TODO: append final 'stand' animation

				node = node->parent;
			}

			if (length) {
				if (node->state.combat)
					path[length-1].action = Animation::combatStand;
				else
					path[length-1].action = Animation::stand;
				path[length-1].direction = path[length-2].direction;
			}

			expandtime = SDL_GetTicks() - starttime;
			return true;
		}

		expandNode(node);
		expandednodes++;

		if(expandednodes >= NODELIMIT_MIN && ((expandednodes) % 5) == 0)
		{
			Uint32 elapsed_ms = SDL_GetTicks() - starttime;
			if(elapsed_ms > 350) break;
		}
	}

	expandtime = SDL_GetTicks() - starttime;

#if 0
	static sint32 pfcalls = 0;
	static sint32 pftotaltime = 0;
	pfcalls++;
	pftotaltime += expandtime;
	pout << "maxout average = " << (pftotaltime / pfcalls) << "ms." << std::endl;
#endif

	return false;
}
Beispiel #2
0
void Pathfinder::newNode(PathNode* oldnode, PathfindingState& state,
						 unsigned int steps)
{
	PathNode* newnode = new PathNode();
	nodelist.push_back(newnode); // for garbage collection
	newnode->state = state;
	newnode->parent = oldnode;
	newnode->depth = oldnode->depth + 1;
	newnode->stepsfromparent = 0;
	
	double sqrddist;
	
	sqrddist = ((newnode->state.x - oldnode->state.x)*
				(newnode->state.x - oldnode->state.x));
	sqrddist += ((newnode->state.y - oldnode->state.y)*
				 (newnode->state.y - oldnode->state.y));
	sqrddist += ((newnode->state.z - oldnode->state.z)*
				 (newnode->state.z - oldnode->state.z));
	
	unsigned int dist;
	dist = static_cast<unsigned int>(std::sqrt(sqrddist));
	
	int turn = 0;
	
	if (oldnode->depth > 0) {
		turn = state.direction - oldnode->state.direction;
		if (turn < 0) turn = -turn;
		if (turn > 4) turn = 8 - turn;
	}
	
	newnode->cost = oldnode->cost + dist + 32*turn; //!! constant

	bool done = checkTarget(newnode);
	if (done)
		newnode->heuristicTotalCost = 0;
	else
		costHeuristic(newnode);

#if 0
	perr << "trying dir " << state.direction;

	if (steps > 0) {
		perr << ", " << steps << " steps";
	}
	perr << " from ("
		 << oldnode->state.x << "," << oldnode->state.y << ") to ("
		 << newnode->state.x << "," << newnode->state.y
		 << "), cost = " << newnode->cost << ", heurtotcost = "
		 << newnode->heuristicTotalCost << std::endl;
#endif

#ifdef DEBUG
	if (actor->getObjId() == visualdebug_actor) {
		RenderSurface* screen = GUIApp::get_instance()->getScreen();
		screen->BeginPainting();
		drawpath(newnode, 0xFFFFFF00, done);
		screen->EndPainting();
		SDL_Delay(250);
		if (!done) {
			screen->BeginPainting();
			drawpath(newnode, 0xFFB0B000, done);
			screen->EndPainting();
		}
	}
#endif

	nodes.push(newnode);	
}