Mercurial > fife-parpg
diff engine/core/pathfinder/routepather/routepather.cpp @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children | 90005975cdbb |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/pathfinder/routepather/routepather.cpp Sun Jun 29 18:44:17 2008 +0000 @@ -0,0 +1,205 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes +#include <cassert> + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "model/metamodel/grids/cellgrid.h" +#include "model/structures/instance.h" +#include "model/structures/layer.h" + +#include "pathfinder/searchspace.h" + +#include "routepather.h" +#include "routepathersearch.h" + +namespace FIFE { + void RoutePather::setMap(Map* map) { + if(!map) { + return; + } + m_map = map; + } + + int RoutePather::getNextLocation(const Instance* instance, const Location& target, + double distance_to_travel, Location& nextLocation, + Location& facingLocation, int session_id, int priority) { + assert(instance); + assert(instance->getLocation().getLayer() == target.getLayer()); + if(session_id != -1) { + PathMap::iterator j = m_paths.find(session_id); + if(j != m_paths.end()) { + if(j->second.empty()) { + m_paths.erase(j); + return -1; + } else { + followPath(instance, j->second, distance_to_travel, nextLocation, facingLocation); + return session_id; + } + } else { + if(!sessionIdValid(session_id)) { + //Session id is invalid. + return -1; + } + } + return session_id; + } + SearchSpace* searchspace = getSearchSpace(target.getLayer()); + if(!searchspace) { + searchspace = new SearchSpace(target.getLayer()); + addSearchSpace(searchspace); + } + if(searchspace->isInSearchSpace(target)) { + session_id = m_nextFreeSessionId++; + RoutePatherSearch* newSearch = new RoutePatherSearch(session_id, instance->getLocation(), target, searchspace); + m_sessions.pushElement(SessionQueue::value_type(newSearch, priority)); + addSessionId(session_id); + } + return session_id; + } + + void RoutePather::update() { + int ticksleft = m_maxticks; + while(ticksleft >= 0) { + if(m_sessions.empty()) { + break; + } + Search* priority_session = m_sessions.getPriorityElement().first; + if(!sessionIdValid(priority_session->getSessionId())) { + delete priority_session; + m_sessions.popElement(); + continue; + } + priority_session->updateSearch(); + if(priority_session->getSearchStatus() == Search::search_status_complete) { + Path newPath = priority_session->calcPath(); + m_paths.insert(PathMap::value_type(priority_session->getSessionId(), newPath)); + invalidateSessionId(priority_session->getSessionId()); + delete priority_session; + m_sessions.popElement(); + } else if(priority_session->getSearchStatus() == Search::search_status_failed) { + invalidateSessionId(priority_session->getSessionId()); + delete priority_session; + m_sessions.popElement(); + } + --ticksleft; + } + } + + void RoutePather::followPath(const Instance* instance, Path& path, double speed, Location& nextLocation, Location& facingLocation) { + Location instanceLoc = instance->getLocation(); + ExactModelCoordinate instancePos = instanceLoc.getMapCoordinates(); + ExactModelCoordinate facingPos = path.front().getMapCoordinates(); + facingPos.x = facingPos.x + (facingPos.x - instancePos.x); + facingPos.y = facingPos.y + (facingPos.y - instancePos.y); + facingLocation = path.front(); + facingLocation.setMapCoordinates(facingPos); + ExactModelCoordinate targetPos = path.front().getMapCoordinates(); + CellGrid* grid = instanceLoc.getLayer()->getCellGrid(); + double dx = (targetPos.x - instancePos.x) * grid->getXScale(); + double dy = (targetPos.y - instancePos.y) * grid->getYScale(); + double distance = sqrt(dx * dx + dy * dy); + bool pop = false; + if(speed > distance) { + speed = distance; + pop = true; + } + if(distance != 0) + { + instancePos.x += (dx / distance) * speed; + instancePos.y += (dy / distance) * speed; + + } else { + pop = true; + } + nextLocation.setMapCoordinates(instancePos); + if(pop) + { + path.pop_front(); + if(!path.empty() && instanceLoc.getLayer()->cellContainsBlockingInstance(path.front().getLayerCoordinates())) + { + //TODO: Determine if we're close enough to stop, otherwise find alternate route. + path.clear(); + return; + } + } + } + + bool RoutePather::cancelSession(const int session_id) { + if(session_id >= 0) { + PathMap::iterator i = m_paths.find(session_id); + if(i != m_paths.end()) { + m_paths.erase(i); + return true; + } else { + invalidateSessionId(session_id); + } + } + return false; + } + + void RoutePather::addSessionId(const int sessionId) { + m_registeredSessionIds.push_back(sessionId); + } + + bool RoutePather::sessionIdValid(const int sessionId) { + for(SessionList::const_iterator i = m_registeredSessionIds.begin(); + i != m_registeredSessionIds.end(); + ++i) { + if((*i) == sessionId) { + return true; + } + } + return false; + } + + bool RoutePather::invalidateSessionId(const int sessionId) { + for(SessionList::iterator i = m_registeredSessionIds.begin(); + i != m_registeredSessionIds.end(); + ++i) { + if((*i) == sessionId) { + m_registeredSessionIds.erase(i); + return true; + } + } + return false; + } + + bool RoutePather::addSearchSpace(SearchSpace* search_space) { + std::pair<SearchSpaceMap::iterator, bool> res = m_searchspaces.insert(SearchSpaceMap::value_type(search_space->getLayer(), search_space)); + + return res.second; + } + + SearchSpace* RoutePather::getSearchSpace(Layer * const layer) { + SearchSpaceMap::iterator i = m_searchspaces.find(layer); + if(i == m_searchspaces.end()) { + return 0; + } + return i->second; + } +}