diff --git a/Aquaria/DSQ.h b/Aquaria/DSQ.h index 773e212..03b189a 100644 --- a/Aquaria/DSQ.h +++ b/Aquaria/DSQ.h @@ -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(); diff --git a/Aquaria/Entity.cpp b/Aquaria/Entity.cpp index b34b0af..d4e2ee9 100644 --- a/Aquaria/Entity.cpp +++ b/Aquaria/Entity.cpp @@ -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"); diff --git a/Aquaria/Entity.h b/Aquaria/Entity.h index e7d8d97..9bc9ee4 100644 --- a/Aquaria/Entity.h +++ b/Aquaria/Entity.h @@ -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; diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index 17b450c..80920da 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -9328,7 +9328,7 @@ void Game::toggleKeyConfigMenu(bool f) //group_keyConfig->children[group_keyConfig->children.size()-3] - RenderObjectList::reverse_iterator i = group_keyConfig->children.rbegin(); + RenderObject::Children::reverse_iterator i = group_keyConfig->children.rbegin(); AquariaKeyConfig *upright0 = (AquariaKeyConfig*)(*i); i++; AquariaKeyConfig *upright = (AquariaKeyConfig*)(*i); diff --git a/Aquaria/PathFinding.cpp b/Aquaria/PathFinding.cpp index 3a0f69e..ee450b7 100644 --- a/Aquaria/PathFinding.cpp +++ b/Aquaria/PathFinding.cpp @@ -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 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(); +} + diff --git a/Aquaria/PathFinding.h b/Aquaria/PathFinding.h index 7920cbb..1193afb 100644 --- a/Aquaria/PathFinding.h +++ b/Aquaria/PathFinding.h @@ -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 diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index 18d96c8..75ff6b6 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -36,6 +36,7 @@ extern "C" #include "Web.h" #include "GridRender.h" #include "AfterEffect.h" +#include "PathFinding.h" #include #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; } diff --git a/Aquaria/ScriptedEntity.cpp b/Aquaria/ScriptedEntity.cpp index 6ac9b53..6316e5f 100644 --- a/Aquaria/ScriptedEntity.cpp +++ b/Aquaria/ScriptedEntity.cpp @@ -153,6 +153,9 @@ void ScriptedEntity::initEmitter(int emit, const std::string &file) void ScriptedEntity::startEmitter(int emit) { + if(emit >= emitters.size()) + return; + if (emitters[emit]) { emitters[emit]->start(); @@ -161,6 +164,9 @@ void ScriptedEntity::startEmitter(int emit) void ScriptedEntity::stopEmitter(int emit) { + if(emit >= emitters.size()) + return; + if (emitters[emit]) { emitters[emit]->stop(); diff --git a/BBGE/Localization.cpp b/BBGE/Localization.cpp index 24c5417..333fc2f 100644 --- a/BBGE/Localization.cpp +++ b/BBGE/Localization.cpp @@ -7,7 +7,6 @@ #endif #ifdef BBGE_BUILD_MACOSX -#include #include #include @@ -112,13 +111,11 @@ std::string getSystemLocale() if ((buf = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleLanguageCode)) != NULL) { localeStr = _CFToStdString(buf); - CFRelease(buf); if ((buf = (CFStringRef)CFLocaleGetValue(locale, kCFLocaleCountryCode)) != NULL) { localeStr += "_"; localeStr += _CFToStdString(buf); - CFRelease(buf); } } diff --git a/BBGE/RenderObject.cpp b/BBGE/RenderObject.cpp index 6268eee..abb0c16 100644 --- a/BBGE/RenderObject.cpp +++ b/BBGE/RenderObject.cpp @@ -1099,26 +1099,6 @@ void RenderObject::lookAt(const Vector &pos, float t, float minAngle, float maxA rotation.interpolateTo(Vector(0,0,angle), t); } -void RenderObject::removeAllChildren() -{ - if (!children.empty()) - { - removeChild(children.front()); - removeAllChildren(); - } -} - -void RenderObject::recursivelyRemoveEveryChild() -{ - if (!children.empty()) - { - RenderObject *child = (children.front()); - child->recursivelyRemoveEveryChild(); - removeChild(child); - recursivelyRemoveEveryChild(); - } -} - void RenderObject::update(float dt) { if (ignoreUpdate) @@ -1149,8 +1129,14 @@ void RenderObject::update(float dt) void RenderObject::removeChild(RenderObject *r) { - children.remove(r); r->parent = 0; + Children::iterator oldend = children.end(); + Children::iterator newend = std::remove(children.begin(), oldend, r); + if(oldend != newend) + { + children.resize(std::distance(children.begin(), newend)); + return; + } for (Children::iterator i = children.begin(); i != children.end(); i++) { @@ -1301,29 +1287,6 @@ void RenderObject::onUpdate(float dt) // updateCullVariables(); } -void RenderObject::propogateAlpha() -{ - /* - if (!shareAlphaWithChildren) return; - for (int i = 0; i < children.size(); i++) - { - children[i]->alpha = this->alpha * children[i]->parentAlphaModifier.getValue(); - children[i]->propogateAlpha(); - } - - */ - /* - if (shareAlphaWithChildren && !children.empty()) - { - for (int i = 0; i < children.size(); i++) - { - - //children[i]->alpha = this->alpha * children[i]->parentAlphaModifier.getValue(); - } - } - */ -} - void RenderObject::unloadDevice() { for (Children::iterator i = children.begin(); i != children.end(); i++) @@ -1375,7 +1338,7 @@ void RenderObject::addChild(RenderObject *r, ParentManaged pm, RenderBeforeParen if (order == CHILD_BACK) children.push_back(r); else - children.push_front(r); + children.insert(children.begin(), r); r->pm = pm; @@ -1407,15 +1370,6 @@ void RenderObject::setOverrideCullRadius(float ovr) overrideCullRadiusSqr = ovr * ovr; } -void RenderObject::propogateParentManagedStatic() -{ - for (Children::iterator i = children.begin(); i != children.end(); i++) - { - (*i)->pm = PM_STATIC; - (*i)->propogateParentManagedStatic(); - } -} - bool RenderObject::isCoordinateInRadius(const Vector &pos, float r) { Vector d = pos-getRealPosition(); diff --git a/BBGE/RenderObject.h b/BBGE/RenderObject.h index 1925570..2542c1f 100644 --- a/BBGE/RenderObject.h +++ b/BBGE/RenderObject.h @@ -167,8 +167,6 @@ public: void addChild(RenderObject *r, ParentManaged pm, RenderBeforeParent rbp = RBP_NONE, ChildOrder order = CHILD_BACK); void removeChild(RenderObject *r); - void removeAllChildren(); - void recursivelyRemoveEveryChild(); Vector getRealPosition(); Vector getRealScale(); @@ -279,7 +277,7 @@ public: InterpolatedVector *positionSnapTo; //DestroyType destroyType; - typedef std::list Children; + typedef std::vector Children; Children children, childGarbage; //Flags flags; @@ -312,10 +310,6 @@ protected: virtual void deathNotify(RenderObject *r); virtual void onEndOfLife() {} - // spread parentManagedStatic flag to the entire child tree - void propogateParentManagedStatic(); - void propogateAlpha(); - inline void updateLife(float dt) { if (decayRate > 0) diff --git a/BBGE/SkeletalSprite.cpp b/BBGE/SkeletalSprite.cpp index 3313034..85dc918 100644 --- a/BBGE/SkeletalSprite.cpp +++ b/BBGE/SkeletalSprite.cpp @@ -1144,16 +1144,10 @@ void SkeletalSprite::prevAnimation() void SkeletalSprite::deleteBones() { bones.clear(); - if (!children.empty()) + for(Children::iterator it = children.begin(); it != children.end(); ++it) { - // remove child had better be recursive - Bone *b = (Bone*)children.front(); - //removeChild(b); - b->destroy(); - delete b; - deleteBones(); + (*it)->safeKill(); } - children.clear(); bones.clear(); }