mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-06-08 01:22:02 +00:00
Some changed to pathfinding. This hopefully gets rid of spikes in very short paths. Some untested changes.
This commit is contained in:
parent
6b82ea86be
commit
35c8086802
6 changed files with 187 additions and 42 deletions
|
@ -31,8 +31,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "AquariaMenuItem.h"
|
#include "AquariaMenuItem.h"
|
||||||
#include "ScriptInterface.h"
|
#include "ScriptInterface.h"
|
||||||
|
|
||||||
#include "PathFinding.h"
|
|
||||||
|
|
||||||
#include "TTFFont.h"
|
#include "TTFFont.h"
|
||||||
|
|
||||||
#include "tinyxml2.h"
|
#include "tinyxml2.h"
|
||||||
|
@ -1397,7 +1395,6 @@ public:
|
||||||
|
|
||||||
void jumpToSection(InStream &inFile, const std::string §ion);
|
void jumpToSection(InStream &inFile, const std::string §ion);
|
||||||
|
|
||||||
PathFinding pathFinding;
|
|
||||||
void runGesture(const std::string &line);
|
void runGesture(const std::string &line);
|
||||||
void generateCollisionMask(RenderObject *r);
|
void generateCollisionMask(RenderObject *r);
|
||||||
void toggleRenderCollisionShapes();
|
void toggleRenderCollisionShapes();
|
||||||
|
|
|
@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
#include "ScriptedEntity.h"
|
#include "ScriptedEntity.h"
|
||||||
#include "Shot.h"
|
#include "Shot.h"
|
||||||
|
#include "PathFinding.h"
|
||||||
|
|
||||||
//Shader Entity::blurShader;
|
//Shader Entity::blurShader;
|
||||||
|
|
||||||
|
@ -485,10 +486,10 @@ void Entity::moveToNode(Path *path, int speedType, int dieOnPathEnd, bool swim)
|
||||||
|
|
||||||
swimPath = swim;
|
swimPath = swim;
|
||||||
//debugLog("Generating path to: " + path->name);
|
//debugLog("Generating path to: " + path->name);
|
||||||
dsq->pathFinding.generatePath(this, TileVector(start), TileVector(dest));
|
PathFinding::generatePath(this, TileVector(start), TileVector(dest));
|
||||||
int sz = position.data->path.getNumPathNodes();
|
//int sz = position.data->path.getNumPathNodes();
|
||||||
position.data->path.addPathNode(path->nodes[0].position, 1);
|
//position.data->path.addPathNode(path->nodes[0].position, 1);
|
||||||
VectorPath old = position.data->path;
|
//VectorPath old = position.data->path;
|
||||||
/*std::ostringstream os;
|
/*std::ostringstream os;
|
||||||
os << "Path length: " << sz;
|
os << "Path length: " << sz;
|
||||||
debugLog(os.str());*/
|
debugLog(os.str());*/
|
||||||
|
@ -509,12 +510,12 @@ void Entity::moveToNode(Path *path, int speedType, int dieOnPathEnd, bool swim)
|
||||||
|
|
||||||
//debugLog("Molesting Path");
|
//debugLog("Molesting Path");
|
||||||
|
|
||||||
dsq->pathFinding.molestPath(position.data->path);
|
PathFinding::molestPath(position.data->path);
|
||||||
//position.data->path.realPercentageCalc();
|
//position.data->path.realPercentageCalc();
|
||||||
//position.data->path.cut(4);
|
//position.data->path.cut(4);
|
||||||
|
|
||||||
//debugLog("forcing path to minimum 2 nodes");
|
//debugLog("forcing path to minimum 2 nodes");
|
||||||
dsq->pathFinding.forceMinimumPath(position.data->path, start, dest);
|
PathFinding::forceMinimumPath(position.data->path, start, dest);
|
||||||
//debugLog("Done");
|
//debugLog("Done");
|
||||||
|
|
||||||
//debugLog("Calculating Time");
|
//debugLog("Calculating Time");
|
||||||
|
|
|
@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "DSQ.h"
|
#include "DSQ.h"
|
||||||
#include "Path.h"
|
#include "Path.h"
|
||||||
#include "Hair.h"
|
#include "Hair.h"
|
||||||
|
#include "TileVector.h"
|
||||||
|
|
||||||
#include "tinyxml2.h"
|
#include "tinyxml2.h"
|
||||||
using namespace tinyxml2;
|
using namespace tinyxml2;
|
||||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "DSQ.h"
|
#include "DSQ.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
|
|
||||||
class SearchGridRaw
|
class SearchGridRaw
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -33,11 +34,19 @@ public:
|
||||||
return (game->getGridRaw(TileVector(x, y)) & blockingObsBits) == OT_EMPTY;
|
return (game->getGridRaw(TileVector(x, y)) & blockingObsBits) == OT_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
ObsType blockingObsBits;
|
||||||
const ObsType blockingObsBits;
|
|
||||||
const Game *game;
|
const Game *game;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PathFinding::State : public ScriptObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
State(ObsType obs) : grid(obs), searcher(grid), result(JPS::NO_PATH) {}
|
||||||
|
SearchGridRaw grid;
|
||||||
|
JPS::Searcher<SearchGridRaw> searcher;
|
||||||
|
JPS::Result result;
|
||||||
|
};
|
||||||
|
|
||||||
static void generateVectorPath(const JPS::PathVector& rawpath, VectorPath& vp, int offx, int offy)
|
static void generateVectorPath(const JPS::PathVector& rawpath, VectorPath& vp, int offx, int offy)
|
||||||
{
|
{
|
||||||
for(JPS::PathVector::const_iterator it = rawpath.begin(); it != rawpath.end(); ++it)
|
for(JPS::PathVector::const_iterator it = rawpath.begin(); it != rawpath.end(); ++it)
|
||||||
|
@ -124,7 +133,7 @@ void PathFinding::molestPath(VectorPath &path)
|
||||||
lastSuccessNode = 0;
|
lastSuccessNode = 0;
|
||||||
hadSuccess = false;
|
hadSuccess = false;
|
||||||
Vector node = path.getPathNode(i)->value;
|
Vector node = path.getPathNode(i)->value;
|
||||||
for (int j = sz-3; j >= i+adjust; j--)
|
for (int j = sz-1; j >= i+adjust; j--)
|
||||||
{
|
{
|
||||||
Vector target = path.getPathNode(j)->value;
|
Vector target = path.getPathNode(j)->value;
|
||||||
if (dsq->game->trace(node, target))
|
if (dsq->game->trace(node, target))
|
||||||
|
@ -183,3 +192,55 @@ bool PathFinding::generatePathSimple(VectorPath& path, const Vector& start, cons
|
||||||
molestPath(path);
|
molestPath(path);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PathFinding::State *PathFinding::initFindPath()
|
||||||
|
{
|
||||||
|
State *state = new PathFinding::State(OT_BLOCKING);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathFinding::deleteFindPath(State *state)
|
||||||
|
{
|
||||||
|
delete state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathFinding::beginFindPath(PathFinding::State *state, const Vector& start, const Vector& end, unsigned int obs /* = 0 */)
|
||||||
|
{
|
||||||
|
if(obs == OT_EMPTY)
|
||||||
|
obs = OT_BLOCKING;
|
||||||
|
|
||||||
|
state->grid.blockingObsBits = (ObsType)obs;
|
||||||
|
JPS::Position istart = JPS::Pos(start.x, start.y);
|
||||||
|
JPS::Position iend = JPS::Pos(end.x, end.y);
|
||||||
|
state->result = state->searcher.findPathInit(istart, iend);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathFinding::updateFindPath(PathFinding::State *state, int limit)
|
||||||
|
{
|
||||||
|
int oldres = state->result;
|
||||||
|
if(oldres == JPS::NEED_MORE_STEPS)
|
||||||
|
{
|
||||||
|
state->result = state->searcher.findPathStep(limit);
|
||||||
|
return oldres != state->result;
|
||||||
|
}
|
||||||
|
return true; // done
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathFinding::finishFindPath(PathFinding::State *state, VectorPath& path, unsigned step /* = 0 */)
|
||||||
|
{
|
||||||
|
if(state->result != JPS::FOUND_PATH)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JPS::PathVector rawpath;
|
||||||
|
state->searcher.findPathFinish(rawpath, step);
|
||||||
|
generateVectorPath(rawpath, path, 0, 0);
|
||||||
|
molestPath(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathFinding::getStats(PathFinding::State *state, unsigned& stepsDone, unsigned& nodesExpanded)
|
||||||
|
{
|
||||||
|
stepsDone = (unsigned)state->searcher.getStepsDone();
|
||||||
|
nodesExpanded = (unsigned)state->searcher.getNodesExpanded();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,23 @@ class RenderObject;
|
||||||
class SearchGrid;
|
class SearchGrid;
|
||||||
class Game;
|
class Game;
|
||||||
|
|
||||||
class PathFinding
|
namespace PathFinding
|
||||||
{
|
{
|
||||||
public:
|
class State;
|
||||||
|
|
||||||
void forceMinimumPath(VectorPath &path, const Vector &start, const Vector &dest);
|
void forceMinimumPath(VectorPath &path, const Vector &start, const Vector &dest);
|
||||||
void molestPath(VectorPath &path);
|
void molestPath(VectorPath &path);
|
||||||
void generatePath(RenderObject *go, TileVector g1, TileVector g2, int offx=0, int offy=0);
|
void generatePath(RenderObject *go, TileVector g1, TileVector g2, int offx=0, int offy=0);
|
||||||
|
|
||||||
bool generatePathSimple(VectorPath& path, const Vector& start, const Vector& end, unsigned int step = 0, unsigned int obs = 0);
|
bool generatePathSimple(VectorPath& path, const Vector& start, const Vector& end, unsigned int step = 0, unsigned int obs = 0);
|
||||||
|
|
||||||
|
State *initFindPath();
|
||||||
|
void deleteFindPath(State *state);
|
||||||
|
|
||||||
|
void beginFindPath(State *state, const Vector& start, const Vector& end, unsigned int obs = 0);
|
||||||
|
bool updateFindPath(State *state, int limit);
|
||||||
|
bool finishFindPath(State *state, VectorPath& path, unsigned step = 0);
|
||||||
|
void getStats(State *state, unsigned& stepsDone, unsigned& nodesExpanded);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,6 +36,7 @@ extern "C"
|
||||||
#include "Web.h"
|
#include "Web.h"
|
||||||
#include "GridRender.h"
|
#include "GridRender.h"
|
||||||
#include "AfterEffect.h"
|
#include "AfterEffect.h"
|
||||||
|
#include "PathFinding.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "../BBGE/MathFunctions.h"
|
#include "../BBGE/MathFunctions.h"
|
||||||
|
@ -8729,6 +8730,43 @@ luaFunc(isShuttingDownGameState)
|
||||||
luaReturnBool(dsq->game->isShuttingDownGameState());
|
luaReturnBool(dsq->game->isShuttingDownGameState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _fillPathfindTables(lua_State *L, VectorPath& path, int xs_idx, int ys_idx)
|
||||||
|
{
|
||||||
|
const unsigned num = path.getNumPathNodes();
|
||||||
|
|
||||||
|
if(lua_istable(L, xs_idx))
|
||||||
|
lua_pushvalue(L, xs_idx);
|
||||||
|
else
|
||||||
|
lua_createtable(L, num, 0);
|
||||||
|
|
||||||
|
if(lua_istable(L, ys_idx))
|
||||||
|
lua_pushvalue(L, ys_idx);
|
||||||
|
else
|
||||||
|
lua_createtable(L, num, 0);
|
||||||
|
|
||||||
|
// [..., xs, yx]
|
||||||
|
for(unsigned i = 0; i < num; ++i)
|
||||||
|
{
|
||||||
|
const VectorPathNode *n = path.getPathNode(i);
|
||||||
|
lua_pushnumber(L, n->value.x); // [..., xs, ys, x]
|
||||||
|
lua_rawseti(L, -3, i+1); // [..., xs, ys]
|
||||||
|
lua_pushnumber(L, n->value.y); // [..., xs, ys, y]
|
||||||
|
lua_rawseti(L, -2, i+1); // [..., xs, ys]
|
||||||
|
}
|
||||||
|
// terminate tables
|
||||||
|
lua_pushnil(L); // [..., xs, ys, nil]
|
||||||
|
lua_rawseti(L, -3, num+1); // [..., xs, ys]
|
||||||
|
lua_pushnil(L); // [..., xs, ys, nil]
|
||||||
|
lua_rawseti(L, -2, num+1); // [..., xs, ys]
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _pathfindDelete(lua_State *L)
|
||||||
|
{
|
||||||
|
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
|
||||||
|
PathFinding::deleteFindPath(state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// startx, starty, endx, endy [, step, xtab, ytab, obsMask]
|
// startx, starty, endx, endy [, step, xtab, ytab, obsMask]
|
||||||
luaFunc(findPath)
|
luaFunc(findPath)
|
||||||
{
|
{
|
||||||
|
@ -8736,55 +8774,81 @@ luaFunc(findPath)
|
||||||
Vector start(lua_tonumber(L, 1), lua_tonumber(L, 2));
|
Vector start(lua_tonumber(L, 1), lua_tonumber(L, 2));
|
||||||
Vector end(lua_tonumber(L, 3), lua_tonumber(L, 4));
|
Vector end(lua_tonumber(L, 3), lua_tonumber(L, 4));
|
||||||
ObsType obs = ObsType(lua_tointeger(L, 8));
|
ObsType obs = ObsType(lua_tointeger(L, 8));
|
||||||
if(!dsq->pathFinding.generatePathSimple(path, start, end, lua_tointeger(L, 5), obs))
|
if(!PathFinding::generatePathSimple(path, start, end, lua_tointeger(L, 5), obs))
|
||||||
luaReturnBool(false);
|
luaReturnBool(false);
|
||||||
|
|
||||||
const unsigned num = path.getNumPathNodes();
|
const unsigned num = path.getNumPathNodes();
|
||||||
lua_pushinteger(L, num);
|
lua_pushinteger(L, num);
|
||||||
|
|
||||||
if(lua_istable(L, 6))
|
_fillPathfindTables(L, path, 6, 7);
|
||||||
lua_pushvalue(L, 6);
|
|
||||||
else
|
|
||||||
lua_createtable(L, num, 0);
|
|
||||||
|
|
||||||
if(lua_istable(L, 7))
|
|
||||||
lua_pushvalue(L, 7);
|
|
||||||
else
|
|
||||||
lua_createtable(L, num, 0);
|
|
||||||
|
|
||||||
// [true, xs, yx]
|
|
||||||
|
|
||||||
for(unsigned i = 0; i < num; ++i)
|
|
||||||
{
|
|
||||||
const VectorPathNode *n = path.getPathNode(i);
|
|
||||||
lua_pushnumber(L, n->value.x); // [num, xs, ys, x]
|
|
||||||
lua_rawseti(L, -3, i+1); // [num, xs, ys]
|
|
||||||
lua_pushnumber(L, n->value.y); // [num, xs, ys, y]
|
|
||||||
lua_rawseti(L, -2, i+1); // [num, xs, ys]
|
|
||||||
}
|
|
||||||
// terminate tables
|
|
||||||
lua_pushnil(L); // [num xs, ys, nil]
|
|
||||||
lua_rawseti(L, -3, num+1); // [num, xs, ys]
|
|
||||||
lua_pushnil(L); // [num, xs, ys, nil]
|
|
||||||
lua_rawseti(L, -2, num+1); // [num, xs, ys]
|
|
||||||
|
|
||||||
return 3; // found path?, x positions, y positions
|
return 3; // found path?, x positions, y positions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
luaFunc(createFindPath)
|
||||||
|
{
|
||||||
|
PathFinding::State **statep = (PathFinding::State**)lua_newuserdata(L, sizeof(void*));
|
||||||
|
*statep = PathFinding::initFindPath();
|
||||||
|
luaL_getmetatable(L, "pathfinder");
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
luaFunc(findPathBegin)
|
||||||
|
{
|
||||||
|
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
|
||||||
|
Vector start(lua_tonumber(L, 1), lua_tonumber(L, 2));
|
||||||
|
Vector end(lua_tonumber(L, 3), lua_tonumber(L, 4));
|
||||||
|
ObsType obs = ObsType(lua_tointeger(L, 8));
|
||||||
|
PathFinding::beginFindPath(state, start, end, obs);
|
||||||
|
luaReturnNil();
|
||||||
|
}
|
||||||
|
|
||||||
|
luaFunc(findPathUpdate)
|
||||||
|
{
|
||||||
|
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
|
||||||
|
int limit = lua_tointeger(L, 2);
|
||||||
|
bool done = PathFinding::updateFindPath(state, limit);
|
||||||
|
luaReturnBool(done);
|
||||||
|
}
|
||||||
|
|
||||||
|
luaFunc(findPathFinish)
|
||||||
|
{
|
||||||
|
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
|
||||||
|
VectorPath path;
|
||||||
|
bool found = PathFinding::finishFindPath(state, path);
|
||||||
|
if(!found)
|
||||||
|
luaReturnBool(false);
|
||||||
|
|
||||||
|
lua_pushinteger(L, (int)path.getNumPathNodes());
|
||||||
|
_fillPathfindTables(L, path, 2, 3);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
luaFunc(findPathGetStats)
|
||||||
|
{
|
||||||
|
PathFinding::State *state = *(PathFinding::State**)luaL_checkudata(L, 1, "pathfinder");
|
||||||
|
unsigned stepsDone, nodesExpanded;
|
||||||
|
PathFinding::getStats(state, stepsDone, nodesExpanded);
|
||||||
|
lua_pushinteger(L, stepsDone);
|
||||||
|
lua_pushinteger(L, nodesExpanded);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
luaFunc(castLine)
|
luaFunc(castLine)
|
||||||
{
|
{
|
||||||
Vector v(lua_tonumber(L, 1), lua_tonumber(L, 2));
|
Vector v(lua_tonumber(L, 1), lua_tonumber(L, 2));
|
||||||
Vector end(lua_tonumber(L, 3), lua_tonumber(L, 4));
|
Vector end(lua_tonumber(L, 3), lua_tonumber(L, 4));
|
||||||
int tiletype = lua_tointeger(L, 5);
|
int tiletype = lua_tointeger(L, 5);
|
||||||
if(!tiletype)
|
if(!tiletype)
|
||||||
tiletype = -1;
|
tiletype = OT_BLOCKING;
|
||||||
Vector step = end - v;
|
Vector step = end - v;
|
||||||
int steps = step.getLength2D() / TILE_SIZE;
|
int steps = step.getLength2D() / TILE_SIZE;
|
||||||
step.setLength2D(TILE_SIZE);
|
step.setLength2D(TILE_SIZE);
|
||||||
|
|
||||||
for(int i = 0; i < steps; ++i)
|
for(int i = 0; i < steps; ++i)
|
||||||
{
|
{
|
||||||
if(dsq->game->isObstructed(TileVector(v), tiletype))
|
if(dsq->game->getGridRaw(TileVector(v)) & tiletype)
|
||||||
{
|
{
|
||||||
lua_pushinteger(L, dsq->game->getGrid(TileVector(v)));
|
lua_pushinteger(L, dsq->game->getGrid(TileVector(v)));
|
||||||
lua_pushnumber(L, v.x);
|
lua_pushnumber(L, v.x);
|
||||||
|
@ -9628,6 +9692,11 @@ static const struct {
|
||||||
luaRegister(getObstruction),
|
luaRegister(getObstruction),
|
||||||
luaRegister(getGridRaw),
|
luaRegister(getGridRaw),
|
||||||
luaRegister(findPath),
|
luaRegister(findPath),
|
||||||
|
luaRegister(createFindPath),
|
||||||
|
luaRegister(findPathBegin),
|
||||||
|
luaRegister(findPathUpdate),
|
||||||
|
luaRegister(findPathFinish),
|
||||||
|
luaRegister(findPathGetStats),
|
||||||
luaRegister(castLine),
|
luaRegister(castLine),
|
||||||
luaRegister(getUserInputString),
|
luaRegister(getUserInputString),
|
||||||
luaRegister(getMaxCameraValues),
|
luaRegister(getMaxCameraValues),
|
||||||
|
@ -10881,6 +10950,13 @@ lua_State *ScriptInterface::createLuaVM()
|
||||||
// In case a script errors outside of any protected environment, report and exit.
|
// In case a script errors outside of any protected environment, report and exit.
|
||||||
lua_atpanic(state, l_panicHandler);
|
lua_atpanic(state, l_panicHandler);
|
||||||
|
|
||||||
|
// Register Lua classes
|
||||||
|
luaL_newmetatable(state, "pathfinder");
|
||||||
|
lua_pushliteral(state, "__gc");
|
||||||
|
lua_pushcfunction(state, _pathfindDelete);
|
||||||
|
lua_settable(state, -3);
|
||||||
|
lua_pop(state, 1);
|
||||||
|
|
||||||
// All done, return the new state.
|
// All done, return the new state.
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue