I'm currently designing a game using a game engine I created and I'm currently implementing a method that loads maps into my game. The maps are made using Tiled Map Editor, saved as an XML file and are loaded using TiledSharp.
At the moment, I'm trying to load a map, that contains 1437 'Game Objects' (These are just tiles, as far as tiled is concerned) and currently it takes around 360ms to load. I was just wondering what I can do to load my maps faster.
Here is the code that loads my maps:
public void LoadMap(string path)
{
Console.WriteLine("Loading map...");
var watch = new Stopwatch();
watch.Start();
// Import XML data using TiledSharp
var tmxMap = new TmxMap(path);
// Lets all the classes variables
width = tmxMap.Width;
height = tmxMap.Height;
tileWidth = tmxMap.TileWidth;
tileHeight = tmxMap.TileHeight;
wholeWidth = width * tileWidth;
wholeHeight = height * tileHeight;
// Now lets load all the sprite sheets that are used in this map
var spriteSheets = LoadSpriteSheets(tmxMap);
// A value that indicates what layer we're drawing to
int currentLayer = -1;
foreach (var layer in tmxMap.Layers)
{
// Increment a layer foreach layer we're in
currentLayer++;
foreach (var tile in layer.Tiles)
{
// Get the tiles x, y and global id
int x = tile.X;
int y = tile.Y;
int gid = tile.Gid;
// Now lets loop through the tilesets in the map
for (int i = 0; i < tmxMap.Tilesets.Count; i++)
{
var tileset = tmxMap.Tilesets[i];
// This just figures out how many images are in the tileset
int firstGid = tileset.FirstGid;
int lastGid = firstGid + (int)tileset.TileCount;
// Check if the tile we're on is in this tileset, if it isn't continue
if (!gid.IsWithin(firstGid, lastGid)) continue;
// Get the regular id, used to get the correct sprite from the sprite sheet
int id = gid - firstGid;
// Create a new object, set its position and scale
var obj = new GameObject();
obj.Transform.Position = new Vector2f(x * tileWidth, y * tileHeight);
obj.Transform.Scale = new Vector2f(tileWidth, tileHeight);
// Now lets add a sprite renderer component, and pass it the correct sprite
var sprite = new Sprite(spriteSheets[i][id], currentLayer, 1.0f);
var renderer = new SpriteRenderer(sprite);
obj.AddComponent(renderer);
// Now lets get the tiles from the tile set, and check if it contains any properties we need to know about
// Things like if its solid, or has a different depth
var tiles = tileset.Tiles;
if (tiles.ContainsKey(id))
HandleProperties(obj, tiles[id].Properties);
// Finally, lets add our game objec to the map
AddGameObject(obj);
}
}
}
// Dispose of our sprite sheets
foreach (var sheet in spriteSheets)
sheet.Bitmap.Dispose();
watch.Stop();
Console.WriteLine("Load time: {0}ms", watch.ElapsedMilliseconds);
if (GameObjects.Contains(Game1.Player)) return;
AddGameObject(Game1.Player);
}
private void HandleProperties(GameObject obj, PropertyDict properties)
{
var value = "";
if (properties.ContainsKey("Solid"))
{
value = properties["Solid"];
if (value == "true")
{
// We know we need to add physics and a collider
var physics = new PhysicsComponent();
physics.DetectCollisions = true;
obj.AddComponent(physics);
var collider = new BoxCollider();
collider.Size = new Vector2f(tileWidth, tileHeight);
obj.AddComponent(collider);
}
}
if(properties.ContainsKey("Depth"))
{
// Lets set the new depth of the sprite
value = properties["Depth"];
int depth = int.Parse(value);
obj.GetComponentOfType<SpriteRenderer>().Sprite.Depth = depth;
}
}
private List<SpriteSheet> LoadSpriteSheets(TmxMap tmxMap)
{
List<SpriteSheet> sheets = new List<SpriteSheet>();
for (int i = 0; i < tmxMap.Tilesets.Count; i++)
sheets.Add(new SpriteSheet(tmxMap.Tilesets[i].Image.Source, tmxMap.TileWidth, tmxMap.TileHeight, Color.White));
return sheets;
}