/* This creates a MapDrawableBatch (MDB) from the list of sprites provided to us by the FlatRedBall (FRB) Scene XML (scnx) file. */ public static MapDrawableBatch FromSpriteSaves(List<SpriteSave> spriteSaveList, int startingIndex, int count, string contentManagerName, bool verifySameTexturesPerLayer) { #if DEBUG if (verifySameTexturesPerLayer) { VerifySingleTexture(spriteSaveList, startingIndex, count); } #endif // We got it! We are going to make some assumptions: // First we need the texture. We'll assume all Sprites // use the same texture: // TODO: I (Bryan) really HATE this assumption. But it will work for now. SpriteSave firstSprite = spriteSaveList[startingIndex]; // This is the file name of the texture, but the file name is relative to the .scnx location string textureRelativeToScene = firstSprite.Texture; // so we load the texture Texture2D texture = FlatRedBallServices.Load<Texture2D>(textureRelativeToScene, contentManagerName); if (!MathFunctions.IsPowerOfTwo(texture.Width) || !MathFunctions.IsPowerOfTwo(texture.Height)) { throw new Exception("The dimensions of the texture file " + texture.Name + " are not power of 2!"); } // Assume all the dimensions of the textures are the same. I.e. all tiles use the same texture width and height. // This assumption is safe for Iso and Ortho tile maps. int tileFileDimensionsWidth = 0; int tileFileDimensionsHeight = 0; if (spriteSaveList.Count > startingIndex) { SpriteSave s = spriteSaveList[startingIndex]; // deduce the dimensionality of the tile from the texture coordinates tileFileDimensionsWidth = (int)System.Math.Round((double)((s.RightTextureCoordinate - s.LeftTextureCoordinate) * texture.Width)); tileFileDimensionsHeight = (int)System.Math.Round((double)((s.BottomTextureCoordinate - s.TopTextureCoordinate) * texture.Height)); } // alas, we create the MDB MapDrawableBatch mMapBatch = new MapDrawableBatch(count, tileFileDimensionsWidth, tileFileDimensionsHeight, texture); int lastIndexExclusive = startingIndex + count; for (int i = startingIndex; i < lastIndexExclusive; i++) { SpriteSave spriteSave = spriteSaveList[i]; // We don't want objects within the IDB to have a different Z than the IDB itself // (if possible) because that makes the IDB behave differently when using sorting vs. // the zbuffer. const bool setZTo0 = true; mMapBatch.Paste(spriteSave, setZTo0); } return mMapBatch; }
public static LayeredTileMap FromTiledMapSave(string tiledMapSaveFile, string contentManager, TiledMapSave tms) { // Ultimately properties are tied to tiles by the tile name. // If a tile has no name but it has properties, those properties // will be lost in the conversion. Therefore, we have to add name properties. tms.MoveTypeToProperties(); #if DEBUG CheckForDuplicateTilesets(tms); #endif tms.NameUnnamedTilesetTiles(); tms.NameUnnamedObjects(); string directory = FlatRedBall.IO.FileManager.GetDirectory(tiledMapSaveFile); var rtmi = ReducedTileMapInfo.FromTiledMapSave( tms, 1, 0, directory, FileReferenceType.Absolute); var toReturn = FromReducedTileMapInfo(rtmi, contentManager, tiledMapSaveFile); AddShapeCollections(toReturn, tms); foreach (var layer in tms.MapLayers) { var matchingLayer = toReturn.MapLayers.FirstOrDefault(item => item.Name == layer.Name); if (matchingLayer != null) { if (layer is MapLayer) { var mapLayer = layer as MapLayer; foreach (var propertyValues in mapLayer.properties) { matchingLayer.Properties.Add(new NamedValue { Name = propertyValues.StrippedName, Value = propertyValues.value, Type = propertyValues.Type }); } matchingLayer.Visible = mapLayer.visible == 1; matchingLayer.Alpha = mapLayer.Opacity; } else if (layer is mapObjectgroup objectLayer) { matchingLayer.Visible = objectLayer.IsVisible; } } } foreach (var tileset in tms.Tilesets) { foreach (var tile in tileset.TileDictionary.Values) { int propertyCountFromTileset = 0; if (tile.properties.Count != 0) { // this needs a name: string name = tile.properties.FirstOrDefault(item => item.StrippedName.ToLowerInvariant() == "name")?.value; // todo - eventually need to copy default values from the Tileset to the tile here AddPropertiesToMap(tms, toReturn.TileProperties, tile.properties, null, name); } } } foreach (var objectLayer in tms.objectgroup) { if (objectLayer.@object != null) { foreach (var objectInstance in objectLayer.@object) { TMXGlueLib.Tileset tileset = null; int propertyCountFromTileset = 0; var objectProperties = objectInstance.properties; List <property> tilesetProperties = null; if (objectInstance.gid != null) { var gidNoFlip = objectInstance.GidNoFlip; tileset = tms.GetTilesetForGid(gidNoFlip.Value); if (tileset.TileDictionary.ContainsKey(gidNoFlip.Value - tileset.Firstgid)) { tilesetProperties = tileset.TileDictionary[gidNoFlip.Value - tileset.Firstgid].properties; propertyCountFromTileset = tilesetProperties.Count; } } if (objectProperties.Count + propertyCountFromTileset != 0) { string name = objectInstance.Name; // if name is null, check the properties: if (string.IsNullOrEmpty(name)) { name = objectProperties.FirstOrDefault(item => item.StrippedNameLower == "name")?.value; } var objectInstanceIsTile = objectInstance.gid != null; if (objectInstanceIsTile) { AddPropertiesToMap(tms, toReturn.TileProperties, objectProperties, tilesetProperties, name); } else { AddPropertiesToMap(tms, toReturn.ShapeProperties, objectProperties, tilesetProperties, name); } } } } } var tmxDirectory = FileManager.GetDirectory(tiledMapSaveFile); // add image layers foreach (var imageLayer in tms.ImageLayers) { var imageLayerFile = tmxDirectory + imageLayer.ImageObject.Source; var texture = FlatRedBallServices.Load <Microsoft.Xna.Framework.Graphics.Texture2D>(imageLayerFile); var newSprite = new Sprite { Texture = texture, Width = imageLayer.ImageObject.Width, Height = imageLayer.ImageObject.Height, X = imageLayer.ImageObject.Width / 2 + imageLayer.OffsetX, Y = -imageLayer.ImageObject.Height / 2 + imageLayer.OffsetY }; var mdb = new MapDrawableBatch(1, texture); mdb.Alpha = imageLayer.Opacity; mdb.AttachTo(toReturn, false); mdb.Paste(newSprite); mdb.Visible = imageLayer.IsVisible; toReturn.mMapLists.Add(mdb); } var animationDictionary = new Dictionary <string, AnimationChain>(); // add animations foreach (var tileset in tms.Tilesets) { string tilesetImageFile = tmxDirectory + tileset.Images[0].Source; if (tileset.SourceDirectory != ".") { tilesetImageFile = tmxDirectory + tileset.SourceDirectory + tileset.Images[0].Source; } var texture = FlatRedBallServices.Load <Microsoft.Xna.Framework.Graphics.Texture2D>(tilesetImageFile, contentManager); foreach (var tile in tileset.Tiles.Where(item => item.Animation != null && item.Animation.Frames.Count != 0)) { var animation = tile.Animation; var animationChain = new AnimationChain(); foreach (var frame in animation.Frames) { var animationFrame = new AnimationFrame(); animationFrame.FrameLength = frame.Duration / 1000.0f; animationFrame.Texture = texture; int tileIdRelative = frame.TileId; int globalTileId = (int)(tileIdRelative + tileset.Firstgid); int leftPixel; int rightPixel; int topPixel; int bottomPixel; TiledMapSave.GetPixelCoordinatesFromGid((uint)globalTileId, tileset, out leftPixel, out topPixel, out rightPixel, out bottomPixel); animationFrame.LeftCoordinate = MapDrawableBatch.CoordinateAdjustment + leftPixel / (float)texture.Width; animationFrame.RightCoordinate = -MapDrawableBatch.CoordinateAdjustment + rightPixel / (float)texture.Width; animationFrame.TopCoordinate = MapDrawableBatch.CoordinateAdjustment + topPixel / (float)texture.Height; animationFrame.BottomCoordinate = -MapDrawableBatch.CoordinateAdjustment + bottomPixel / (float)texture.Height; animationChain.Add(animationFrame); } var property = tile.properties.FirstOrDefault(item => item.StrippedNameLower == "name"); if (property == null) { throw new InvalidOperationException( $"The tile with ID {tile.id} has an animation, but it doesn't have a Name property, which is required for animation."); } else { animationDictionary.Add(property.value, animationChain); } } } toReturn.Animation = new LayeredTileMapAnimation(animationDictionary); AddTileShapeCollections(toReturn, tms, separateOnTileType: true); toReturn.MapProperties = tms.properties .Select(propertySave => new NamedValue { Name = propertySave.name, Value = propertySave.value, Type = propertySave.Type }) .ToList(); return(toReturn); }
/* This creates a MapDrawableBatch (MDB) from the list of sprites provided to us by the FlatRedBall (FRB) Scene XML (scnx) file. */ public static MapDrawableBatch FromSpriteSaves(List <SpriteSave> spriteSaveList, int startingIndex, int count, string contentManagerName, bool verifySameTexturesPerLayer) { #if DEBUG if (verifySameTexturesPerLayer) { VerifySingleTexture(spriteSaveList, startingIndex, count); } #endif // We got it! We are going to make some assumptions: // First we need the texture. We'll assume all Sprites // use the same texture: // TODO: I (Bryan) really HATE this assumption. But it will work for now. SpriteSave firstSprite = spriteSaveList[startingIndex]; // This is the file name of the texture, but the file name is relative to the .scnx location string textureRelativeToScene = firstSprite.Texture; // so we load the texture Texture2D texture = FlatRedBallServices.Load <Texture2D>(textureRelativeToScene, contentManagerName); if (!MathFunctions.IsPowerOfTwo(texture.Width) || !MathFunctions.IsPowerOfTwo(texture.Height)) { throw new Exception("The dimensions of the texture file " + texture.Name + " are not power of 2!"); } // Assume all the dimensions of the textures are the same. I.e. all tiles use the same texture width and height. // This assumption is safe for Iso and Ortho tile maps. int tileFileDimensionsWidth = 0; int tileFileDimensionsHeight = 0; if (spriteSaveList.Count > startingIndex) { SpriteSave s = spriteSaveList[startingIndex]; // deduce the dimensionality of the tile from the texture coordinates tileFileDimensionsWidth = (int)System.Math.Round((double)((s.RightTextureCoordinate - s.LeftTextureCoordinate) * texture.Width)); tileFileDimensionsHeight = (int)System.Math.Round((double)((s.BottomTextureCoordinate - s.TopTextureCoordinate) * texture.Height)); } // alas, we create the MDB MapDrawableBatch mMapBatch = new MapDrawableBatch(count, tileFileDimensionsWidth, tileFileDimensionsHeight, texture); int lastIndexExclusive = startingIndex + count; for (int i = startingIndex; i < lastIndexExclusive; i++) { SpriteSave spriteSave = spriteSaveList[i]; // We don't want objects within the IDB to have a different Z than the IDB itself // (if possible) because that makes the IDB behave differently when using sorting vs. // the zbuffer. const bool setZTo0 = true; mMapBatch.Paste(spriteSave, setZTo0); } return(mMapBatch); }