From cda06a5169a0ed908d189ce8370756d4cca11063 Mon Sep 17 00:00:00 2001 From: Andrew Kloet Date: Tue, 8 Jul 2025 11:08:38 -0400 Subject: [PATCH] fix segfault for real --- src/Aquarium.cpp | 43 +++++---- src/Castle.cpp | 2 +- src/SeaMonster.cpp | 5 +- src/Ship.cpp | 4 +- src/Whale.cpp | 4 +- src/assets/CastleAssets.h | 7 +- src/assets/SeaMonsterAssets.h | 44 +++++---- src/assets/ShipAssets.h | 32 +++++-- src/assets/WhaleAssets.h | 174 ++++++++++++++++++---------------- 9 files changed, 176 insertions(+), 139 deletions(-) diff --git a/src/Aquarium.cpp b/src/Aquarium.cpp index 1ec7be5..f453d37 100644 --- a/src/Aquarium.cpp +++ b/src/Aquarium.cpp @@ -47,15 +47,18 @@ void Aquarium::ensureEntitiesSorted() { void Aquarium::redraw() { clearCurrentFrame(); - ensureBigEntityExists(); - std::vector> newEntities; - bool entities_modified = false; + // Use static vectors to avoid per-frame allocations + static std::vector> newEntities; + static std::vector entitiesToRemove; - // Update and check for removal/replacement - for (auto it = entities.begin(); it != entities.end();) { - auto &entity = *it; + newEntities.clear(); + entitiesToRemove.clear(); + + // Update all entities and collect changes + for (size_t i = 0; i < entities.size(); ++i) { + auto &entity = entities[i]; entity->update(); // Handle fish bubble spawning @@ -69,30 +72,32 @@ void Aquarium::redraw() { if (entity->shouldBeRemoved()) { auto replacement = entity->createReplacement(); if (replacement) { - *it = std::move(replacement); - entities_modified = true; - ++it; + entity = std::move(replacement); // Replace in-place + entities_need_sorting = true; } else { - it = entities.erase(it); - entities_modified = true; + entitiesToRemove.push_back(i); // Mark for removal } - } else { - ++it; } } - // Add new entities if any + // Remove entities in reverse order to maintain indices + for (auto it = entitiesToRemove.rbegin(); it != entitiesToRemove.rend(); + ++it) { + entities.erase(entities.begin() + *it); + entities_need_sorting = true; + } + + // Add new entities (only if we have them) if (!newEntities.empty()) { + // Reserve space to minimize reallocations + entities.reserve(entities.size() + newEntities.size()); + for (auto &newEntity : newEntities) { entities.emplace_back(std::move(newEntity)); } - entities_modified = true; - } - - // Only sort if entities were modified - if (entities_modified) { entities_need_sorting = true; } + ensureEntitiesSorted(); // Draw all entities diff --git a/src/Castle.cpp b/src/Castle.cpp index 7be3320..33bd46b 100644 --- a/src/Castle.cpp +++ b/src/Castle.cpp @@ -5,4 +5,4 @@ Castle::Castle() : Entity(Aquarium::getInstance().getWidth() - 32, Aquarium::getInstance().getHeight() - 13), - image(castleAsset.image), mask(castleAsset.mask) {} + image(getCastleAsset().image), mask(getCastleAsset().mask) {} diff --git a/src/SeaMonster.cpp b/src/SeaMonster.cpp index eb3f9ad..1df34d5 100644 --- a/src/SeaMonster.cpp +++ b/src/SeaMonster.cpp @@ -6,8 +6,9 @@ SeaMonster::SeaMonster() : SeaMonster(getRandomDirection()) {} SeaMonster::SeaMonster(int asset_index) - : Entity(asset_index == 0), frames(seaMonsterAssets[asset_index].frames), - mask(seaMonsterAssets[asset_index].mask), speed(SEAMONSTER_SPEED) { + : Entity(asset_index == 0), + frames(getSeaMonsterAssets()[asset_index].frames), + mask(getSeaMonsterAssets()[asset_index].mask), speed(SEAMONSTER_SPEED) { const auto &aquarium = Aquarium::getInstance(); y = WATER_SURFACE_OFFSET; diff --git a/src/Ship.cpp b/src/Ship.cpp index d10d53f..e7e1ff9 100644 --- a/src/Ship.cpp +++ b/src/Ship.cpp @@ -6,8 +6,8 @@ Ship::Ship() : Ship(getRandomDirection()) {} Ship::Ship(int asset_index) - : Entity(asset_index == 0), image(shipAssets[asset_index].image), - mask(shipAssets[asset_index].mask), speed(SHIP_SPEED) { + : Entity(asset_index == 0), image(getShipAssets()[asset_index].image), + mask(getShipAssets()[asset_index].mask), speed(SHIP_SPEED) { const auto &aquarium = Aquarium::getInstance(); y = 0; diff --git a/src/Whale.cpp b/src/Whale.cpp index c30d7e9..435e980 100644 --- a/src/Whale.cpp +++ b/src/Whale.cpp @@ -6,8 +6,8 @@ Whale::Whale() : Whale(getRandomDirection()) {} Whale::Whale(int asset_index) - : Entity((asset_index == 0)), frames(whaleAssets[asset_index].frames), - mask(whaleAssets[asset_index].mask), speed(WHALE_SPEED) { + : Entity((asset_index == 0)), frames(getWhaleAssets()[asset_index].frames), + mask(getWhaleAssets()[asset_index].mask), speed(WHALE_SPEED) { const auto &aquarium = Aquarium::getInstance(); y = 0; diff --git a/src/assets/CastleAssets.h b/src/assets/CastleAssets.h index 0007a27..34be562 100644 --- a/src/assets/CastleAssets.h +++ b/src/assets/CastleAssets.h @@ -8,7 +8,8 @@ struct CastleAsset { std::vector mask; }; -inline CastleAsset castleAsset = { +inline const CastleAsset& getCastleAsset() { + static const CastleAsset castleAsset = { { R"( T~~)", R"( |)", @@ -37,4 +38,6 @@ inline CastleAsset castleAsset = { R"( yy yy)", R"( y y y y)", R"( yyyyyyy)"} -}; + }; + return castleAsset; +} diff --git a/src/assets/SeaMonsterAssets.h b/src/assets/SeaMonsterAssets.h index c91a071..8f44773 100644 --- a/src/assets/SeaMonsterAssets.h +++ b/src/assets/SeaMonsterAssets.h @@ -8,23 +8,31 @@ struct SeaMonsterAsset { std::vector mask; }; -const SeaMonsterAsset seaMonster = { - {// Frame 1 +inline const SeaMonsterAsset& getSeaMonster() { + static const SeaMonsterAsset seaMonster = { { - R"(?????????_???_?????????????????????_???_???????_a_a???)", - R"(???????_{.`=`.}_??????_???_??????_{.`=`.}_????{/ ''\_?)", - R"(?_????{.' _ '.}????{.`'`.}????{.' _ '.}??{| ._oo))", - R"({ \??{/ .'?'. \}??{/ .-. \}??{/ .'?'. \}?{/ |????)"}, - { - R"(??????????????????????_???_????????????????????_a_a???)", - R"(??_??????_???_??????_{.`=`.}_??????_???_??????{/ ''\_?)", - R"(?{ \????{.`'`.}????{.' _ '.}????{.`'`.}????{| ._oo))", - R"(??\ \??{/ .-. \}??{/ .'?'. \}??{/ .-. \}???{/ |????)"}}, - { - R"( W W )", - R"()", - R"()", - R"()"}}; + { + R"(?????????_???_?????????????????????_???_???????_a_a???)", + R"(???????_{.`=`.}_??????_???_??????_{.`=`.}_????{/ ''\_?)", + R"(?_????{.' _ '.}????{.`'`.}????{.' _ '.}??{| ._oo))", + R"({ \??{/ .'?'. \}??{/ .-. \}??{/ .'?'. \}?{/ |????)"}, + { + R"(??????????????????????_???_????????????????????_a_a???)", + R"(??_??????_???_??????_{.`=`.}_??????_???_??????{/ ''\_?)", + R"(?{ \????{.`'`.}????{.' _ '.}????{.`'`.}????{| ._oo))", + R"(??\ \??{/ .-. \}??{/ .'?'. \}??{/ .-. \}???{/ |????)"}}, + { + R"( W W )", + R"()", + R"()", + R"()" + } + }; + return seaMonster; +} -inline const std::vector seaMonsterAssets = - createBidirectionalFramedAssets(seaMonster); +inline const std::vector& getSeaMonsterAssets() { + static const std::vector seaMonsterAssets = + createBidirectionalFramedAssets(getSeaMonster()); + return seaMonsterAssets; +} diff --git a/src/assets/ShipAssets.h b/src/assets/ShipAssets.h index b84d2e3..20905c9 100644 --- a/src/assets/ShipAssets.h +++ b/src/assets/ShipAssets.h @@ -3,13 +3,27 @@ #include "../SpriteUtils.h" #include -const AssetPair ship = { - {R"( | | | )", R"( )_) )_) )_) )", - R"( )___))___))___)\ )", R"( )____)____)_____)\\ )", - R"(_____|____|____|____\\\__)", R"(\ /????)"}, - {R"( y y y )", R"()", R"( w )", - R"( ww )", R"(yyyyyyyyyyyyyyyyyyyywwwyy)", - R"(y y )"}}; +inline const AssetPair &getShip() { + static const AssetPair ship = { + { + R"( | | | )", + R"( )_) )_) )_) )", + R"( )___))___))___)\ )", + R"( )____)____)_____)\\ )", + R"(_____|____|____|____\\\__)", + R"(\ /????)"}, + { + R"( y y y )", + R"()", + R"( w )", + R"( ww )", + R"(yyyyyyyyyyyyyyyyyyyywwwyy)", + R"(y y )"}}; + return ship; +} -inline const std::vector shipAssets = - createBidirectionalAssets({ship}); +inline const std::vector &getShipAssets() { + static const std::vector shipAssets = + createBidirectionalAssets({getShip()}); + return shipAssets; +} diff --git a/src/assets/WhaleAssets.h b/src/assets/WhaleAssets.h index aa1efad..2fcbf9f 100644 --- a/src/assets/WhaleAssets.h +++ b/src/assets/WhaleAssets.h @@ -8,91 +8,97 @@ struct WhaleAsset { std::vector mask; }; -const WhaleAsset whale = { - { +inline const WhaleAsset& getWhale() { + static const WhaleAsset whale = { { - R"( )", + { + R"( )", + R"()", + R"()", + R"( .-----. )", + R"( .' `. )", + R"(,????/ (o) \)", + R"(\`._/ ,__)" + }, + { + R"( )", + R"()", + R"( : )", + R"( .-----. )", + R"( .' `. )", + R"(,????/ (o) \)", + R"(\`._/ ,__)" + }, + { + R"( )", + R"( : )", + R"( : )", + R"( .-----. )", + R"( .' `. )", + R"(,????/ (o) \)", + R"(\`._/ ,__)" + }, + { + R"( . . )", + R"( -:- )", + R"( : )", + R"( .-----. )", + R"( .' `. )", + R"(,????/ (o) \)", + R"(\`._/ ,__)" + }, + { + R"( . . )", + R"( .-.-. )", + R"( : )", + R"( .-----. )", + R"( .' `. )", + R"(,????/ (o) \)", + R"(\`._/ ,__)" + }, + { + R"( . . )", + R"( '.-:-.' )", + R"( ' : ' )", + R"( .-----. )", + R"( .' `. )", + R"(,????/ (o) \)", + R"(\`._/ ,__)" + }, + { + R"( )", + R"( .- -. )", + R"( ; : ; )", + R"( .-----. )", + R"( .' `. )", + R"(,????/ (o) \)", + R"(\`._/ ,__)" + }, + { + R"( )", + R"( )", + R"( ; ; )", + R"( .-----. )", + R"( .' `. )", + R"(,????/ (o) \)", + R"(\`._/ ,__)" + } + }, + { + R"( C C )", + R"( CCCCCCC )", + R"( C C C )", + R"()", R"()", - R"()", - R"( .-----. )", - R"( .' `. )", - R"(,????/ (o) \)", - R"(\`._/ ,__)" - }, - { - R"( )", - R"()", - R"( : )", - R"( .-----. )", - R"( .' `. )", - R"(,????/ (o) \)", - R"(\`._/ ,__)" - }, - { - R"( )", - R"( : )", - R"( : )", - R"( .-----. )", - R"( .' `. )", - R"(,????/ (o) \)", - R"(\`._/ ,__)" - }, - { - R"( . . )", - R"( -:- )", - R"( : )", - R"( .-----. )", - R"( .' `. )", - R"(,????/ (o) \)", - R"(\`._/ ,__)" - }, - { - R"( . . )", - R"( .-.-. )", - R"( : )", - R"( .-----. )", - R"( .' `. )", - R"(,????/ (o) \)", - R"(\`._/ ,__)" - }, - { - R"( . . )", - R"( '.-:-.' )", - R"( ' : ' )", - R"( .-----. )", - R"( .' `. )", - R"(,????/ (o) \)", - R"(\`._/ ,__)" - }, - { - R"( )", - R"( .- -. )", - R"( ; : ; )", - R"( .-----. )", - R"( .' `. )", - R"(,????/ (o) \)", - R"(\`._/ ,__)" - }, - { - R"( )", - R"( )", - R"( ; ; )", - R"( .-----. )", - R"( .' `. )", - R"(,????/ (o) \)", - R"(\`._/ ,__)" + R"( W )", + R"()" } - }, - { - R"( C C )", - R"( CCCCCCC )", - R"( C C C )", - R"()", - R"()", - R"( W )", - R"()" - } -}; + }; + return whale; +} -inline const std::vector whaleAssets = - createBidirectionalFramedAssets(whale); +inline const std::vector& getWhaleAssets() { + static const std::vector whaleAssets = + createBidirectionalFramedAssets(getWhale()); + return whaleAssets; +}