Mercurial > fife-parpg
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
1 /*************************************************************************** | |
2 * Copyright (C) 2005-2008 by the FIFE team * | |
3 * http://www.fifengine.de * | |
4 * This file is part of FIFE. * | |
5 * * | |
6 * FIFE is free software; you can redistribute it and/or modify * | |
7 * it under the terms of the GNU General Public License as published by * | |
8 * the Free Software Foundation; either version 2 of the License, or * | |
9 * (at your option) any later version. * | |
10 * * | |
11 * This program is distributed in the hope that it will be useful, * | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
14 * GNU General Public License for more details. * | |
15 * * | |
16 * You should have received a copy of the GNU General Public License * | |
17 * along with this program; if not, write to the * | |
18 * Free Software Foundation, Inc., * | |
19 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * | |
20 ***************************************************************************/ | |
21 | |
22 // Standard C++ library includes | |
23 #include <cassert> | |
24 | |
25 // 3rd party library includes | |
26 | |
27 // FIFE includes | |
28 // These includes are split up in two parts, separated by one empty line | |
29 // First block: files included from the FIFE root src directory | |
30 // Second block: files included from the same folder | |
31 #include "model/metamodel/grids/cellgrid.h" | |
32 #include "model/structures/instance.h" | |
33 #include "model/structures/layer.h" | |
34 | |
35 #include "pathfinder/searchspace.h" | |
36 | |
37 #include "routepather.h" | |
38 #include "routepathersearch.h" | |
39 | |
40 namespace FIFE { | |
41 void RoutePather::setMap(Map* map) { | |
42 if(!map) { | |
43 return; | |
44 } | |
45 m_map = map; | |
46 } | |
47 | |
48 int RoutePather::getNextLocation(const Instance* instance, const Location& target, | |
49 double distance_to_travel, Location& nextLocation, | |
50 Location& facingLocation, int session_id, int priority) { | |
51 assert(instance); | |
52 assert(instance->getLocation().getLayer() == target.getLayer()); | |
53 if(session_id != -1) { | |
54 PathMap::iterator j = m_paths.find(session_id); | |
55 if(j != m_paths.end()) { | |
56 if(j->second.empty()) { | |
57 m_paths.erase(j); | |
58 return -1; | |
59 } else { | |
60 followPath(instance, j->second, distance_to_travel, nextLocation, facingLocation); | |
61 return session_id; | |
62 } | |
63 } else { | |
64 if(!sessionIdValid(session_id)) { | |
65 //Session id is invalid. | |
66 return -1; | |
67 } | |
68 } | |
69 return session_id; | |
70 } | |
71 SearchSpace* searchspace = getSearchSpace(target.getLayer()); | |
72 if(!searchspace) { | |
73 searchspace = new SearchSpace(target.getLayer()); | |
74 addSearchSpace(searchspace); | |
75 } | |
76 if(searchspace->isInSearchSpace(target)) { | |
77 session_id = m_nextFreeSessionId++; | |
78 RoutePatherSearch* newSearch = new RoutePatherSearch(session_id, instance->getLocation(), target, searchspace); | |
79 m_sessions.pushElement(SessionQueue::value_type(newSearch, priority)); | |
80 addSessionId(session_id); | |
81 } | |
82 return session_id; | |
83 } | |
84 | |
85 void RoutePather::update() { | |
86 int ticksleft = m_maxticks; | |
87 while(ticksleft >= 0) { | |
88 if(m_sessions.empty()) { | |
89 break; | |
90 } | |
91 Search* priority_session = m_sessions.getPriorityElement().first; | |
92 if(!sessionIdValid(priority_session->getSessionId())) { | |
93 delete priority_session; | |
94 m_sessions.popElement(); | |
95 continue; | |
96 } | |
97 priority_session->updateSearch(); | |
98 if(priority_session->getSearchStatus() == Search::search_status_complete) { | |
99 Path newPath = priority_session->calcPath(); | |
100 m_paths.insert(PathMap::value_type(priority_session->getSessionId(), newPath)); | |
101 invalidateSessionId(priority_session->getSessionId()); | |
102 delete priority_session; | |
103 m_sessions.popElement(); | |
104 } else if(priority_session->getSearchStatus() == Search::search_status_failed) { | |
105 invalidateSessionId(priority_session->getSessionId()); | |
106 delete priority_session; | |
107 m_sessions.popElement(); | |
108 } | |
109 --ticksleft; | |
110 } | |
111 } | |
112 | |
113 void RoutePather::followPath(const Instance* instance, Path& path, double speed, Location& nextLocation, Location& facingLocation) { | |
114 Location instanceLoc = instance->getLocation(); | |
115 ExactModelCoordinate instancePos = instanceLoc.getMapCoordinates(); | |
116 ExactModelCoordinate facingPos = path.front().getMapCoordinates(); | |
117 facingPos.x = facingPos.x + (facingPos.x - instancePos.x); | |
118 facingPos.y = facingPos.y + (facingPos.y - instancePos.y); | |
119 facingLocation = path.front(); | |
120 facingLocation.setMapCoordinates(facingPos); | |
121 ExactModelCoordinate targetPos = path.front().getMapCoordinates(); | |
122 CellGrid* grid = instanceLoc.getLayer()->getCellGrid(); | |
123 double dx = (targetPos.x - instancePos.x) * grid->getXScale(); | |
124 double dy = (targetPos.y - instancePos.y) * grid->getYScale(); | |
125 double distance = sqrt(dx * dx + dy * dy); | |
126 bool pop = false; | |
127 if(speed > distance) { | |
128 speed = distance; | |
129 pop = true; | |
130 } | |
131 if(distance != 0) | |
132 { | |
133 instancePos.x += (dx / distance) * speed; | |
134 instancePos.y += (dy / distance) * speed; | |
135 | |
136 } else { | |
137 pop = true; | |
138 } | |
139 nextLocation.setMapCoordinates(instancePos); | |
140 if(pop) | |
141 { | |
142 path.pop_front(); | |
143 if(!path.empty() && instanceLoc.getLayer()->cellContainsBlockingInstance(path.front().getLayerCoordinates())) | |
144 { | |
145 //TODO: Determine if we're close enough to stop, otherwise find alternate route. | |
146 path.clear(); | |
147 return; | |
148 } | |
149 } | |
150 } | |
151 | |
152 bool RoutePather::cancelSession(const int session_id) { | |
153 if(session_id >= 0) { | |
154 PathMap::iterator i = m_paths.find(session_id); | |
155 if(i != m_paths.end()) { | |
156 m_paths.erase(i); | |
157 return true; | |
158 } else { | |
159 invalidateSessionId(session_id); | |
160 } | |
161 } | |
162 return false; | |
163 } | |
164 | |
165 void RoutePather::addSessionId(const int sessionId) { | |
166 m_registeredSessionIds.push_back(sessionId); | |
167 } | |
168 | |
169 bool RoutePather::sessionIdValid(const int sessionId) { | |
170 for(SessionList::const_iterator i = m_registeredSessionIds.begin(); | |
171 i != m_registeredSessionIds.end(); | |
172 ++i) { | |
173 if((*i) == sessionId) { | |
174 return true; | |
175 } | |
176 } | |
177 return false; | |
178 } | |
179 | |
180 bool RoutePather::invalidateSessionId(const int sessionId) { | |
181 for(SessionList::iterator i = m_registeredSessionIds.begin(); | |
182 i != m_registeredSessionIds.end(); | |
183 ++i) { | |
184 if((*i) == sessionId) { | |
185 m_registeredSessionIds.erase(i); | |
186 return true; | |
187 } | |
188 } | |
189 return false; | |
190 } | |
191 | |
192 bool RoutePather::addSearchSpace(SearchSpace* search_space) { | |
193 std::pair<SearchSpaceMap::iterator, bool> res = m_searchspaces.insert(SearchSpaceMap::value_type(search_space->getLayer(), search_space)); | |
194 | |
195 return res.second; | |
196 } | |
197 | |
198 SearchSpace* RoutePather::getSearchSpace(Layer * const layer) { | |
199 SearchSpaceMap::iterator i = m_searchspaces.find(layer); | |
200 if(i == m_searchspaces.end()) { | |
201 return 0; | |
202 } | |
203 return i->second; | |
204 } | |
205 } |