/// <summary> /// returns the tile position clamped to the tiled map /// </summary> /// <returns>The to tile position.</returns> /// <param name="worldPosition">World position.</param> /// <param name="axis">Axis.</param> int WorldToTilePosition(float worldPosition, Axis axis) { if (axis == Axis.Y) { return(TiledMap.WorldToTilePositionY(worldPosition)); } return(TiledMap.WorldToTilePositionX(worldPosition)); }
public override void Draw(Batcher batcher, Vector2 position, Vector2 scale, float layerDepth, RectangleF cameraClipBounds) { // offset it by the entity position since the tilemap will always expect positions in its own coordinate space cameraClipBounds.Location -= (position + Offset); int minX, minY, maxX, maxY; if (TiledMap.requiresLargeTileCulling) { // we expand our cameraClipBounds by the excess tile width/height of the largest tiles to ensure we include tiles whose // origin might be outside of the cameraClipBounds minX = TiledMap.WorldToTilePositionX((cameraClipBounds.Left - (TiledMap.LargestTileWidth - TiledMap.TileWidth)) / scale.X); minY = TiledMap.WorldToTilePositionY((cameraClipBounds.Top - (TiledMap.LargestTileHeight - TiledMap.TileHeight)) / scale.Y); maxX = TiledMap.WorldToTilePositionX((cameraClipBounds.Right + (TiledMap.LargestTileWidth - TiledMap.TileWidth)) / scale.X); maxY = TiledMap.WorldToTilePositionY((cameraClipBounds.Bottom + (TiledMap.LargestTileHeight - TiledMap.TileHeight)) / scale.Y); } else { minX = Mathf.Clamp(TiledMap.WorldToTilePositionX(cameraClipBounds.Left / scale.X), 0, TiledMap.Width - 1); minY = Mathf.Clamp(TiledMap.WorldToTilePositionX(cameraClipBounds.Top / scale.Y), 0, TiledMap.Height - 1); maxX = Mathf.Clamp(TiledMap.WorldToTilePositionX(cameraClipBounds.Right / scale.X), 0, TiledMap.Width - 1); maxY = Mathf.Clamp(TiledMap.WorldToTilePositionX(cameraClipBounds.Bottom / scale.Y), 0, TiledMap.Height - 1); } // loop through and draw all the non-culled tiles for (var y = minY; y <= maxY; y++) { for (var x = minX; x <= maxX; x++) { var tile = GetTile(x, y); if (tile == null) { continue; } var tileRegion = tile.TextureRegion; // culling for arbitrary size tiles if necessary if (TiledMap.requiresLargeTileCulling) { // TODO: this only checks left and bottom. we should check top and right as well to deal with rotated, odd-sized tiles var tileworldpos = TiledMap.TileToWorldPosition(new Point(x, y)); if (tileworldpos.X + tileRegion.SourceRect.Width < cameraClipBounds.Left || tileworldpos.Y - tileRegion.SourceRect.Height > cameraClipBounds.Bottom) { continue; } } // for the y position, we need to take into account if the tile is larger than the tileHeight and shift. Tiled uses // a bottom-left coordinate system and MonoGame a top-left var tx = tile.X * TiledMap.TileWidth * scale.X + (int)position.X; var ty = tile.Y * TiledMap.TileHeight * scale.Y + (int)position.Y; var rotation = 0f; var spriteEffects = SpriteEffects.None; if (tile.FlippedHorizonally) { spriteEffects |= SpriteEffects.FlipHorizontally; } if (tile.FlippedVertically) { spriteEffects |= SpriteEffects.FlipVertically; } if (tile.FlippedDiagonally) { if (tile.FlippedHorizonally && tile.FlippedVertically) { spriteEffects ^= SpriteEffects.FlipVertically; rotation = MathHelper.PiOver2; tx += TiledMap.TileHeight + (tileRegion.SourceRect.Height - TiledMap.TileHeight); ty -= (tileRegion.SourceRect.Width - TiledMap.TileWidth); } else if (tile.FlippedHorizonally) { spriteEffects ^= SpriteEffects.FlipVertically; rotation = -MathHelper.PiOver2; ty += TiledMap.TileHeight; } else if (tile.FlippedVertically) { spriteEffects ^= SpriteEffects.FlipHorizontally; rotation = MathHelper.PiOver2; tx += TiledMap.TileWidth + (tileRegion.SourceRect.Height - TiledMap.TileHeight); ty += (TiledMap.TileWidth - tileRegion.SourceRect.Width); } else { spriteEffects ^= SpriteEffects.FlipHorizontally; rotation = -MathHelper.PiOver2; ty += TiledMap.TileHeight; } } // if we had no rotations (diagonal flipping) shift our y-coord to account for any non-tileSized tiles to account for // Tiled being bottom-left origin if (rotation == 0) { ty += (TiledMap.TileHeight - tileRegion.SourceRect.Height); } batcher.Draw(tileRegion, new Vector2(tx, ty) + Offset, Color, rotation, Vector2.Zero, scale, spriteEffects, layerDepth); } } }