1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-06-08 09:31:58 +00:00

Some changed to pathfinding. This hopefully gets rid of spikes in very short paths. Some untested changes.

This commit is contained in:
fgenesis 2014-07-21 22:20:08 +02:00
parent 6b82ea86be
commit 35c8086802
6 changed files with 187 additions and 42 deletions

View file

@ -31,8 +31,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "AquariaMenuItem.h"
#include "ScriptInterface.h"
#include "PathFinding.h"
#include "TTFFont.h"
#include "tinyxml2.h"
@ -1397,7 +1395,6 @@ public:
void jumpToSection(InStream &inFile, const std::string &section);
PathFinding pathFinding;
void runGesture(const std::string &line);
void generateCollisionMask(RenderObject *r);
void toggleRenderCollisionShapes();

View file

@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "Avatar.h"
#include "ScriptedEntity.h"
#include "Shot.h"
#include "PathFinding.h"
//Shader Entity::blurShader;
@ -485,10 +486,10 @@ void Entity::moveToNode(Path *path, int speedType, int dieOnPathEnd, bool swim)
swimPath = swim;
//debugLog("Generating path to: " + path->name);
dsq->pathFinding.generatePath(this, TileVector(start), TileVector(dest));
int sz = position.data->path.getNumPathNodes();
position.data->path.addPathNode(path->nodes[0].position, 1);
VectorPath old = position.data->path;
PathFinding::generatePath(this, TileVector(start), TileVector(dest));
//int sz = position.data->path.getNumPathNodes();
//position.data->path.addPathNode(path->nodes[0].position, 1);
//VectorPath old = position.data->path;
/*std::ostringstream os;
os << "Path length: " << sz;
debugLog(os.str());*/
@ -509,12 +510,12 @@ void Entity::moveToNode(Path *path, int speedType, int dieOnPathEnd, bool swim)
//debugLog("Molesting Path");
dsq->pathFinding.molestPath(position.data->path);
PathFinding::molestPath(position.data->path);
//position.data->path.realPercentageCalc();
//position.data->path.cut(4);
//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("Calculating Time");

View file

@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "DSQ.h"
#include "Path.h"
#include "Hair.h"
#include "TileVector.h"
#include "tinyxml2.h"
using namespace tinyxml2;

View file

@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "DSQ.h"
#include "Game.h"
class SearchGridRaw
{
public:
@ -33,11 +34,19 @@ public:
return (game->getGridRaw(TileVector(x, y)) & blockingObsBits) == OT_EMPTY;
}
private:
const ObsType blockingObsBits;
ObsType blockingObsBits;
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)
{
for(JPS::PathVector::const_iterator it = rawpath.begin(); it != rawpath.end(); ++it)
@ -124,7 +133,7 @@ void PathFinding::molestPath(VectorPath &path)
lastSuccessNode = 0;
hadSuccess = false;
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;
if (dsq->game->trace(node, target))
@ -183,3 +192,55 @@ bool PathFinding::generatePathSimple(VectorPath& path, const Vector& start, cons
molestPath(path);
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();
}

View file

@ -30,14 +30,23 @@ class RenderObject;
class SearchGrid;
class Game;
class PathFinding
namespace PathFinding
{
public:
class State;
void forceMinimumPath(VectorPath &path, const Vector &start, const Vector &dest);
void molestPath(VectorPath &path);
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);
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

View file

@ -36,6 +36,7 @@ extern "C"
#include "Web.h"
#include "GridRender.h"
#include "AfterEffect.h"
#include "PathFinding.h"
#include <algorithm>
#include "../BBGE/MathFunctions.h"
@ -8729,6 +8730,43 @@ luaFunc(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]
luaFunc(findPath)
{
@ -8736,55 +8774,81 @@ luaFunc(findPath)
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));
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);
const unsigned num = path.getNumPathNodes();
lua_pushinteger(L, num);
if(lua_istable(L, 6))
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]
_fillPathfindTables(L, path, 6, 7);
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)
{
Vector v(lua_tonumber(L, 1), lua_tonumber(L, 2));
Vector end(lua_tonumber(L, 3), lua_tonumber(L, 4));
int tiletype = lua_tointeger(L, 5);
if(!tiletype)
tiletype = -1;
tiletype = OT_BLOCKING;
Vector step = end - v;
int steps = step.getLength2D() / TILE_SIZE;
step.setLength2D(TILE_SIZE);
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_pushnumber(L, v.x);
@ -9628,6 +9692,11 @@ static const struct {
luaRegister(getObstruction),
luaRegister(getGridRaw),
luaRegister(findPath),
luaRegister(createFindPath),
luaRegister(findPathBegin),
luaRegister(findPathUpdate),
luaRegister(findPathFinish),
luaRegister(findPathGetStats),
luaRegister(castLine),
luaRegister(getUserInputString),
luaRegister(getMaxCameraValues),
@ -10881,6 +10950,13 @@ lua_State *ScriptInterface::createLuaVM()
// In case a script errors outside of any protected environment, report and exit.
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.
return state;
}