Exemple #1
0
        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);
                }
            }
        }