Public Group

This topic is 703 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

So I am loading a tiled map file using TinyXML but the only problem is, if I load the files in update the map is unplayable due to lag, yet if I wanted multiple levels, this is the only possible way to do it, I can't load the files in setup because it won't update to the new map. Any ideas on how to successfully do this?

Level.cpp

bool Level::LoadFromFile(std::string filename)
{
TiXmlDocument levelFile(filename.c_str());

{
std::cout << "Loading level \"" << filename << "\" failed." << std::endl;
return false;
}

//Map element. This is the root element for the whole file.
TiXmlElement *map;
map = levelFile.FirstChildElement("map");

//Set up misc map properties.
width = atoi(map->Attribute("width"));
height = atoi(map->Attribute("height"));
tileWidth = atoi(map->Attribute("tilewidth"));
tileHeight = atoi(map->Attribute("tileheight"));

//Tileset stuff
TiXmlElement *tilesetElement;
tilesetElement = map->FirstChildElement("tileset");
firstTileID = atoi(tilesetElement->Attribute("firstgid"));

//Tileset image
TiXmlElement *image;
image = tilesetElement->FirstChildElement("image");
std::string imagepath = image->Attribute("source");

{
std::cout << "Failed to load tile sheet." << std::endl;
return false;
}

tilesetImage.SetSmooth(false);

//Columns and rows (of tileset image)
int columns = tilesetImage.GetWidth() / tileWidth;
int rows = tilesetImage.GetHeight() / tileHeight;

std::vector <sf::Rect<int> > subRects;//container of subrects (to divide the tilesheet image up)

//tiles/subrects are counted from 0, left to right, top to bottom
for (int y = 0; y < rows; y++)
{
for (int x = 0; x < columns; x++)
{
sf::Rect <int> rect;
rect.Top = y * tileHeight;
rect.Bottom = y * tileHeight + tileHeight;
rect.Left = x * tileWidth;
rect.Right = x * tileWidth + tileWidth;
subRects.push_back(rect);
}
}

//Layers
TiXmlElement *layerElement;
layerElement = map->FirstChildElement("layer");
while (layerElement)
{
Layer layer;
if (layerElement->Attribute("opacity") != NULL)//check if opacity attribute exists
{
float opacity = strtod(layerElement->Attribute("opacity"), NULL);//convert the (string) opacity element to float
layer.opacity = 255 * opacity;
}
else
{
layer.opacity = 255;//if the attribute doesnt exist, default to full opacity
}

//Tiles
TiXmlElement *layerDataElement;
layerDataElement = layerElement->FirstChildElement("data");

if (layerDataElement == NULL)
{
std::cout << "Bad map. No layer information found." << std::endl;
}

TiXmlElement *tileElement;
tileElement = layerDataElement->FirstChildElement("tile");

if (tileElement == NULL)
{
std::cout << "Bad map. No tile information found." << std::endl;
return false;
}

int x = 0;
int y = 0;

while (tileElement)
{
int tileGID = atoi(tileElement->Attribute("gid"));
int subRectToUse = tileGID - firstTileID;//Work out the subrect ID to 'chop up' the tilesheet image.
if (subRectToUse >= 0)//we only need to (and only can) create a sprite/tile if there is one to display
{
sf::Sprite sprite;//sprite for the tile
sprite.SetImage(tilesetImage);
sprite.SetSubRect(subRects[subRectToUse]);
sprite.SetPosition(x * tileWidth, y * tileHeight);

sprite.SetColor(sf::Color(255, 255, 255, layer.opacity));//Set opacity of the tile.

layer.tiles.push_back(sprite);
}

tileElement = tileElement->NextSiblingElement("tile");

//increment x, y
x++;
if (x >= width)//if x has "hit" the end (right) of the map, reset it to the start (left)
{
x = 0;
y++;
if (y >= height)
{
y = 0;
}
}
}

layers.push_back(layer);

layerElement = layerElement->NextSiblingElement("layer");
}

//Objects
TiXmlElement *objectGroupElement;
if (map->FirstChildElement("objectgroup") != NULL)//Check that there is atleast one object layer
{
objectGroupElement = map->FirstChildElement("objectgroup");
while (objectGroupElement)//loop through object layers
{
TiXmlElement *objectElement;
objectElement = objectGroupElement->FirstChildElement("object");
while (objectElement)//loop through objects
{
std::string objectType;
if (objectElement->Attribute("type") != NULL)
{
objectType = objectElement->Attribute("type");
}
std::string objectName;
if (objectElement->Attribute("name") != NULL)
{
objectName = objectElement->Attribute("name");
}
int x = atoi(objectElement->Attribute("x"));
int y = atoi(objectElement->Attribute("y"));
int width = atoi(objectElement->Attribute("width"));
int height = atoi(objectElement->Attribute("height"));

Object object;
object.name = objectName;
object.type = objectType;

sf::Rect <int> objectRect;
objectRect.Top = y;
objectRect.Left = x;
objectRect.Bottom = y + height;
objectRect.Right = x + width;

if (objectType == "solid")
{
solidObjects.push_back(objectRect);
}

object.rect = objectRect;

TiXmlElement *properties;
properties = objectElement->FirstChildElement("properties");
if (properties != NULL)
{
TiXmlElement *prop;
prop = properties->FirstChildElement("property");
if (prop != NULL)
{
while(prop)
{
std::string propertyName = prop->Attribute("name");
std::string propertyValue = prop->Attribute("value");

object.properties[propertyName] = propertyValue;

prop = prop->NextSiblingElement("property");
}
}
}

objects.push_back(object);

objectElement = objectElement->NextSiblingElement("object");
}
objectGroupElement = objectGroupElement->NextSiblingElement("objectgroup");
}
}
else
{
std::cout << "No object layers found..." << std::endl;
}

return true;
}

