void Spritesheet::parseFrames(Json::Value& rootElement) { // Get the frames array in the spritesheet data Json::Value& framesElement = rootElement["frames"]; numFrames = framesElement.size(); // This spritesheet is well-formed only if the "frames" element is a non-empty array // (i.e. there are frames in the spritesheet) if(!framesElement.isArray() || numFrames <= 0) { DEBUG("No frames found in spritesheet."); T_T("Empty (invalid) spritesheet constructed."); } DEBUG("Loading frames..."); frameList = new SpriteFrame[numFrames]; for(int i = 0; i < numFrames; ++i) { Json::Value& currFrame = framesElement[i]; // Get the current frame name std::string frameName = currFrame["name"].asString(); if(frameName == UNTITLED_LINE) { // Skip untitled frames. continue; } // Make sure this frame name has not already been used in this file if(frameIndices.find(frameName) != frameIndices.end()) { DEBUG("Duplicated name %s in spritesheet.", frameName.c_str()); T_T("Parse error reading spritesheet."); } else { DEBUG("Adding frame %s...", frameName.c_str()); } // Get the frame rectangle coordinates int left = currFrame["left"].asInt(); int top = currFrame["top"].asInt(); int right = currFrame["right"].asInt(); int bottom = currFrame["bottom"].asInt(); frameList[i] = SpriteFrame(left, top, right, bottom); DEBUG("Frame %s loaded in with coordinates %d, %d, %d, %d", frameName.c_str(), left, top, right, bottom); frameIndices[frameName] = i; } DEBUG("Frames loaded."); }
void Settings::save(std::ostream& output) { if(!output) { T_T("Failed to write settings data."); } Json::Value jsonRoot; jsonRoot["musicEnabled"] = m_musicEnabled; jsonRoot["soundEnabled"] = m_soundEnabled; jsonRoot["fullScreenEnabled"] = m_fullScreenEnabled; Json::Value& resolutionSettings = jsonRoot["resolution"] = Json::Value(Json::objectValue); resolutionSettings["bitsPerPixel"] = m_resolution.bitsPerPixel; resolutionSettings["height"] = m_resolution.height; resolutionSettings["width"] = m_resolution.width; output << jsonRoot; if(m_settingsSnapshot) { m_settingsSnapshot->setSettings(*this); } }
void Music::load(const char* path) { music = Mix_LoadMUS(path); if(music == NULL) { T_T(Mix_GetError()); } }
void PlayerDataSummary::load(const std::string& path) { DEBUG("Loading save file %s", path.c_str()); std::ifstream input(path.c_str()); if(!input) { T_T("Failed to open save game file for reading."); } Json::Value jsonRoot; input >> jsonRoot; if(jsonRoot.isNull()) { DEBUG("Unexpected root element name."); T_T("Failed to parse save data."); } parseCharactersAndParty(jsonRoot); }
void MenuState::activate() { if(menuPane == NULL) { DEBUG("Missing menu pane for the menu! Please initialize it by calling setMenuPane in the subclass."); T_T("Missing menu pane for the menu!"); } GameState::activate(); menuShell.setActiveState(this); menuPane->setVisible(true); }
void XRegion::load(const char* path) { struct dirent *entry; DIR *dp; std::vector<std::string> files; dp = opendir(path); if (dp == NULL) { T_T("opendir"); } while((entry = readdir(dp))) { std::string filename(entry->d_name); if(filename.length() > 4 && filename.substr(filename.length() - 4, 4) == ".tmx") { files.push_back(filename); } } closedir(dp); for(std::vector<std::string>::iterator iter = files.begin(); iter != files.end(); ++iter) { std::string mapFile(std::string(path) + *iter); try { Map* nextMap = new XMap(iter->substr(0, iter->length() - 4), mapFile); areas[nextMap->getName()] = nextMap; } catch(Exception e) { T_T(std::string("Malformed map in map file: ") + mapFile + '\n' + e.getMessage()); } } }
void Spritesheet::load(const std::string& path) { // Load the image itself into a texture using GraphicsUtil std::string imgPath(path); imgPath += IMG_EXTENSION; DEBUG("Loading spritesheet image \"%s\"...", imgPath.c_str()); texture = new Texture(imgPath); size = texture->getSize(); // Load in the spritesheet data file, which tells the engine where // each frame is in the image std::string dataPath(path); dataPath += DATA_EXTENSION; DEBUG("Loading spritesheet data \"%s\"...", dataPath.c_str()); std::ifstream input(dataPath.c_str()); if(!input.is_open()) { T_T(std::string("Error opening file: ") + dataPath); } // Read in the JSON data in the file Json::Value jsonRoot; input >> jsonRoot; if(jsonRoot.isNull()) { DEBUG("Unexpected root element name."); T_T("Failed to parse spritesheet data."); } parseFrames(jsonRoot); parseAnimations(jsonRoot); DEBUG("Spritesheet constructed!"); }
void Sound::load(const std::string& path) { std::lock_guard<decltype(m_playbackMutex)> lock(m_playbackMutex); DEBUG("Sound \"%s\": Loading WAV %s", getResourceName().c_str(), path.c_str()); auto sound = Mix_LoadWAV(path.c_str()); if(!sound) { T_T(Mix_GetError()); } DEBUG("Sound \"%s\": Successfully loaded WAV %s.", getResourceName().c_str(), path.c_str()); m_sound.reset(sound); }
void Sound::load(const char* path) { /** * \todo This should only be called once. Move it into initialization code. */ Mix_ChannelFinished(&Sound::channelFinished); DEBUG("Loading WAV %s", path); sound = Mix_LoadWAV(path); if(sound == NULL) { T_T(Mix_GetError()); } DEBUG("Successfully loaded WAV %s.", path); }
int Scheduler::block(const std::shared_ptr<Task>& pendingTask, int numResults) { DEBUG("Blocking coroutine %d on task %d...", m_runningCoroutine->getId(), pendingTask->m_id); // Find the coroutine in the ready list if(m_readyCoroutines.find(m_runningCoroutine) != m_readyCoroutines.end()) { // If the coroutine is in the ready list, push it into the finished coroutine list DEBUG("Putting coroutine %d in the finish list", m_runningCoroutine->getId()); m_finishedCoroutines.push_back(m_runningCoroutine); printFinishedQueue(); // Add the coroutine to the blocked list m_blockedCoroutines[pendingTask->m_id] = m_runningCoroutine; } else { T_T("Attempting to block a coroutine that isn't ready/running!"); } DEBUG("Yielding: %d", m_runningCoroutine->getId()); return m_runningCoroutine->yield(numResults); }
int Scheduler::join(const std::shared_ptr<Coroutine>& coroutine, int numResults) { DEBUG("Joining coroutine %d on coroutine %d...", m_runningCoroutine->getId(), coroutine->getId()); // Find the coroutine in the ready list if(m_readyCoroutines.find(m_runningCoroutine) != m_readyCoroutines.end()) { // If the coroutine is in the ready list, push it into the finished coroutine list DEBUG("Putting coroutine %d in the finish list", m_runningCoroutine->getId()); m_finishedCoroutines.push_back(m_runningCoroutine); printFinishedQueue(); // Add the coroutine to the joining list m_joiningCoroutines[coroutine] = m_runningCoroutine; } else { T_T("Attempting to suspend a coroutine that isn't ready/running!"); } DEBUG("Yielding: %d", m_runningCoroutine->getId()); return m_runningCoroutine->yield(numResults); }
void Tileset::load(const std::string& path) { DEBUG("Loading tileset file %s", path.c_str()); std::ifstream input(path.c_str()); if(!input) { T_T("Failed to open tileset file for reading."); } TiXmlDocument xmlDoc; input >> xmlDoc; if(xmlDoc.Error()) { DEBUG("Error occurred in tileset XML parsing: %s", xmlDoc.ErrorDesc()); T_T("Failed to parse tileset data."); } TiXmlElement* root = xmlDoc.RootElement(); if(strcmp(root->Value(), "tileset") != 0) { DEBUG("Unexpected root element name."); T_T("Failed to parse tileset data."); } TiXmlElement* imageElement = root->FirstChildElement("image"); if(imageElement == nullptr) { DEBUG("Expected image data in tileset."); T_T("Failed to parse tileset data."); } std::string imagePath = imageElement->Attribute("source"); DEBUG("Loading tileset image \"%s\"...", imagePath.c_str()); m_texture.reset(new Texture(std::string("data/tilesets/") + imagePath)); m_size = m_texture->getSize() / TileEngine::TILE_SIZE; m_collisionShapes.resize(m_size.getArea()); auto const* tileElement = root->FirstChildElement("tile"); for(;tileElement != nullptr; tileElement = tileElement->NextSiblingElement("tile")) { int tileNum = -1; tileElement->Attribute("id", &tileNum); if(tileNum < 0) { continue; } auto& collisionShape = m_collisionShapes[tileNum]; // Retrieve the collision shape information for this tile const auto objectGroupElement = tileElement->FirstChildElement("objectgroup"); if(objectGroupElement) { const auto collisionElement = objectGroupElement->FirstChildElement("object"); if(collisionElement) { collisionShape.left = std::stoi(collisionElement->Attribute("x")) / TileEngine::TILE_SIZE; collisionShape.top = std::stoi(collisionElement->Attribute("y")) / TileEngine::TILE_SIZE; const auto collisionWidth = std::stoi(collisionElement->Attribute("width")) / TileEngine::TILE_SIZE; const auto collisionHeight = std::stoi(collisionElement->Attribute("height")) / TileEngine::TILE_SIZE; collisionShape.right = collisionShape.left + collisionWidth; collisionShape.bottom = collisionShape.top + collisionHeight; } } } }
Map::Map(const std::string& name, const std::string& filePath) : m_name(name) { DEBUG("Loading map file %s", filePath.c_str()); std::ifstream input(filePath.c_str()); if(!input) { T_T("Failed to open map file for reading."); } TiXmlDocument xmlDoc; input >> xmlDoc; if(xmlDoc.Error()) { DEBUG("Error occurred in map XML parsing: %s", xmlDoc.ErrorDesc()); T_T("Failed to parse map data."); } const TiXmlElement* root = xmlDoc.RootElement(); if(strcmp(root->Value(), "map") != 0) { DEBUG("Unexpected root element name."); T_T("Failed to parse map data."); } int width; int height; root->Attribute("width", &width); root->Attribute("height", &height); m_bounds = geometry::Rectangle(geometry::Point2D::ORIGIN, geometry::Size(width, height)); const TiXmlElement* layerElement = root->FirstChildElement("layer"); while(layerElement != nullptr) { const std::string layerName(layerElement->Attribute("name")); if(layerName == "background") { // This 'new' is being emplaced into a unique_ptr and therefore // cleanup will be handled automatically. m_backgroundLayers.emplace_back(new Layer(layerElement, m_bounds)); DEBUG("Background layer added."); } else if(layerName == "foreground") { // This 'new' is being emplaced into a unique_ptr and therefore // cleanup will be handled automatically. m_foregroundLayers.emplace_back(new Layer(layerElement, m_bounds)); DEBUG("Foreground layer added."); } layerElement = layerElement->NextSiblingElement("layer"); } initializePassibilityMatrix(); bool hasCollisionLayer = false; bool hasEntrancesLayer = false; bool hasExitsLayer = false; bool hasTriggersLayer = false; bool hasNPCLayer = false; auto const* objectGroupElement = root->FirstChildElement("objectgroup"); while(objectGroupElement != nullptr) { std::string objectGroupName = objectGroupElement->Attribute("name"); if(objectGroupName == "collision" && !hasCollisionLayer) { parseCollisionGroup(objectGroupElement); hasCollisionLayer = true; } else if(objectGroupName == "entrances" && !hasEntrancesLayer) { parseMapEntrancesGroup(objectGroupElement); hasEntrancesLayer = true; } else if(objectGroupName == "exits" && !hasExitsLayer) { parseMapExitsGroup(objectGroupElement); hasExitsLayer = true; } else if(objectGroupName == "triggers" && !hasTriggersLayer) { parseMapTriggersGroup(objectGroupElement); hasTriggersLayer = true; } else if(objectGroupName == "npcs" && !hasNPCLayer) { parseNPCGroup(objectGroupElement); hasNPCLayer = true; } objectGroupElement = objectGroupElement->NextSiblingElement("objectgroup"); } DEBUG("Map loaded."); }
void Spritesheet::parseAnimations(Json::Value& rootElement) { Json::Value& animsElement = rootElement["animations"]; int numAnimations = animsElement.size(); if(!animsElement.isArray() || numAnimations <= 0) { DEBUG("No animations found in spritesheet."); return; } for(int i = 0; i < numAnimations; ++i) { Json::Value& currAnimation = animsElement[i]; // Get the name of the animation std::string animationName = currAnimation["name"].asString(); if(animationName == UNTITLED_LINE) { // Skip untitled animations continue; } // Make sure this animation name has not already been used in this file if(animationList.find(animationName) != animationList.end()) { DEBUG("Duplicated animation name %s in spritesheet.", animationName.c_str()); T_T("Parse error reading spritesheet."); } // Get the frames of the animation FrameSequence* frameSequence = new FrameSequence(); Json::Value& frameArray = currAnimation["frames"]; int sequenceLength = frameArray.size(); if(!frameArray.isArray() || sequenceLength <= 0) { // There should be no such thing as an animation without a non-empty array of frames DEBUG("Encountered malformed animation %s.", animationName.c_str()); T_T("Parse error reading spritesheet."); } for(int i = 0; i < sequenceLength; ++i) { // Get the name of the next frame in the animation std::string frameName = frameArray[i].asString(); // Ensure that the frame exists in the frame list and grab the associated frame index std::map<std::string, int>::const_iterator frameIndexIter = frameIndices.find(frameName); if(frameIndexIter == frameIndices.end()) { DEBUG("Found invalid frame name '%s' in animation %s", frameName.c_str(), animationName.c_str()); T_T("Parse error reading spritesheet."); } int frameIndex = frameIndexIter->second; DEBUG("Animation %s: Adding node with index %d", animationName.c_str(), frameIndex); // Add the retrieved frame index into the sequence of frames frameSequence->push_back(frameIndex); } // Bind the animation name to the next available animation index animationList[animationName] = frameSequence; } }