diff --git a/Aquaria/Game.cpp b/Aquaria/Game.cpp index deea079..fb82365 100644 --- a/Aquaria/Game.cpp +++ b/Aquaria/Game.cpp @@ -2176,15 +2176,29 @@ std::string Game::getNoteName(int n, const std::string &pre) return os.str(); } -void Game::reconstructEntityGrid() +void Game::clearDynamicGrid() { - for (int x = 0; x < MAX_GRID; x++) + // just to be sure in case the grid/type sizes change, + // otherwise there is a chance to write a few bytes over the end of the buffer -- FG + compile_assert(sizeof(grid) % sizeof(uint32) == 0); + + signed char *gridstart = &grid[0][0]; + uint32 *gridend = (uint32*)(gridstart + sizeof(grid)); + uint32 *gridptr = (uint32*)gridstart; + // mask out non-black bytes (which are those set by entites or tiles), + // use full uint32 rounds instead of single-bytes to speed things up. + const unsigned int mask = OT_MASK_BLACK | (OT_MASK_BLACK << 8) | (OT_MASK_BLACK << 16) | (OT_MASK_BLACK << 24); + do { - for (int y = 0; y < MAX_GRID; y++) - { - grid[x][y] = baseGrid[x][y]; - } + *gridptr &= mask; + ++gridptr; } + while(gridptr < gridend); +} + +void Game::reconstructEntityGrid() +{ + clearDynamicGrid(); FOR_ENTITIES(i) { @@ -2203,37 +2217,6 @@ void Game::reconstructGrid(bool force) { Element *e = dsq->getElement(i); e->fillGrid(); - /* - Element *e = dsq->getElement(i); - if (e->getElementType() == Element::BOX) - { - int w = e->getWidth()/TILE_SIZE; - int h = e->getHeight()/TILE_SIZE; - TileVector t(e->position); - - if (h <= 1) - { - for (int tx = t.x-w/2; tx < t.x+w/2; tx++) - { - setGrid(TileVector(tx, t.y), 1); - } - } - else - { - for (int tx = t.x-w/2; tx < t.x+w/2; tx++) - { - for (int ty = t.y-h/2; ty < t.y+h/2; ty++) - { - setGrid(TileVector(tx, ty), 1); - } - } - } - } - else if (e->templateIdx != -1 && e->bgLayer == 0) - { - setGrid(&elementTemplates[e->templateIdx], e->position, e->rotation.z); - } - */ } ObsRow *o; @@ -2246,23 +2229,37 @@ void Game::reconstructGrid(bool force) } } - for (int x = 0; x < MAX_GRID; x++) - { - for (int y = 0; y < MAX_GRID; y++) - { - baseGrid[x][y] = grid[x][y]; - } - } - FOR_ENTITIES(i) { Entity *e = *i; e->fillGrid(); } + trimGrid(); + dsq->pathFinding.generateZones(); } +void Game::trimGrid() +{ + // Prevent the left- and rightmost column of black tiles + // from beeing drawn. (The maps were designed with this mind...) + for (int x = 0; x < MAX_GRID; x++) + { + const signed char *curCol = dsq->game->getGridColumn(x); + const signed char *leftCol = dsq->game->getGridColumn(x-1); + const signed char *rightCol = dsq->game->getGridColumn(x+1); + for (int y = 0; y < MAX_GRID; y++) + { + if (curCol[y] & OT_MASK_BLACK) + { + if (!(leftCol[y] & OT_MASK_BLACK) || !(rightCol[y] & OT_MASK_BLACK)) + setGrid(TileVector(x, y), OT_BLACKINVIS); + } + } + } +} + float Game::getCoverage(Vector pos, int sampleArea) { TileVector t(pos); @@ -6773,6 +6770,10 @@ void Game::applyState() addRenderObject(gridRender3, LR_DEBUG_TEXT); gridRender3->alpha = 0; + edgeRender = new GridRender(OT_BLACKINVIS); + addRenderObject(edgeRender, LR_DEBUG_TEXT); + edgeRender->alpha = 0; + waterSurfaceRender = new WaterSurfaceRender(); //waterSurfaceRender->setRenderPass(-1); addRenderObject(waterSurfaceRender, LR_WATERSURFACE); @@ -8786,12 +8787,14 @@ void Game::toggleGridRender() gridRender->alpha.interpolateTo(0.5, t); gridRender2->alpha.interpolateTo(0.5, t); gridRender3->alpha.interpolateTo(0.5, t); + edgeRender->alpha.interpolateTo(0.5, t); } else if (gridRender->alpha == 0.5) { gridRender->alpha.interpolateTo(0, t); gridRender2->alpha.interpolateTo(0, t); gridRender3->alpha.interpolateTo(0, t); + edgeRender->alpha.interpolateTo(0, t); } } @@ -10872,13 +10875,10 @@ void Game::loadElementTemplates(std::string pack) void Game::clearGrid(int v) { - for (int x = 0; x < MAX_GRID; x++) - { - for (int y = 0; y < MAX_GRID; y++) - { - grid[x][y] = v; - } - } + // ensure that grid is really a byte-array + compile_assert(sizeof(grid) == MAX_GRID * MAX_GRID); + + memset(grid, v, sizeof(grid)); } void Game::resetFromTitle() diff --git a/Aquaria/Game.h b/Aquaria/Game.h index db4a922..8204807 100644 --- a/Aquaria/Game.h +++ b/Aquaria/Game.h @@ -596,13 +596,20 @@ typedef std::vector QuadArray; typedef std::list ElementUpdateList; +// Note: although this is a bitmask, only one of these values may be set at a time! enum ObsType { - OT_EMPTY = 0, - OT_INVISIBLE = 1, - OT_BLACK = 2, - OT_INVISIBLEIN = 3, - OT_HURT = 4 + OT_EMPTY = 0x00, + + // immutable + OT_BLACK = 0x01, + OT_BLACKINVIS = 0x02, // same as OT_BLACK, but not drawn + OT_MASK_BLACK = OT_BLACK | OT_BLACKINVIS, + + // set by entities or tiles + OT_INVISIBLE = 0x04, + OT_INVISIBLEIN = 0x08, + OT_HURT = 0x10, }; struct EntitySaveData @@ -641,6 +648,7 @@ public: const signed char *getGridColumn(int tileX); void setGrid(const TileVector &tile, int v); bool isObstructed(const TileVector &tile, int t = -1) const; + void trimGrid(); void clearPointers(); @@ -652,6 +660,7 @@ public: bool loadScene(std::string scene); void clearGrid(int v = 0); + void clearDynamicGrid(); void toggleWorldMap(); @@ -976,7 +985,7 @@ public: void createGradient(); std::string saveMusic; - GridRender *gridRender, *gridRender2, *gridRender3; + GridRender *gridRender, *gridRender2, *gridRender3, *edgeRender; void toggleGridRender(); ElementUpdateList elementUpdateList; @@ -1189,7 +1198,6 @@ protected: signed char grid[MAX_GRID][MAX_GRID]; - signed char baseGrid[MAX_GRID][MAX_GRID]; Quad *bg, *bg2; @@ -1223,7 +1231,7 @@ int Game::getGridRaw(unsigned int x, unsigned int y) const inline int Game::getGrid(const TileVector &tile) const { - if (tile.x < 0 || tile.x >= MAX_GRID || tile.y < 0 || tile.y >= MAX_GRID) return 1; + if (tile.x < 0 || tile.x >= MAX_GRID || tile.y < 0 || tile.y >= MAX_GRID) return OT_INVISIBLE; return grid[tile.x][tile.y]; } @@ -1246,10 +1254,7 @@ void Game::setGrid(const TileVector &tile, int v) } inline -bool Game::isObstructed(const TileVector &tile, int t) const +bool Game::isObstructed(const TileVector &tile, int t /* = -1 */) const { - if (t == -1) - return (getGrid(tile) != 0); - return getGrid(tile) == t; + return (getGrid(tile) & t); } - diff --git a/Aquaria/GridRender.cpp b/Aquaria/GridRender.cpp index 4d9958c..14e9a8d 100644 --- a/Aquaria/GridRender.cpp +++ b/Aquaria/GridRender.cpp @@ -77,6 +77,9 @@ void GridRender::onRender() 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; diff --git a/Aquaria/SceneEditor.cpp b/Aquaria/SceneEditor.cpp index 0996f9b..fc82be9 100644 --- a/Aquaria/SceneEditor.cpp +++ b/Aquaria/SceneEditor.cpp @@ -518,7 +518,7 @@ void SceneEditor::openMainMenu() addMainMenuItem("EDIT TILES (F5)", 106); addMainMenuItem("EDIT ENTITIES (F6)", 107); addMainMenuItem("EDIT NODES (F7)", 108); - addMainMenuItem("REGEN COLLISIONS (SHIFT-R)", 103); + addMainMenuItem("REGEN COLLISIONS (ALT-R)", 103); addMainMenuItem("RECACHE TEXTURES (CTRL-R)", 130); // addMainMenuItem("REFRESH DATAFILES (F11)", 117); addMainMenuItem("REGEN ROCK FROM MAPTEMPLATE (F11+F12)", 116); @@ -1949,12 +1949,12 @@ void SceneEditor::skinLevel(pngRawInfo *png, int minX, int minY, int maxX, int m float rot=0; bool addTile = false; TileVector t(x,y); - if (dsq->game->isObstructed(t,OT_BLACK) + if (dsq->game->isObstructed(t, OT_MASK_BLACK) && ( - !dsq->game->isObstructed(TileVector(x+1,y),OT_BLACK) || - !dsq->game->isObstructed(TileVector(x-1,y),OT_BLACK) || - !dsq->game->isObstructed(TileVector(x,y-1),OT_BLACK) || - !dsq->game->isObstructed(TileVector(x,y+1),OT_BLACK) + !dsq->game->isObstructed(TileVector(x+1,y), OT_MASK_BLACK) || + !dsq->game->isObstructed(TileVector(x-1,y), OT_MASK_BLACK) || + !dsq->game->isObstructed(TileVector(x,y-1), OT_MASK_BLACK) || + !dsq->game->isObstructed(TileVector(x,y+1), OT_MASK_BLACK) ) ) { @@ -1967,7 +1967,7 @@ void SceneEditor::skinLevel(pngRawInfo *png, int minX, int minY, int maxX, int m { */ float dist=0; - wallNormal = dsq->game->getWallNormal(t.worldVector(), 5, &dist, OT_BLACK); + wallNormal = dsq->game->getWallNormal(t.worldVector(), 5, &dist, OT_MASK_BLACK); offset = wallNormal*(-TILE_SIZE*0.6f); MathFunctions::calculateAngleBetweenVectorsInDegrees(Vector(0,0,0), wallNormal, rot); rot = 180-(360-rot); @@ -3919,22 +3919,12 @@ void SceneEditor::prevEntityType() void SceneEditor::dumpObs() { TileVector tv; - const uint32 A = 0xFF000000; -#define COL(c) (((0x ## c)) | A) - const uint32 coltab[5] = - { - COL(FFFFFF), - COL(FFFFFF), - COL(000000), - COL(FFFFFF), - COL(FFFFFF), - }; unsigned char *data = new unsigned char[MAX_GRID * MAX_GRID * sizeof(uint32)]; uint32 *ptr = (uint32*)data; for(tv.y = MAX_GRID - 1; ; --tv.y) { for(tv.x = 0; tv.x < MAX_GRID; ++tv.x) - *ptr++ = coltab[game->getGrid(tv)]; + *ptr++ = game->isObstructed(tv, OT_MASK_BLACK) ? 0xFF000000 : 0xFFFFFFFF; if(tv.y == 0) break; } diff --git a/Aquaria/ScriptInterface.cpp b/Aquaria/ScriptInterface.cpp index f59140e..e8b3da5 100644 --- a/Aquaria/ScriptInterface.cpp +++ b/Aquaria/ScriptInterface.cpp @@ -349,7 +349,6 @@ static void scriptDebug(lua_State *L, const std::string& msg) void compile_time_assertions() { #define oo(cls) offsetof(cls, _objtype) -#define compile_assert(pred) switch(0){case 0:case (pred):;} compile_assert(oo(Path) == oo(RenderObject)); compile_assert(oo(Path) == oo(Entity)); compile_assert(oo(Path) == oo(Ingredient)); @@ -364,7 +363,6 @@ void compile_time_assertions() compile_assert(oo(Path) == oo(Avatar)); compile_assert(oo(Path) == oo(BaseText)); #undef oo -#undef compile_assert } template diff --git a/BBGE/Base.h b/BBGE/Base.h index 5394bda..4e2e3c9 100644 --- a/BBGE/Base.h +++ b/BBGE/Base.h @@ -97,6 +97,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "glext.h" #endif +#define compile_assert(pred) switch(0){case 0:case (pred):;} #ifdef _MSC_VER #pragma warning(disable:4786)