mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-11-25 09:44:02 +00:00
Reduce Game::fillGrid() complexity from O(n^2) to O(n) when trimming
Eliminates stutter on slow machines or in debug mode when operating doors. Also the game shouldn't freeze anymore when marking very large tiles as obstructing.
This commit is contained in:
parent
4702cd238c
commit
b59fb507ca
2 changed files with 40 additions and 23 deletions
|
@ -421,37 +421,47 @@ void Game::fillGrid(const GridFiller& gf)
|
|||
}
|
||||
}
|
||||
|
||||
if(!obs.size()) // no obs -> nothing else to do here
|
||||
return;
|
||||
|
||||
if (gf.trim)
|
||||
{
|
||||
std::vector<TileVector> obsCopy;
|
||||
obsCopy.swap(obs);
|
||||
// obs now empty
|
||||
int minx = INT_MAX, maxx = 0, miny = INT_MAX, maxy = 0;
|
||||
for(size_t i = 0; i < obs.size(); ++i)
|
||||
{
|
||||
const TileVector& tv = obs[i];
|
||||
minx = std::min(minx, tv.x);
|
||||
maxx = std::max(maxx, tv.x);
|
||||
miny = std::min(miny, tv.y);
|
||||
maxy = std::max(maxy, tv.y);
|
||||
}
|
||||
if(minx == maxx || miny == maxy)
|
||||
return; // would get trimmed completely -> get out early
|
||||
|
||||
int sides = 0;
|
||||
for (size_t i = 0; i < obsCopy.size(); i++)
|
||||
Array2d<unsigned char> gr(size_t(maxx - minx) + 1, size_t(maxy - miny) + 1, 0);
|
||||
|
||||
for(size_t i = 0; i < obs.size(); ++i)
|
||||
{
|
||||
sides = 0;
|
||||
for (size_t j = 0; j < obsCopy.size(); j++)
|
||||
{
|
||||
if (i != j)
|
||||
{
|
||||
if (
|
||||
(obsCopy[j].x == obsCopy[i].x-1 && obsCopy[j].y == obsCopy[i].y)
|
||||
|| (obsCopy[j].x == obsCopy[i].x+1 && obsCopy[j].y == obsCopy[i].y)
|
||||
|| (obsCopy[j].y == obsCopy[i].y-1 && obsCopy[j].x == obsCopy[i].x)
|
||||
|| (obsCopy[j].y == obsCopy[i].y+1 && obsCopy[j].x == obsCopy[i].x)
|
||||
)
|
||||
{
|
||||
sides++;
|
||||
const TileVector& tv = obs[i];
|
||||
gr(size_t(tv.x - minx), size_t(tv.y - miny)) = 1;
|
||||
}
|
||||
if (sides>=4)
|
||||
|
||||
const size_t nx = gr.width() - 1;
|
||||
const size_t ny = gr.height() - 1;
|
||||
size_t idx = 0;
|
||||
for(size_t y = 1; y < ny; ++y)
|
||||
{
|
||||
obs.push_back(obsCopy[i]);
|
||||
break;
|
||||
}
|
||||
const unsigned char * const row = gr.row(y);
|
||||
for(size_t x = 1; x < nx; ++x)
|
||||
{
|
||||
if(row[x])
|
||||
{
|
||||
if(row[x-1] && row[x+1] && gr(x, y-1) && gr(x, y+1))
|
||||
obs[idx++] = TileVector(int(x) + minx, int(y) + miny);
|
||||
}
|
||||
}
|
||||
}
|
||||
obs.resize(idx);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ protected:
|
|||
public:
|
||||
Array2d() : _w(0), _h(0) {}
|
||||
Array2d(size_t w, size_t h) : _w(w), _h(h), _v(w*h) {}
|
||||
Array2d(size_t w, size_t h, const T& def) : _w(w), _h(h), _v(w*h, def) {}
|
||||
|
||||
size_t width() const {return _w;}
|
||||
size_t height() const {return _h;}
|
||||
|
@ -25,6 +26,12 @@ public:
|
|||
_h = h;
|
||||
_v.resize(w*h);
|
||||
}
|
||||
void init(size_t w, size_t h, const T& def)
|
||||
{
|
||||
_w = w;
|
||||
_h = h;
|
||||
_v.resize(w*h, def);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue