1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-12-25 22:25:46 +00:00

Pathfinding & map grid improvements.

There were still only 6 of 8 bits of the map grid in use.
The last 2 bits are now available as non-colliding user bits,
and are ignored unless specially treated.
The findPath() function can now be told which bits to respect,
which allows to prevent pathfinding to pass through fish tunnels,
for example.
A function for fast user bit map dilation is added as well.
This commit is contained in:
fgenesis 2014-05-16 00:11:52 +02:00
parent b98e2532ed
commit 3db8c9e13a
8 changed files with 185 additions and 124 deletions

View file

@ -3561,7 +3561,7 @@ void Avatar::lockToWall()
while(0); while(0);
} }
if (dsq->game->getGrid(t)==OT_HURT && isDamageTarget(DT_WALLHURT)) if (dsq->game->isObstructed(t, OT_HURT) && isDamageTarget(DT_WALLHURT))
{ {
good = false; good = false;
} }
@ -3612,16 +3612,16 @@ void Avatar::lockToWall()
Vector offdiff = t.worldVector() - position; Vector offdiff = t.worldVector() - position;
if (!offdiff.isZero()) if (!offdiff.isZero())
{ {
if (tileType != OT_INVISIBLEIN) if (tileType & OT_INVISIBLEIN)
{ {
Vector adjust = offdiff; Vector adjust = offdiff;
adjust.setLength2D(TILE_SIZE*2); adjust.setLength2D(TILE_SIZE/2);
offdiff -= adjust; offdiff -= adjust;
} }
else else
{ {
Vector adjust = offdiff; Vector adjust = offdiff;
adjust.setLength2D(TILE_SIZE/2); adjust.setLength2D(TILE_SIZE*2);
offdiff -= adjust; offdiff -= adjust;
} }
} }

View file

