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:
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 "ScriptInterface.h"
|
||||
|
||||
#include "PathFinding.h"
|
||||
|
||||
#include "TTFFont.h"
|
||||
|
||||
#include "tinyxml2.h"
|
||||
|
@ -1397,7 +1395,6 @@ public:
|
|||
|
||||
void jumpToSection(InStream &inFile, const std::string §ion);
|
||||
|
||||
PathFinding pathFinding;
|
||||
void runGesture(const std::string &line);
|
||||
void generateCollisionMask(RenderObject *r);
|
||||
void toggleRenderCollisionShapes();
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue