#include "game.h" #include "transform_system.h" #include "animation_system.h" #include "character_system.h" #include "camera_system.h" #include "script_system.h" int Game::emplaceSprite(std::string alias) { int id; if (idsToReuse_.empty()) { id = sprites_.size(); sprites_.emplace_back(); sprites_.back().alias = alias; } else { id = idsToReuse_.front(); idsToReuse_.pop_front(); sprites_[id] = Sprite(); sprites_[id].alias = alias; } spriteIds_.insert(id); spritesByAlias_[alias] = id; return id; } void Game::destroySprite(int id) { for (std::unique_ptr& system : systems_) { system->destroySprite(id); } spriteIds_.erase(id); idsToReuse_.push_back(id); spritesByAlias_.erase(sprites_.at(id).alias); } void Game::loadMap(std::string filename) { // Clear out non-persistent sprites. std::list spritesToDelete; for (int spriteId : spriteIds_) { Sprite& sprite = sprites_.at(spriteId); if (!sprite.persistent) { spritesToDelete.push_back(spriteId); } } for (int spriteId : spritesToDelete) { destroySprite(spriteId); } // Load the new map. map_ = std::make_unique(filename); std::vector> backgroundScripts; for (const Prototype& p : map_->getPrototypes()) { if (spritesByAlias_.count(p.name)) continue; int spriteId = emplaceSprite(p.name); getSystem().initSprite(spriteId, p.pos, p.masked ? SpriteLayer::Mask : SpriteLayer::Normal); getSystem().setUpCollision(spriteId, p.collisionOffset, p.collisionSize, true); if (!p.animationFilename.empty()) { getSystem().initSprite(spriteId, p.animationFilename); getSprite(spriteId).normallyHasShadow = p.shadow; if (!p.animName.empty()) { getSystem().setSpriteAnimation(spriteId, p.animName); } getSystem().setSpriteDirection(spriteId, p.dir); } getSprite(spriteId).interactionScript = p.interactionScript; if (p.movementSpeed != -1) { getSystem().initSprite(spriteId, p.movementSpeed); if (p.wander) { getSprite(spriteId).behaviourType = BehaviourType::Wander; } if (!p.bumpPlayerScript.empty()) { getSprite(spriteId).bumpPlayerScript = p.bumpPlayerScript; } } if (!p.enclosureZone.empty()) { getSprite(spriteId).enclosureZone = p.enclosureZone; } if (p.mirrorType != MirrorType::None) { getSprite(spriteId).mirrorType = p.mirrorType; getSprite(spriteId).mirrorAxis = p.mirrorAxis; getSprite(spriteId).mirroredSpriteId = getSpriteByAlias(p.spriteToMirror); } if (!p.backgroundScript.empty()) { backgroundScripts.push_back({spriteId, p.backgroundScript}); } getSprite(spriteId).floating = p.floating; } for (const Trigger& t : map_->getTriggers()) { if (spritesByAlias_.count(t.name)) continue; int spriteId = emplaceSprite(t.name); getSystem().initSprite(spriteId, t.pos); getSystem().setUpCollision(spriteId, {0, 0}, t.size, false); getSprite(spriteId).walkthroughScript = t.script; } // Run the map's init script. if (getSystem().mapHasScript(map_->getName(), "init")) { getSystem().runScript(map_->getName(), "init"); } // Run any background scripts associated with new sprites. for (auto& [spriteId, scriptName] : backgroundScripts) { getSystem().runScript(map_->getName(), scriptName, spriteId); } }