@ -1509,13 +1509,13 @@ bool Entity::isSittingOnInvisibleIn()
{ {
for (int y = 0; y < 4; y++) for (int y = 0; y < 4; y++)
{ {
if (dsq->game->getGrid(TileVector(t.x+x, t.y+y))==OT_INVISIBLEIN) if (dsq->game->isObstructed(TileVector(t.x+x, t.y+y), OT_INVISIBLEIN))
return true; return true;
if (dsq->game->getGrid(TileVector(t.x-x, t.y+y))==OT_INVISIBLEIN) if (dsq->game->isObstructed(TileVector(t.x-x, t.y+y), OT_INVISIBLEIN))
return true; return true;
if (dsq->game->getGrid(TileVector(t.x+x, t.y-y))==OT_INVISIBLEIN) if (dsq->game->isObstructed(TileVector(t.x+x, t.y-y), OT_INVISIBLEIN))
return true; return true;
if (dsq->game->getGrid(TileVector(t.x-x, t.y-y))==OT_INVISIBLEIN) if (dsq->game->isObstructed(TileVector(t.x-x, t.y-y), OT_INVISIBLEIN))
return true; return true;
} }
} }
@ -3055,6 +3055,7 @@ bool Entity::doCollisionAvoidance(float dt, int search, float mod, Vector *vp, i
int minDist=-1; int minDist=-1;
TileVector t(position); TileVector t(position);
TileVector useTile; TileVector useTile;
const int blockObs = ~ignoreObs;
float totalDist = sqrtf(float(sqr((search*2)*TILE_SIZE)+sqr((search*2)*TILE_SIZE))); float totalDist = sqrtf(float(sqr((search*2)*TILE_SIZE)+sqr((search*2)*TILE_SIZE)));
for (int x = -search; x <= search; x++) for (int x = -search; x <= search; x++)
@ -3069,7 +3070,7 @@ bool Entity::doCollisionAvoidance(float dt, int search, float mod, Vector *vp, i
} }
if (waterBlocked || dsq->game->isObstructed(checkT)) if (waterBlocked || dsq->game->isObstructed(checkT))
{ {
if (dsq->game->getGrid(checkT) != ignoreObs) if (dsq->game->isObstructed(checkT, blockObs))
{ {
Vector vtc(t.x+x, t.y+y); Vector vtc(t.x+x, t.y+y);
Vector vt(t.x, t.y); Vector vt(t.x, t.y);

View file

@ -2075,8 +2075,8 @@ void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim)
//dsq->game->setGrid(TileVector(tpos.x+(w2*TILE_SIZE)+(x/TILE_SIZE), tpos.y+(h2*TILE_SIZE)+(y/TILE_SIZE)), obsType); //dsq->game->setGrid(TileVector(tpos.x+(w2*TILE_SIZE)+(x/TILE_SIZE), tpos.y+(h2*TILE_SIZE)+(y/TILE_SIZE)), obsType);
TileVector tvec(tpos.x+w2+x, tpos.y+h2+y); TileVector tvec(tpos.x+w2+x, tpos.y+h2+y);
if (dsq->game->getGrid(tvec) == OT_EMPTY) if (!dsq->game->isObstructed(tvec))
dsq->game->setGrid(tvec, obsType); dsq->game->addGrid(tvec, obsType);
} }
glPopMatrix(); glPopMatrix();
@ -2103,7 +2103,7 @@ void Game::clearDynamicGrid(unsigned char maskbyte /* = OT_MASK_BLACK */)
// otherwise there is a chance to write a few bytes over the end of the buffer -- FG // otherwise there is a chance to write a few bytes over the end of the buffer -- FG
compile_assert(sizeof(grid) % sizeof(uint32) == 0); compile_assert(sizeof(grid) % sizeof(uint32) == 0);
signed char *gridstart = &grid[0][0]; unsigned char *gridstart = &grid[0][0];
uint32 *gridend = (uint32*)(gridstart + sizeof(grid)); uint32 *gridend = (uint32*)(gridstart + sizeof(grid));
uint32 *gridptr = (uint32*)gridstart; uint32 *gridptr = (uint32*)gridstart;
// mask out specific bytes // mask out specific bytes
@ -2165,9 +2165,9 @@ void Game::trimGrid()
// from beeing drawn. (The maps were designed with this mind...) // from beeing drawn. (The maps were designed with this mind...)
for (int x = 0; x < MAX_GRID; x++) for (int x = 0; x < MAX_GRID; x++)
{ {
const signed char *curCol = dsq->game->getGridColumn(x); const unsigned char *curCol = grid[x]; // safe
const signed char *leftCol = dsq->game->getGridColumn(x-1); const unsigned char *leftCol = dsq->game->getGridColumn(x-1); // unsafe
const signed char *rightCol = dsq->game->getGridColumn(x+1); const unsigned char *rightCol = dsq->game->getGridColumn(x+1); // unsafe
for (int y = 0; y < MAX_GRID; y++) for (int y = 0; y < MAX_GRID; y++)
{ {
if (curCol[y] & OT_MASK_BLACK) if (curCol[y] & OT_MASK_BLACK)
@ -2179,6 +2179,66 @@ void Game::trimGrid()
} }
} }
void Game::dilateGrid(unsigned int radius, ObsType test, ObsType set, ObsType allowOverwrite)
{
if(!radius)
return;
const int lim = MAX_GRID - radius;
const unsigned int denyOverwrite = ~allowOverwrite;
// Box dilation is separable, so we do a two-pass by axis
int dilate = 0;
// dilate rows
for (int y = 0; y < MAX_GRID; ++y)
{
for (int x = radius; x < lim; ++x)
{
if (grid[x][y] & test)
{
dilate = 2 * radius;
goto doDilate1;
}
if(dilate)
{
--dilate;
doDilate1:
if((grid[x - radius][y] & denyOverwrite) == OT_EMPTY)
grid[x - radius][y] |= set;
}
}
assert(lim + dilate < MAX_GRID);
for(int x = 0; x < dilate; ++x)
if(!(grid[x][y - radius] & test))
grid[x][y - radius] |= set;
}
// dilate colums
dilate = 0;
for (int x = 0; x < MAX_GRID; ++x)
{
unsigned char * const curCol = grid[x];
for (int y = radius; y < lim; ++y)
{
if (curCol[y] & test)
{
dilate = 2 * radius;
goto doDilate2;
}
if(dilate)
{
--dilate;
doDilate2:
if((curCol[y - radius] & denyOverwrite) == OT_EMPTY)
curCol[y - radius] |= set;
}
}
assert(lim + dilate < MAX_GRID);
for(int y = 0; y < dilate; ++y)
if(!(curCol[y - radius] & test))
curCol[y - radius] |= set;
}
}
float Game::getCoverage(Vector pos, int sampleArea) float Game::getCoverage(Vector pos, int sampleArea)
{ {
TileVector t(pos); TileVector t(pos);
@ -6451,30 +6511,46 @@ void Game::applyState()
addRenderObject(songLineRender, LR_HUD); addRenderObject(songLineRender, LR_HUD);
gridRender = new GridRender(OT_INVISIBLE); gridRender = new GridRender(OT_INVISIBLE);
gridRender->color = Vector(1, 0, 0);
addRenderObject(gridRender, LR_DEBUG_TEXT); addRenderObject(gridRender, LR_DEBUG_TEXT);
gridRender->alpha = 0; gridRender->alpha = 0;
gridRender2 = new GridRender(OT_HURT); gridRender2 = new GridRender(OT_HURT);
gridRender2->color = Vector(1, 1, 0);
addRenderObject(gridRender2, LR_DEBUG_TEXT); addRenderObject(gridRender2, LR_DEBUG_TEXT);
gridRender2->alpha = 0; gridRender2->alpha = 0;
gridRender3 = new GridRender(OT_INVISIBLEIN); gridRender3 = new GridRender(OT_INVISIBLEIN);
gridRender3->color = Vector(1, 0.5f, 0);
addRenderObject(gridRender3, LR_DEBUG_TEXT); addRenderObject(gridRender3, LR_DEBUG_TEXT);
gridRender3->alpha = 0; gridRender3->alpha = 0;
edgeRender = new GridRender(OT_BLACKINVIS); edgeRender = new GridRender(OT_BLACKINVIS);
edgeRender->color = Vector(0.3f, 0, 0.6f);
addRenderObject(edgeRender, LR_DEBUG_TEXT); addRenderObject(edgeRender, LR_DEBUG_TEXT);
edgeRender->alpha = 0; edgeRender->alpha = 0;
gridRenderEnt = new GridRender(OT_INVISIBLEENT); gridRenderEnt = new GridRender(OT_INVISIBLEENT);
gridRenderEnt->color = Vector(0, 1, 0.5);
addRenderObject(gridRenderEnt, LR_DEBUG_TEXT); addRenderObject(gridRenderEnt, LR_DEBUG_TEXT);
gridRenderEnt->alpha = 0; gridRenderEnt->alpha = 0;
gridRenderUser1 = new GridRender(OT_USER1);
addRenderObject(gridRenderUser1, LR_DEBUG_TEXT);
gridRenderUser1->color = Vector(1, 0, 1);
gridRenderUser1->alpha = 0;
gridRenderUser2 = new GridRender(OT_USER2);
addRenderObject(gridRenderUser2, LR_DEBUG_TEXT);
gridRenderUser2->color = Vector(1, 1, 1);
gridRenderUser2->alpha = 0;
waterSurfaceRender = new WaterSurfaceRender(); waterSurfaceRender = new WaterSurfaceRender();
//waterSurfaceRender->setRenderPass(-1); //waterSurfaceRender->setRenderPass(-1);
addRenderObject(waterSurfaceRender, LR_WATERSURFACE); addRenderObject(waterSurfaceRender, LR_WATERSURFACE);
GridRender *blackRender = new GridRender(OT_BLACK); GridRender *blackRender = new GridRender(OT_BLACK);
blackRender->color = Vector(0, 0, 0);
//blackRender->alpha = 0; //blackRender->alpha = 0;
blackRender->blendEnabled = false; blackRender->blendEnabled = false;
addRenderObject(blackRender, LR_ELEMENTS4); addRenderObject(blackRender, LR_ELEMENTS4);
@ -8515,22 +8591,17 @@ void Game::toggleMiniMapRender(int v)
void Game::toggleGridRender() void Game::toggleGridRender()
{ {
float t = 0; float t = 0;
float a = 0;
if (gridRender->alpha == 0) if (gridRender->alpha == 0)
{ a = 0.5f;
gridRender->alpha.interpolateTo(0.5, t);
gridRender2->alpha.interpolateTo(0.5, t); gridRender->alpha.interpolateTo(a, t);
gridRender3->alpha.interpolateTo(0.5, t); gridRender2->alpha.interpolateTo(a, t);
edgeRender->alpha.interpolateTo(0.5, t); gridRender3->alpha.interpolateTo(a, t);
gridRenderEnt->alpha.interpolateTo(0.5, t); edgeRender->alpha.interpolateTo(a, t);
} gridRenderEnt->alpha.interpolateTo(a, t);
else if (gridRender->alpha == 0.5) gridRenderUser1->alpha.interpolateTo(a, t);
{ gridRenderUser2->alpha.interpolateTo(a, t);
gridRender->alpha.interpolateTo(0, t);
gridRender2->alpha.interpolateTo(0, t);
gridRender3->alpha.interpolateTo(0, t);
edgeRender->alpha.interpolateTo(0, t);
gridRenderEnt->alpha.interpolateTo(0, t);
}
} }
Vector Game::getCameraPositionFor(const Vector &pos) Vector Game::getCameraPositionFor(const Vector &pos)
@ -10624,7 +10695,7 @@ void Game::setGrid(ElementTemplate *et, Vector position, float rot360)
} }
TileVector s(t.x+x, t.y+y); TileVector s(t.x+x, t.y+y);
//Vector v = Vector(position.x+et->grid[i].x*TILE_SIZE, position.y+et->grid[i].y*TILE_SIZE); //Vector v = Vector(position.x+et->grid[i].x*TILE_SIZE, position.y+et->grid[i].y*TILE_SIZE);
setGrid(s, 1); setGrid(s, OT_INVISIBLE);
} }
} }
@ -10752,6 +10823,12 @@ void Game::removeState()
miniMapRender = 0; miniMapRender = 0;
gridRender = 0; gridRender = 0;
gridRender2 = 0;
gridRender3 = 0;
edgeRender = 0;
gridRenderEnt = 0;
gridRenderUser1 = 0;
gridRenderUser2 = 0;
worldMapRender = 0; worldMapRender = 0;
//core->sound->stopStreamingOgg(); //core->sound->stopStreamingOgg();
@ -10922,44 +10999,6 @@ bool Game::collideCircleWithGrid(const Vector& position, float r)
return false; return false;
} }
bool Game::collideBoxWithGrid(const Vector& position, int hw, int hh)
{
Vector tile = position;
TileVector t(tile);
tile.x = t.x;
tile.y = t.y;
float hsz = TILE_SIZE/2;
int xrange=1,yrange=1;
xrange = (hw/TILE_SIZE)+1;
yrange = (hh/TILE_SIZE)+1;
for (int x = tile.x-xrange; x <= tile.x+xrange; x++)
{
for (int y = tile.y-yrange; y <= tile.y+yrange; y++)
{
int v = this->getGrid(TileVector(x, y));
if (v == 1)
{
if (tile.x == x && tile.y == y) return true;
float rx = (x*TILE_SIZE)+TILE_SIZE/2;
float ry = (y*TILE_SIZE)+TILE_SIZE/2;
if (isBoxIn(position, Vector(hw, hh), Vector(rx, ry), Vector(hsz, hsz)))
{
return true;
}
if (isBoxIn(Vector(rx, ry), Vector(hsz, hsz), position, Vector(hw, hh)))
{
return true;
}
}
}
}
return false;
}
void Game::learnedRecipe(Recipe *r, bool effects) void Game::learnedRecipe(Recipe *r, bool effects)
{ {
if (nocasecmp(dsq->getTopStateData()->name,"Game")==0 && !applyingState) if (nocasecmp(dsq->getTopStateData()->name,"Game")==0 && !applyingState)

View file

@ -587,6 +587,14 @@ enum ObsType
// set by entities // set by entities
OT_INVISIBLEENT = 0x20, OT_INVISIBLEENT = 0x20,
// mask for all bits that block
OT_BLOCKING = OT_MASK_BLACK | OT_INVISIBLE | OT_INVISIBLEIN | OT_HURT | OT_INVISIBLEENT,
// free for use, not colliding by default
OT_USER1 = 0x40,
OT_USER2 = 0x80,
OT_USER_MASK = OT_USER1 | OT_USER2,
}; };
struct EntitySaveData struct EntitySaveData
@ -620,12 +628,14 @@ public:
std::string getSelectedChoice() { return selectedChoice; } std::string getSelectedChoice() { return selectedChoice; }
int getGrid(const TileVector &tile) const; ObsType getGrid(const TileVector &tile) const;
int getGridRaw(unsigned int x, unsigned int y) const; ObsType getGridRaw(const TileVector &tile) const;
const signed char *getGridColumn(int tileX); unsigned char *getGridColumn(int tileX);
void setGrid(const TileVector &tile, int v); void setGrid(const TileVector &tile, ObsType v);
bool isObstructed(const TileVector &tile, int t = -1) const; void addGrid(const TileVector &tile, ObsType v);
bool isObstructed(const TileVector &tile, int t = OT_BLOCKING) const;
void trimGrid(); void trimGrid();
void dilateGrid(unsigned int radius, ObsType test, ObsType set, ObsType allowOverwrite);
void clearPointers(); void clearPointers();
@ -655,7 +665,6 @@ public:
void registerSporeDrop(const Vector &pos, int t); void registerSporeDrop(const Vector &pos, int t);
bool collideBoxWithGrid(const Vector& position, int w, int h);
bool collideCircleWithGrid(const Vector& position, float r); bool collideCircleWithGrid(const Vector& position, float r);
bool collideHairVsCircle(Entity *a, int num, const Vector &pos2, float radius, float perc=0, int *colSegment=0); bool collideHairVsCircle(Entity *a, int num, const Vector &pos2, float radius, float perc=0, int *colSegment=0);
@ -959,7 +968,7 @@ public:
void createGradient(); void createGradient();
std::string saveMusic; std::string saveMusic;
GridRender *gridRender, *gridRender2, *gridRender3, *edgeRender, *gridRenderEnt; GridRender *gridRender, *gridRender2, *gridRender3, *edgeRender, *gridRenderEnt, *gridRenderUser1, *gridRenderUser2;
void toggleGridRender(); void toggleGridRender();
ElementUpdateList elementUpdateList; ElementUpdateList elementUpdateList;
ElementUpdateList elementInteractionList; ElementUpdateList elementInteractionList;
@ -1174,7 +1183,7 @@ protected:
void toggleSceneEditor(); void toggleSceneEditor();
#endif #endif
signed char grid[MAX_GRID][MAX_GRID]; unsigned char grid[MAX_GRID][MAX_GRID];
Quad *bg, *bg2; Quad *bg, *bg2;
@ -1200,21 +1209,23 @@ extern Game *game;
// INLINE FUNCTIONS // INLINE FUNCTIONS
inline inline
int Game::getGridRaw(unsigned int x, unsigned int y) const ObsType Game::getGridRaw(const TileVector &tile) const
{ {
return grid[x][y]; return (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID))
? ObsType(grid[tile.x][tile.y])
: OT_INVISIBLE;
} }
inline inline
int Game::getGrid(const TileVector &tile) const ObsType Game::getGrid(const TileVector &tile) const
{ {
//if (tile.x < 0 || tile.x >= MAX_GRID || tile.y < 0 || tile.y >= MAX_GRID) return OT_INVISIBLE; return (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID))
//return grid[tile.x][tile.y]; ? ObsType(grid[tile.x][tile.y] & OT_BLOCKING)
return (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID)) ? grid[tile.x][tile.y] : OT_INVISIBLE; : OT_INVISIBLE;
} }
inline inline
const signed char *Game::getGridColumn(int tileX) unsigned char *Game::getGridColumn(int tileX)
{ {
if (tileX < 0) if (tileX < 0)
return grid[0]; return grid[0];
@ -1225,14 +1236,21 @@ const signed char *Game::getGridColumn(int tileX)
} }
inline inline
void Game::setGrid(const TileVector &tile, int v) void Game::setGrid(const TileVector &tile, ObsType v)
{ {
if (tile.x < 0 || tile.x >= MAX_GRID || tile.y < 0 || tile.y >= MAX_GRID) return; if (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID))
grid[tile.x][tile.y] = v; grid[tile.x][tile.y] = v;
} }
inline inline
bool Game::isObstructed(const TileVector &tile, int t /* = -1 */) const void Game::addGrid(const TileVector &tile, ObsType v)
{
if (unsigned(tile.x) < unsigned(MAX_GRID) && unsigned(tile.y) < unsigned(MAX_GRID))
grid[tile.x][tile.y] |= v;
}
inline
bool Game::isObstructed(const TileVector &tile, int t /* = OT_BLOCKING */) const
{ {
return (getGrid(tile) & t); return (getGrid(tile) & t);
} }

