diff --git a/desktop_version/src/BlockV.cpp b/desktop_version/src/BlockV.cpp index 74e6a45c..79b9745c 100644 --- a/desktop_version/src/BlockV.cpp +++ b/desktop_version/src/BlockV.cpp @@ -1,6 +1,11 @@ #include "BlockV.h" blockclass::blockclass() +{ + clear(); +} + +void blockclass::clear() { type = 0; trigger = 0; @@ -20,6 +25,11 @@ blockclass::blockclass() x = 0.0f; y = 0.0f; + + /* std::strings get initialized automatically, but this is */ + /* in case this function gets called again after construction */ + script.clear(); + prompt.clear(); } void blockclass::rectset(const int xi, const int yi, const int wi, const int hi) diff --git a/desktop_version/src/BlockV.h b/desktop_version/src/BlockV.h index 1e4a5977..4c65b0f4 100644 --- a/desktop_version/src/BlockV.h +++ b/desktop_version/src/BlockV.h @@ -8,6 +8,7 @@ class blockclass { public: blockclass(); + void clear(); void rectset(const int xi, const int yi, const int wi, const int hi); diff --git a/desktop_version/src/Ent.cpp b/desktop_version/src/Ent.cpp index 876f1ba2..f10a63c5 100644 --- a/desktop_version/src/Ent.cpp +++ b/desktop_version/src/Ent.cpp @@ -4,6 +4,11 @@ #include "Graphics.h" entclass::entclass() +{ + clear(); +} + +void entclass::clear() { invis = false; type = 0; diff --git a/desktop_version/src/Ent.h b/desktop_version/src/Ent.h index e4d6bdc3..b34cf29f 100644 --- a/desktop_version/src/Ent.h +++ b/desktop_version/src/Ent.h @@ -9,6 +9,7 @@ class entclass { public: entclass(); + void clear(); bool outside(); diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index d81a396c..7cea39ca 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -760,7 +760,35 @@ void entityclass::createblock( int t, int xp, int yp, int w, int h, int trig /*= { k = blocks.size(); - blockclass block; + blockclass newblock; + blockclass* blockptr; + + /* Can we reuse the slot of a disabled block? */ + bool reuse = false; + for (size_t i = 0; i < blocks.size(); ++i) + { + if (blocks[i].type == -1 + && blocks[i].wp == 0 + && blocks[i].hp == 0 + && blocks[i].rect.w == 0 + && blocks[i].rect.h == 0) + { + reuse = true; + blockptr = &blocks[i]; + break; + } + } + + if (!reuse) + { + blockptr = &newblock; + } + else + { + blockptr->clear(); + } + + blockclass& block = *blockptr; switch(t) { case BLOCK: //Block @@ -1038,23 +1066,31 @@ void entityclass::createblock( int t, int xp, int yp, int w, int h, int trig /*= break; } - blocks.push_back(block); + if (!reuse) + { + blocks.push_back(block); + } } -// Remove entity, and return true if entity was successfully removed -bool entityclass::removeentity(int t) +/* Disable entity, and return true if entity was successfully disabled */ +bool entityclass::disableentity(int t) { if (!INBOUNDS_VEC(t, entities)) { - puts("removeentity() out-of-bounds!"); + puts("disableentity() out-of-bounds!"); return true; } if (entities[t].rule == 0 && t == getplayer()) { - // Don't remove the player entity! + /* Don't disable the player entity! */ return false; } - entities.erase(entities.begin() + t); + + entities[t].invis = true; + entities[t].size = -1; + entities[t].type = -1; + entities[t].rule = -1; + return true; } @@ -1063,22 +1099,21 @@ void entityclass::removeallblocks() blocks.clear(); } -void entityclass::removeblock( int t ) +void entityclass::disableblock( int t ) { if (!INBOUNDS_VEC(t, blocks)) { - puts("removeblock() out-of-bounds!"); + puts("disableblock() out-of-bounds!"); return; } - blocks.erase(blocks.begin() + t); -} -void entityclass::removeblockat( int x, int y ) -{ - for (size_t i = 0; i < blocks.size(); i++) - { - if(blocks[i].xp == int(x) && blocks[i].yp == int(y)) removeblock_iter(i); - } + blocks[t].type = -1; + + blocks[t].wp = 0; + blocks[t].hp = 0; + + blocks[t].rect.w = blocks[t].wp; + blocks[t].rect.h = blocks[t].hp; } void entityclass::moveblockto(int x1, int y1, int x2, int y2, int w, int h) @@ -1099,17 +1134,13 @@ void entityclass::moveblockto(int x1, int y1, int x2, int y2, int w, int h) } } -void entityclass::nocollisionat(int x, int y) +void entityclass::disableblockat(int x, int y) { for (size_t i = 0; i < blocks.size(); i++) { if (blocks[i].xp == x && blocks[i].yp == y) { - blocks[i].wp = 0; - blocks[i].hp = 0; - - blocks[i].rect.w = blocks[i].wp; - blocks[i].rect.h = blocks[i].hp; + disableblock(i); } } } @@ -1120,7 +1151,7 @@ void entityclass::removetrigger( int t ) { if(blocks[i].type == TRIGGER && blocks[i].trigger == t) { - removeblock_iter(i); + disableblock(i); } } } @@ -1186,6 +1217,33 @@ void entityclass::createentity( float xp, float yp, int t, float vx /*= 0*/, flo { k = entities.size(); + entclass newent; + entclass* entptr; + + /* Can we reuse the slot of a disabled entity? */ + bool reuse = false; + for (size_t i = 0; i < entities.size(); ++i) + { + if (entities[i].invis + && entities[i].size == -1 + && entities[i].type == -1 + && entities[i].rule == -1) + { + reuse = true; + entptr = &entities[i]; + break; + } + } + + if (!reuse) + { + entptr = &newent; + } + else + { + entptr->clear(); + } + //Size 0 is a sprite //Size 1 is a tile //Beyond that are special cases (to do) @@ -1210,7 +1268,7 @@ void entityclass::createentity( float xp, float yp, int t, float vx /*= 0*/, flo bool custom_gray = false; #endif - entclass entity; + entclass& entity = *entptr; entity.xp = xp; entity.yp = yp; entity.lerpoldxp = xp; @@ -2128,7 +2186,10 @@ void entityclass::createentity( float xp, float yp, int t, float vx /*= 0*/, flo } } - entities.push_back(entity); + if (!reuse) + { + entities.push_back(entity); + } } //Returns true if entity is removed @@ -2324,13 +2385,13 @@ bool entityclass::updateentities( int i ) { if (entities[i].xp >= 335) { - return removeentity(i); + return disableentity(i); } if (game.roomx == 117) { if (entities[i].xp >= (33*8)-32) { - return removeentity(i); + return disableentity(i); } //collector for LIES } @@ -2359,13 +2420,13 @@ bool entityclass::updateentities( int i ) { if (entities[i].yp <= -60) { - return removeentity(i); + return disableentity(i); } if (game.roomx == 113 && game.roomy == 108) { if (entities[i].yp <= 60) { - return removeentity(i); + return disableentity(i); } //collector for factory } @@ -2520,7 +2581,7 @@ bool entityclass::updateentities( int i ) if (entities[i].life % 3 == 0) entities[i].tile++; if (entities[i].life <= 0) { - removeblockat(entities[i].xp, entities[i].yp); + disableblockat(entities[i].xp, entities[i].yp); entities[i].state = 3;// = false; entities[i].invis = true; } @@ -2566,8 +2627,8 @@ bool entityclass::updateentities( int i ) entities[i].tile++; if (entities[i].life <= 0) { - removeblockat(entities[i].xp, entities[i].yp); - return removeentity(i); + disableblockat(entities[i].xp, entities[i].yp); + return disableentity(i); } } break; @@ -2576,7 +2637,7 @@ bool entityclass::updateentities( int i ) if (entities[i].state == 1) { game.gravitycontrol = (game.gravitycontrol + 1) % 2; - return removeentity(i); + return disableentity(i); } break; @@ -2586,7 +2647,7 @@ bool entityclass::updateentities( int i ) entities[i].life--; if (entities[i].life < 0) { - return removeentity(i); + return disableentity(i); } } break; @@ -2600,7 +2661,7 @@ bool entityclass::updateentities( int i ) collect[(int) entities[i].para] = true; } - return removeentity(i); + return disableentity(i); } break; case 7: //Found a trinket @@ -2627,7 +2688,7 @@ bool entityclass::updateentities( int i ) } } - return removeentity(i); + return disableentity(i); } break; case 8: //Savepoints @@ -3143,7 +3204,7 @@ bool entityclass::updateentities( int i ) if (entities[i].xp >= 310) { game.scmprogress++; - return removeentity(i); + return disableentity(i); } } break; @@ -3168,7 +3229,7 @@ bool entityclass::updateentities( int i ) entities[i].vx = 7; if (entities[i].xp > 320) { - return removeentity(i); + return disableentity(i); } } break; @@ -3178,7 +3239,7 @@ bool entityclass::updateentities( int i ) entities[i].vx = -7; if (entities[i].xp <-20) { - return removeentity(i); + return disableentity(i); } } break; @@ -3273,7 +3334,7 @@ bool entityclass::updateentities( int i ) music.playef(27); } - return removeentity(i); + return disableentity(i); } break; case 100: //The teleporter @@ -4662,7 +4723,7 @@ void entityclass::collisioncheck(int i, int j, bool scm /*= false*/) { //Disable collision temporarily so we don't push the person out! //Collision will be restored at end of platform update loop in gamelogic - nocollisionat(entities[j].xp, entities[j].yp); + disableblockat(entities[j].xp, entities[j].yp); } break; case 3: //Entity to entity diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index 623559d5..e670d106 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -10,23 +10,6 @@ #include "BlockV.h" #include "Game.h" -#define removeentity_iter(index) \ - do \ - { \ - extern entityclass obj; \ - if (obj.removeentity(index)) \ - { \ - index--; \ - } \ - } while (false) -#define removeblock_iter(index) \ - do \ - { \ - extern entityclass obj; \ - obj.removeblock(index); \ - index--; \ - } while (false) - enum { BLOCK = 0, @@ -71,18 +54,16 @@ public: void createblock(int t, int xp, int yp, int w, int h, int trig = 0, const std::string& script = ""); - bool removeentity(int t); + bool disableentity(int t); void removeallblocks(); - void removeblock(int t); + void disableblock(int t); - void removeblockat(int x, int y); + void disableblockat(int x, int y); void moveblockto(int x1, int y1, int x2, int y2, int w, int h); - void nocollisionat(int x, int y); - void removetrigger(int t); void copylinecross(int t); diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index 5fe1c71a..e6e5e2ae 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -2173,7 +2173,7 @@ void Game::updatestate() i = obj.getcompanion(); if(INBOUNDS_VEC(i, obj.entities)) { - obj.removeentity(i); + obj.disableentity(i); } i = obj.getteleporter(); diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index 766fc641..10586806 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -1891,7 +1891,7 @@ void gameinput() if((int(SDL_fabsf(obj.entities[ie].vx))<=1) && (int(obj.entities[ie].vy) == 0) ) { script.load(obj.blocks[game.activeactivity].script); - obj.removeblock(game.activeactivity); + obj.disableblock(game.activeactivity); game.activeactivity = -1; } } diff --git a/desktop_version/src/Logic.cpp b/desktop_version/src/Logic.cpp index d1c097e9..9d8b03ad 100644 --- a/desktop_version/src/Logic.cpp +++ b/desktop_version/src/Logic.cpp @@ -347,7 +347,7 @@ void gamelogic() //(and if the tile wasn't there it would pass straight through again) int prevx = obj.entities[i].xp; int prevy = obj.entities[i].yp; - obj.nocollisionat(prevx, prevy); + obj.disableblockat(prevx, prevy); obj.entities[i].xp = 152; obj.entities[i].newxp = 152; @@ -668,7 +668,7 @@ void gamelogic() obj.entities[line].xp += 24; if (obj.entities[line].xp > 320) { - obj.removeentity(line); + obj.disableentity(line); game.swngame = 8; } } @@ -783,7 +783,7 @@ void gamelogic() int prevx = obj.entities[i].xp; int prevy = obj.entities[i].yp; - obj.nocollisionat(prevx, prevy); + obj.disableblockat(prevx, prevy); bool entitygone = obj.updateentities(i); // Behavioral logic if (entitygone) continue; @@ -811,7 +811,7 @@ void gamelogic() int prevx = obj.entities[ie].xp; int prevy = obj.entities[ie].yp; - obj.nocollisionat(prevx, prevy); + obj.disableblockat(prevx, prevy); bool entitygone = obj.updateentities(ie); // Behavioral logic if (entitygone) continue; diff --git a/desktop_version/src/Map.cpp b/desktop_version/src/Map.cpp index 45762a64..7f510874 100644 --- a/desktop_version/src/Map.cpp +++ b/desktop_version/src/Map.cpp @@ -871,11 +871,25 @@ void mapclass::gotoroom(int rx, int ry) } } - for (size_t i = 0; i < obj.entities.size(); i++) + /* Disable all entities in the room, and deallocate any unnecessary entity slots. */ + /* However don't disable player entities, but do preserve holes between them (if any). */ + bool player_found = false; + for (int i = obj.entities.size() - 1; i >= 0; --i) { - if (obj.entities[i].rule != 0) + /* Iterate in reverse order to prevent unnecessary indice shifting */ + if (obj.entities[i].rule == 0) { - removeentity_iter(i); + player_found = true; + continue; + } + + if (!player_found) + { + obj.entities.erase(obj.entities.begin() + i); + } + else + { + obj.disableentity(i); } } diff --git a/desktop_version/src/Script.cpp b/desktop_version/src/Script.cpp index 35d47cb4..befa16c1 100644 --- a/desktop_version/src/Script.cpp +++ b/desktop_version/src/Script.cpp @@ -167,16 +167,16 @@ void scriptclass::run() { if(words[1]=="gravitylines"){ for(size_t edi=0; edi