Edited by Elit3d

##### Share on other sites

Without more information on what kind of game it is, and how the level data is used, it's hard to answer, but I'll take a stab.

##### Share on other sites

Without more information on what kind of game it is, and how the level data is used, it's hard to answer, but I'll take a stab.

I'll try to be more specific, and yes most likely I will have a loading screen(I also tried to load the maps using the loading screen state but that doesn't allow my collision to work). So after level 1 is finished, I would like to then load level 2 but because the setup already calls level 1 to begin with I cant set the next level as its not updating, wouldn't I need to handle the level changing in the update rather than the setup function? However doing this method in the Update function lags my game as it is constantly loading the LoadFromFile(std::string filename) function over and over.

##### Share on other sites

You should not load your level every frame, you should only load your level when you reach a new level (unless you are streaming a large level, in which case the same logic applies at a different scale: You shouldn't load the same level segment every frame, you should only load a new level segment when you reach the new level segment).

Ignoring how you load your level, can you post the code that shows *where* you load you level? That is to say, can you post the entire function that calls "LoadFromFile()" and the entire function that calls that function, and the entire function that calls that function, all the way back to main()?

I need to see the complete code for the entire callstack of LoadFromFile(), because that's almost certainly where your problem is.

I heavily disagree that you should look into multithreading your program - that'd be way too much over-complication at your level.

##### Share on other sites

if I load the files in update the map is unplayable due to lag, yet if I wanted multiple levels, this is the only possible way to do it, I can't load the files in setup because it won't update to the new map.

If you can't load a new map in setup, then your setup is in the wrong place. Perhaps you need two setup stages, one at the start of the application for the shared data, and one for each time you load a level, just for the data relevant to that level.

##### Share on other sites

I'll try to be more specific, and yes most likely I will have a loading screen(I also tried to load the maps using the loading screen state but that doesn't allow my collision to work). So after level 1 is finished, I would like to then load level 2 but because the setup already calls level 1 to begin with I cant set the next level as its not updating, wouldn't I need to handle the level changing in the update rather than the setup function? However doing this method in the Update function lags my game as it is constantly loading the LoadFromFile(std::string filename) function over and over.

I was under the impression you were trying to load on the fly.  Since it's at an obvious stopping point, I don't understand why you can't move to a loading state, throw up a "loading level" screen and load everything you need right then.  When the level is loaded, you can go back to the playing state and start on the new level.  Multi-threading is definitely not needed in this situation.

Edited by BeerNutts

##### Share on other sites

Just wanted to feedback to this thread that I managed to fix my issue, thanks everyone for the help as it allowed me to tackle my problem from another angle. What I decided to do was to load my level file from the load screen state and then I changed how my collision worked. So now it all works without lag. Many thanks everyone for the help!

##### Share on other sites

marked for tracking

##### Share on other sites

marked for tracking

1. 1
2. 2
3. 3
Rutin
19
4. 4
5. 5

• 10
• 14
• 30
• 13
• 11
• ### Forum Statistics

• Total Topics
631782
• Total Posts
3002338
×