View file

@ -66,30 +66,6 @@ inline static void doRenderGrid(int x, int startCol, int endCol)
void GridRender::onRender() void GridRender::onRender()
{ {
switch(obsType)
{
case OT_INVISIBLE:
core->setColor(1, 0, 0, alpha.getValue());
break;
case OT_INVISIBLEIN:
core->setColor(1, 0.5, 0, alpha.getValue());
break;
case OT_INVISIBLEENT:
core->setColor(0, 1, 0.5, alpha.getValue());
break;
case OT_BLACK:
core->setColor(0, 0, 0, 1);
break;
case OT_BLACKINVIS:
core->setColor(0.3, 0, 0.6, alpha.getValue());
break;
case OT_HURT:
core->setColor(1, 1, 0, alpha.getValue());
break;
default:
break;
}
const signed char obsType = this->obsType; const signed char obsType = this->obsType;
Vector camPos = core->cameraPos; Vector camPos = core->cameraPos;
camPos.x -= core->getVirtualOffX() * (core->invGlobalScale); camPos.x -= core->getVirtualOffX() * (core->invGlobalScale);
@ -112,11 +88,11 @@ void GridRender::onRender()
return; return;
for (int x = startX; x <= endX; ++x) for (int x = startX; x <= endX; ++x)
{ {
const signed char *gridColumn = dsq->game->getGridColumn(x); const unsigned char *gridColumn = dsq->game->getGridColumn(x);
int startCol = -1, y; int startCol = -1, y;
// fast-forward to next drawable byte // fast-forward to next drawable byte
if(const signed char *next = (const signed char*)memchr(gridColumn + startY, obsType, endY - startY + 1)) // find next byte with correct obs type if(const unsigned char *next = (const unsigned char*)memchr(gridColumn + startY, obsType, endY - startY + 1)) // find next byte with correct obs type
{ {
y = next - gridColumn; // will get incremented right away, which is okay, because we alrady set startCol y = next - gridColumn; // will get incremented right away, which is okay, because we alrady set startCol
startCol = y; startCol = y;
@ -131,7 +107,7 @@ void GridRender::onRender()
doRenderGrid(x, startCol, y - 1); doRenderGrid(x, startCol, y - 1);
// fast-forward to next drawable byte // fast-forward to next drawable byte
if(const signed char *next = (const signed char*)memchr(gridColumn + y, obsType, endY - y)) // find next byte with correct obs type if(const unsigned char *next = (const unsigned char*)memchr(gridColumn + y, obsType, endY - y)) // find next byte with correct obs type
{ {
y = next - gridColumn; // will get incremented right away, which is okay, because we alrady set startCol y = next - gridColumn; // will get incremented right away, which is okay, because we alrady set startCol
startCol = y; startCol = y;

View file

@ -24,16 +24,17 @@ 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 SearchGrid class SearchGridRaw
{ {
public: public:
SearchGrid() : game(dsq->game) {} SearchGridRaw(ObsType blocking) : game(dsq->game), blockingObsBits(blocking) {}
inline bool operator()(unsigned x, unsigned y) const inline bool operator()(unsigned x, unsigned y) const
{ {
return game->getGrid(TileVector(x, y)) == OT_EMPTY; return (game->getGridRaw(TileVector(x, y)) & blockingObsBits) == OT_EMPTY;
} }
private: private:
const ObsType blockingObsBits;
const Game *game; const Game *game;
}; };
@ -157,7 +158,7 @@ void PathFinding::generatePath(RenderObject *ro, TileVector start, TileVector go
VectorPath& vp = ro->position.data->path; VectorPath& vp = ro->position.data->path;
vp.clear(); vp.clear();
SearchGrid grid; SearchGridRaw grid(OT_BLOCKING);
JPS::PathVector path; JPS::PathVector path;
if(JPS::findPath(path, grid, start.x, start.y, goal.x, goal.y, 1)) if(JPS::findPath(path, grid, start.x, start.y, goal.x, goal.y, 1))
{ {
@ -166,9 +167,12 @@ void PathFinding::generatePath(RenderObject *ro, TileVector start, TileVector go
} }
} }
bool PathFinding::generatePathSimple(VectorPath& path, const Vector& start, const Vector& end, unsigned int step /* = 0 */) bool PathFinding::generatePathSimple(VectorPath& path, const Vector& start, const Vector& end, unsigned int step /* = 0 */, unsigned int obs /* = 0 */)
{ {
SearchGrid grid; if(obs == OT_EMPTY)
obs = OT_BLOCKING;
SearchGridRaw grid((ObsType)obs);
JPS::PathVector p; JPS::PathVector p;
TileVector tstart(start); TileVector tstart(start);
TileVector tend(end); TileVector tend(end);

View file

@ -37,7 +37,7 @@ public:
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); bool generatePathSimple(VectorPath& path, const Vector& start, const Vector& end, unsigned int step = 0, unsigned int obs = 0);
}; };
#endif #endif

View file

@ -2898,6 +2898,16 @@ luaFunc(reconstructEntityGrid)
luaReturnNil(); luaReturnNil();
} }
luaFunc(dilateGrid)
{
unsigned int radius = lua_tointeger(L, 1);
ObsType test = (ObsType)lua_tointeger(L, 2);
ObsType set = (ObsType)lua_tointeger(L, 3);
ObsType allowOverwrite = (ObsType)lua_tointeger(L, 4);
dsq->game->dilateGrid(radius, test, set, allowOverwrite);
luaReturnNil();
}
luaFunc(entity_setCanLeaveWater) luaFunc(entity_setCanLeaveWater)
{ {
Entity *e = entity(L); Entity *e = entity(L);
@ -8347,6 +8357,11 @@ luaFunc(getObstruction)
luaReturnInt(dsq->game->getGrid(TileVector(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2))))); luaReturnInt(dsq->game->getGrid(TileVector(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)))));
} }
luaFunc(getGridRaw)
{
luaReturnInt(dsq->game->getGridRaw(TileVector(Vector(lua_tonumber(L, 1), lua_tonumber(L, 2)))));
}
luaFunc(isObstructedBlock) luaFunc(isObstructedBlock)
{ {
float x = lua_tonumber(L, 1); float x = lua_tonumber(L, 1);
@ -8568,13 +8583,14 @@ luaFunc(isShuttingDownGameState)
luaReturnBool(dsq->game->isShuttingDownGameState()); luaReturnBool(dsq->game->isShuttingDownGameState());
} }
// startx, starty, endx, endy [, step, xtab, ytab] // startx, starty, endx, endy [, step, xtab, ytab, obsMask]
luaFunc(findPath) luaFunc(findPath)
{ {
VectorPath path; VectorPath path;
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));
if(!dsq->pathFinding.generatePathSimple(path, start, end, lua_tointeger(L, 5))) ObsType obs = ObsType(lua_tointeger(L, 8));
if(!dsq->pathFinding.generatePathSimple(path, start, end, lua_tointeger(L, 5), obs))
luaReturnBool(false); luaReturnBool(false);
const unsigned num = path.getNumPathNodes(); const unsigned num = path.getNumPathNodes();
@ -8964,6 +8980,7 @@ static const struct {
luaRegister(reconstructGrid), luaRegister(reconstructGrid),
luaRegister(reconstructEntityGrid), luaRegister(reconstructEntityGrid),
luaRegister(dilateGrid),
luaRegister(ing_hasIET), luaRegister(ing_hasIET),
luaRegister(ing_getIngredientName), luaRegister(ing_getIngredientName),
@ -9463,6 +9480,7 @@ static const struct {
luaRegister(isObstructed), luaRegister(isObstructed),
luaRegister(isObstructedBlock), luaRegister(isObstructedBlock),
luaRegister(getObstruction), luaRegister(getObstruction),
luaRegister(getGridRaw),
luaRegister(findPath), luaRegister(findPath),
luaRegister(castLine), luaRegister(castLine),
luaRegister(getUserInputString), luaRegister(getUserInputString),
@ -10597,6 +10615,11 @@ static const struct {
luaConstant(OT_INVISIBLEIN), luaConstant(OT_INVISIBLEIN),
luaConstant(OT_HURT), luaConstant(OT_HURT),
luaConstant(OT_INVISIBLEENT), luaConstant(OT_INVISIBLEENT),
luaConstant(OT_USER1),
luaConstant(OT_USER2),
luaConstant(OT_MASK_BLACK),
luaConstant(OT_BLOCKING),
luaConstant(OT_USER_MASK),
luaConstant(SEE_MAP_NEVER), luaConstant(SEE_MAP_NEVER),
luaConstant(SEE_MAP_DEFAULT), luaConstant(SEE_MAP_DEFAULT),