示例#1
0
        private static void DrawPolygon(Graphics g, Pen pen, Brush brush, TmxMap tmxMap, TmxObjectPolygon tmxPolygon)
        {
            var points = TmxMath.GetPointsInMapSpace(tmxMap, tmxPolygon).ToArray();

            g.FillPolygon(brush, points);
            g.DrawPolygon(pen, points);
        }
示例#2
0
        private static void DrawPolyline(SKCanvas canvas, SKColor color, TmxMap tmxMap, TmxObjectPolyline tmxPolyline)
        {
            using (SKPaint paint = new SKPaint())
                using (SKPath path = new SKPath())
                {
                    var points = TmxMath.GetPointsInMapSpace(tmxMap, tmxPolyline).ToSkPointArray();
                    path.AddPoly(points, false);

                    paint.Style       = SKPaintStyle.Stroke;
                    paint.StrokeWidth = StrokeWidthThick;
                    paint.Color       = color;
                    canvas.DrawPath(path, paint);
                }
        }
示例#3
0
        private static void DrawObjectMarker(SKCanvas canvas, TmxMap tmxMap, TmxObject tmxObject, SKColor color)
        {
            using (new SKAutoCanvasRestore(canvas))
                using (SKPaint paint = new SKPaint())
                {
                    PointF xfPosition = TmxMath.ObjectPointFToMapSpace(tmxMap, tmxObject.Position);
                    canvas.Translate(xfPosition.X, xfPosition.Y);

                    paint.Style       = SKPaintStyle.Stroke;
                    paint.StrokeWidth = StrokeWidthThick;
                    paint.Color       = color;
                    canvas.DrawCircle(0, 0, 2, paint);
                }
        }
示例#4
0
        private static void DrawObjectMarker(Graphics g, TmxMap tmxMap, TmxObject tmxObject, Color color)
        {
            using (Pen pen = new Pen(color))
            {
                GraphicsState state = g.Save();

                PointF xfPosition = TmxMath.ObjectPointFToMapSpace(tmxMap, tmxObject.Position);
                g.TranslateTransform(xfPosition.X, xfPosition.Y);
                g.RotateTransform(tmxObject.Rotation);

                Rectangle rc = new Rectangle(-2, -2, 4, 4);
                g.DrawEllipse(pen, rc);
                g.Restore(state);
            }
        }
示例#5
0
        private static void DrawTilesInObjectGroup(Graphics g, TmxMap tmxMap, TmxObjectGroup objectGroup)
        {
            // Get opacity in eventually
#if !TILED2UNITY_MAC
            ColorMatrix colorMatrix = new ColorMatrix();
            colorMatrix.Matrix33 = objectGroup.Opacity;

            ImageAttributes imageAttributes = new ImageAttributes();
            imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
#endif

            foreach (var tmxObject in objectGroup.Objects)
            {
                if (!tmxObject.Visible)
                {
                    continue;
                }

                TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile;
                if (tmxObjectTile == null)
                {
                    continue;
                }

                GraphicsState state      = g.Save();
                PointF        xfPosition = TmxMath.ObjectPointFToMapSpace(tmxMap, tmxObject.Position);
                g.TranslateTransform(xfPosition.X, xfPosition.Y);
                g.RotateTransform(tmxObject.Rotation);
                {
                    GraphicsState tileState = g.Save();
                    PrepareTransformForTileObject(g, tmxMap, tmxObjectTile);

                    // Draw the tile
                    Rectangle destination = new Rectangle(0, -tmxObjectTile.Tile.TileSize.Height, tmxObjectTile.Tile.TileSize.Width, tmxObjectTile.Tile.TileSize.Height);
                    Rectangle source      = new Rectangle(tmxObjectTile.Tile.LocationOnSource, tmxObjectTile.Tile.TileSize);
                    //g.DrawRectangle(Pens.Black, destination);

#if !TILED2UNITY_MAC
                    g.DrawImage(tmxObjectTile.Tile.TmxImage.ImageBitmap, destination, source.X, source.Y, source.Width, source.Height, GraphicsUnit.Pixel, imageAttributes);
#else
                    g.DrawImage(tmxObjectTile.Tile.TmxImage.ImageBitmap, destination, source.X, source.Y, source.Width, source.Height, GraphicsUnit.Pixel);
#endif

                    g.Restore(tileState);
                }
                g.Restore(state);
            }
        }
示例#6
0
        private static void DrawPolygon(SKCanvas canvas, SKColor color, TmxMap tmxMap, TmxObjectPolygon tmxPolygon)
        {
            using (SKPaint paint = new SKPaint())
                using (SKPath path = new SKPath())
                {
                    var points = TmxMath.GetPointsInMapSpace(tmxMap, tmxPolygon).ToSkPointArray();
                    path.AddPoly(points);

                    paint.Style       = SKPaintStyle.Fill;
                    paint.StrokeWidth = StrokeWidthThick;
                    paint.Color       = color.WithAlpha(128);
                    canvas.DrawPath(path, paint);

                    paint.Style       = SKPaintStyle.Stroke;
                    paint.StrokeWidth = StrokeWidthThick;
                    paint.Color       = color;
                    canvas.DrawPath(path, paint);
                }
        }
示例#7
0
        private static void DrawTilesInObjectGroup(SKCanvas canvas, TmxMap tmxMap, TmxObjectGroup objectGroup)
        {
            using (SKPaint paint = new SKPaint())
            {
                // Draw with the given opacity
                paint.Color = SKColors.White.WithAlpha((byte)(objectGroup.Opacity * byte.MaxValue));

                foreach (var tmxObject in objectGroup.Objects)
                {
                    if (!tmxObject.Visible)
                    {
                        continue;
                    }

                    TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile;
                    if (tmxObjectTile == null)
                    {
                        continue;
                    }

                    using (new SKAutoCanvasRestore(canvas))
                    {
                        PointF xfPosition = TmxMath.ObjectPointFToMapSpace(tmxMap, tmxObject.Position);
                        canvas.Translate(xfPosition.X, xfPosition.Y);
                        canvas.RotateDegrees(tmxObject.Rotation);
                        using (new SKAutoCanvasRestore(canvas))
                        {
                            PrepareTransformForTileObject(canvas, tmxMap, tmxObjectTile);

                            // Draw the tile
                            SKRect destination = new RectangleF(0, -tmxObjectTile.Tile.TileSize.Height, tmxObjectTile.Tile.TileSize.Width, tmxObjectTile.Tile.TileSize.Height).ToSKRect();
                            SKRect source      = new RectangleF(tmxObjectTile.Tile.LocationOnSource, tmxObjectTile.Tile.TileSize).ToSKRect();
                            canvas.DrawBitmap(tmxObjectTile.Tile.TmxImage.ImageBitmap, source, destination, paint);
                        }
                    }
                }
            }
        }
示例#8
0
        private static RectangleF CalculateBoundary(TmxMap tmxMap)
        {
            RectangleF rcMap = new RectangleF(Point.Empty, tmxMap.MapSizeInPixels());

            // Take boundaries from object groups
            var objBounds = from g in tmxMap.ObjectGroups
                            from o in g.Objects
                            where o.Visible == true
                            select o.GetWorldBounds();

            // Take boundaries from objects embedded in tiles
            var tileBounds = from layer in tmxMap.Layers
                             where layer.Visible == true
                             from y in Enumerable.Range(0, layer.Height)
                             from x in Enumerable.Range(0, layer.Width)
                             let tileId = layer.GetTileIdAt(x, y)
                                          where tileId != 0
                                          let tile = tmxMap.Tiles[tileId]
                                                     from o in tile.ObjectGroup.Objects
                                                     let bound                         = o.GetWorldBounds()
                                                                             let point = TmxMath.TileCornerInScreenCoordinates(tmxMap, x, y)
                                                                                         select new RectangleF(bound.X + point.X, bound.Y + point.Y, bound.Width, bound.Height);

            var allBounds = objBounds.Concat(tileBounds);
            var union     = allBounds.Aggregate(rcMap, RectangleF.Union);

            // Inflate a tile size to make room for the grid
            union.Inflate(tmxMap.TileWidth, tmxMap.TileHeight);
            union.Inflate(PreviewImage.GridSize, PreviewImage.GridSize);

            return(union);
        }
示例#9
0
        private static void DrawObjectCollider(Graphics g, TmxMap tmxMap, TmxObject tmxObject, Color color)
        {
            using (Brush brush = TmxHelper.CreateObjectColliderBrush(color))
                using (Pen pen = new Pen(color))
                {
                    GraphicsState state = g.Save();

                    PointF xfPosition = TmxMath.ObjectPointFToMapSpace(tmxMap, tmxObject.Position);
                    g.TranslateTransform(xfPosition.X, xfPosition.Y);
                    g.RotateTransform(tmxObject.Rotation);

                    if (tmxObject.GetType() == typeof(TmxObjectPolygon))
                    {
                        DrawPolygon(g, pen, brush, tmxMap, tmxObject as TmxObjectPolygon);
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectRectangle))
                    {
                        if (tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
                        {
                            TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(tmxMap, tmxObject as TmxObjectRectangle);
                            DrawPolygon(g, pen, brush, tmxMap, tmxIsometricRectangle);
                        }
                        else
                        {
                            // Rectangles are polygons
                            DrawPolygon(g, pen, brush, tmxMap, tmxObject as TmxObjectPolygon);
                        }
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectEllipse))
                    {
                        DrawEllipse(g, pen, brush, tmxMap, tmxObject as TmxObjectEllipse);
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectPolyline))
                    {
                        DrawPolyline(g, pen, tmxMap, tmxObject as TmxObjectPolyline);
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectTile))
                    {
                        GraphicsState tileState = g.Save();

                        TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile;
                        PrepareTransformForTileObject(g, tmxMap, tmxObjectTile);

                        // Draw the collisions
                        // Temporarily set orienation to Orthogonal for tile colliders
                        TmxMap.MapOrientation restoreOrientation = tmxMap.Orientation;
                        tmxMap.Orientation = TmxMap.MapOrientation.Orthogonal;
                        {
                            // Make up for the fact that the bottom-left corner is the origin
                            g.TranslateTransform(0, -tmxObjectTile.Tile.TileSize.Height);
                            foreach (var obj in tmxObjectTile.Tile.ObjectGroup.Objects)
                            {
                                DrawObjectCollider(g, tmxMap, obj, Color.Gray);
                            }
                        }
                        tmxMap.Orientation = restoreOrientation;

                        g.Restore(tileState);
                    }
                    else
                    {
                        g.Restore(state);
                        Logger.WriteWarning("Unhandled object: {0}", tmxObject.GetNonEmptyName());
                    }

                    // Restore our state
                    g.Restore(state);
                }
        }
示例#10
0
        private static void DrawTilesInTileLayer(Graphics g, TmxMap tmxMap, TmxLayer layer)
        {
            // Set the opacity for the layer (Not supported on Mac builds)
#if !TILED2UNITY_MAC
            ColorMatrix colorMatrix = new ColorMatrix();
            colorMatrix.Matrix33 = layer.Opacity;

            ImageAttributes imageAttributes = new ImageAttributes();
            imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
#endif
            // The range of x and y depends on the render order of the tiles
            // By default we draw right and down but may reverse the tiles we visit
            var range_x = Enumerable.Range(0, GetMaxTilesWide(layer));
            var range_y = Enumerable.Range(0, GetMaxTilesHigh(layer));

            if (tmxMap.DrawOrderHorizontal == -1)
            {
                range_x = range_x.Reverse();
            }

            if (tmxMap.DrawOrderVertical == -1)
            {
                range_y = range_y.Reverse();
            }

            // Visit the tiles we are going to draw
            var tiles = from y in range_y
                        from x in range_x
                        let rawTileId = layer.GetRawTileIdAt(x, y)
                                        let tileId = layer.GetTileIdAt(x, y)
                                                     where tileId != 0

                                                     let tile = tmxMap.Tiles[tileId]

                                                                // Support for animated tiles. Just show the first frame of the animation.
                                                                let frame = tmxMap.Tiles[tile.Animation.Frames[0].GlobalTileId]

                                                                            select new
            {
                Tile                  = frame,
                Position              = TmxMath.TileCornerInScreenCoordinates(tmxMap, x, y),
                Bitmap                = frame.TmxImage.ImageBitmap,
                IsFlippedDiagnoally   = TmxMath.IsTileFlippedDiagonally(rawTileId),
                IsFlippedHorizontally = TmxMath.IsTileFlippedHorizontally(rawTileId),
                IsFlippedVertically   = TmxMath.IsTileFlippedVertically(rawTileId),
            };

            PointF[] destPoints  = new PointF[4];
            PointF[] destPoints3 = new PointF[3];
            foreach (var t in tiles)
            {
                PointF location = t.Position;

                // Individual tiles may be larger than the given tile size of the overall map
                location.Y = (t.Position.Y - t.Tile.TileSize.Height) + tmxMap.TileHeight;

                // Take tile offset into account
                location.X += t.Tile.Offset.X;
                location.Y += t.Tile.Offset.Y;

                // Make up the 'quad' of texture points and transform them
                PointF center = new PointF(t.Tile.TileSize.Width * 0.5f, t.Tile.TileSize.Height * 0.5f);
                destPoints[0] = new Point(0, 0);
                destPoints[1] = new Point(t.Tile.TileSize.Width, 0);
                destPoints[2] = new Point(t.Tile.TileSize.Width, t.Tile.TileSize.Height);
                destPoints[3] = new Point(0, t.Tile.TileSize.Height);

                // Transform the points based on our flipped flags
                TmxMath.TransformPoints(destPoints, center, t.IsFlippedDiagnoally, t.IsFlippedHorizontally, t.IsFlippedVertically);

                // Put the destination points back into world space
                TmxMath.TranslatePoints(destPoints, location);

                // Stupid DrawImage function only takes 3 destination points otherwise it throws an exception
                destPoints3[0] = destPoints[0];
                destPoints3[1] = destPoints[1];
                destPoints3[2] = destPoints[3];

                // Draw the tile
                Rectangle source = new Rectangle(t.Tile.LocationOnSource, t.Tile.TileSize);
#if !TILED2UNITY_MAC
                g.DrawImage(t.Bitmap, destPoints3, source, GraphicsUnit.Pixel, imageAttributes);
#else
                g.DrawImage(t.Bitmap, destPoints3, source, GraphicsUnit.Pixel);
#endif
            }
        }
示例#11
0
        private static void DrawGridHex(Graphics g, TmxMap tmxMap)
        {
            // Our collection of points to render
            HashSet <Point> points = new HashSet <Point>();

            // Note: borrowed heavily from Tiled source (HexagonalRenderer::drawGrid)
            int tileWidth  = tmxMap.TileWidth & ~1;
            int tileHeight = tmxMap.TileHeight & ~1;

            int sideLengthX = tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.X ? tmxMap.HexSideLength : 0;
            int sideLengthY = tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.Y ? tmxMap.HexSideLength : 0;

            int sideOffsetX = (tmxMap.TileWidth - sideLengthX) / 2;
            int sideOffsetY = (tmxMap.TileHeight - sideLengthY) / 2;

            int columnWidth = sideOffsetX + sideLengthX;
            int rowHeight   = sideOffsetY + sideLengthY;

            bool staggerX = tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.X;

            // Determine the tile and pixel coordinates to start at
            Point startTile = new Point(0, 0);
            Point startPos  = TmxMath.TileCornerInScreenCoordinates(tmxMap, startTile.X, startTile.Y);

            Point[] oct = new Point[8]
            {
                new Point(0, tileHeight - sideOffsetY),
                new Point(0, sideOffsetY),
                new Point(sideOffsetX, 0),
                new Point(tileWidth - sideOffsetX, 0),
                new Point(tileWidth, sideOffsetY),
                new Point(tileWidth, tileHeight - sideOffsetY),
                new Point(tileWidth - sideOffsetX, tileHeight),
                new Point(sideOffsetX, tileHeight)
            };

            if (staggerX)
            {
                // Odd row shifting is applied in the rendering loop, so un-apply it here
                if (TmxMath.DoStaggerX(tmxMap, startTile.X))
                {
                    startPos.Y -= rowHeight;
                }

                for (; startTile.X < GetMaxTilesWide(tmxMap); startTile.X++)
                {
                    Point rowTile = startTile;
                    Point rowPos  = startPos;

                    if (TmxMath.DoStaggerX(tmxMap, startTile.X))
                    {
                        rowPos.Y += rowHeight;
                    }

                    for (; rowTile.Y < GetMaxTilesHigh(tmxMap); rowTile.Y++)
                    {
                        points.Add(TmxMath.AddPoints(rowPos, oct[1]));
                        points.Add(TmxMath.AddPoints(rowPos, oct[2]));
                        points.Add(TmxMath.AddPoints(rowPos, oct[3]));
                        points.Add(TmxMath.AddPoints(rowPos, oct[4]));

                        bool isStaggered = TmxMath.DoStaggerX(tmxMap, startTile.X);
                        bool lastRow     = rowTile.Y == tmxMap.Height - 1;
                        bool lastColumn  = rowTile.X == tmxMap.Width - 1;
                        bool bottomLeft  = rowTile.X == 0 || (lastRow && isStaggered);
                        bool bottomRight = lastColumn || (lastRow && isStaggered);

                        if (bottomRight)
                        {
                            points.Add(TmxMath.AddPoints(rowPos, oct[5]));
                            points.Add(TmxMath.AddPoints(rowPos, oct[6]));
                        }
                        if (lastRow)
                        {
                            points.Add(TmxMath.AddPoints(rowPos, oct[6]));
                            points.Add(TmxMath.AddPoints(rowPos, oct[7]));
                        }
                        if (bottomLeft)
                        {
                            points.Add(TmxMath.AddPoints(rowPos, oct[7]));
                            points.Add(TmxMath.AddPoints(rowPos, oct[0]));
                        }

                        rowPos.Y += tileHeight + sideLengthY;
                    }

                    startPos.X += columnWidth;
                }
            }
            else
            {
                // Odd row shifting is applied in the rendering loop, so un-apply it here
                if (TmxMath.DoStaggerY(tmxMap, startTile.Y))
                {
                    startPos.X -= columnWidth;
                }

                for (; startTile.Y < tmxMap.Height; startTile.Y++)
                {
                    Point rowTile = startTile;
                    Point rowPos  = startPos;

                    if (TmxMath.DoStaggerY(tmxMap, startTile.Y))
                    {
                        rowPos.X += columnWidth;
                    }

                    for (; rowTile.X < tmxMap.Width; rowTile.X++)
                    {
                        points.Add(TmxMath.AddPoints(rowPos, oct[0]));
                        points.Add(TmxMath.AddPoints(rowPos, oct[1]));
                        points.Add(TmxMath.AddPoints(rowPos, oct[2]));
                        points.Add(TmxMath.AddPoints(rowPos, oct[3]));
                        points.Add(TmxMath.AddPoints(rowPos, oct[4]));


                        bool isStaggered = TmxMath.DoStaggerY(tmxMap, startTile.Y);
                        bool lastRow     = rowTile.Y == tmxMap.Height - 1;
                        bool lastColumn  = rowTile.Y == tmxMap.Width - 1;
                        bool bottomLeft  = lastRow || (rowTile.X == 0 && !isStaggered);
                        bool bottomRight = lastRow || (lastColumn && isStaggered);

                        if (lastColumn)
                        {
                            points.Add(TmxMath.AddPoints(rowPos, oct[4]));
                            points.Add(TmxMath.AddPoints(rowPos, oct[5]));
                        }
                        if (bottomRight)
                        {
                            points.Add(TmxMath.AddPoints(rowPos, oct[5]));
                            points.Add(TmxMath.AddPoints(rowPos, oct[6]));
                        }
                        if (bottomLeft)
                        {
                            points.Add(TmxMath.AddPoints(rowPos, oct[7]));
                            points.Add(TmxMath.AddPoints(rowPos, oct[0]));
                        }

                        rowPos.X += tileWidth + sideLengthX;
                    }

                    startPos.Y += rowHeight;
                }
            }

            foreach (var p in points)
            {
                RectangleF rc = new RectangleF(p.X, p.Y, PreviewImage.GridSize, PreviewImage.GridSize);
                rc.Offset(-PreviewImage.GridSize * 0.5f, -PreviewImage.GridSize * 0.5f);

                g.DrawRectangle(Pens.Black, rc.X, rc.Y, rc.Width, rc.Height);
            }
        }
示例#12
0
        private static void DrawGridQuad(Graphics g, TmxMap tmxMap, float scale)
        {
            HashSet <Point> points = new HashSet <Point>();

            for (int x = 0; x < GetMaxTilesWide(tmxMap); ++x)
            {
                for (int y = 0; y < GetMaxTilesHigh(tmxMap); ++y)
                {
                    // Add the "top-left" corner of a tile
                    points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x, y));

                    // Add all other corners of the tile to our list of grid points
                    // This is complicated by different map types (espcially staggered isometric)
                    if (tmxMap.Orientation == TmxMap.MapOrientation.Orthogonal || tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
                    {
                        points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x + 1, y));
                        points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x + 1, y + 1));
                        points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x, y + 1));
                    }
                    else if (tmxMap.Orientation == TmxMap.MapOrientation.Staggered)
                    {
                        bool sx = TmxMath.DoStaggerX(tmxMap, x);
                        bool sy = TmxMath.DoStaggerY(tmxMap, y);

                        if (sx)
                        {
                            // top-right, bottom-right, and bottom-left
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x + 1, y + 1));
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x, y + 1));
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x - 1, y + 1));
                        }
                        else if (sy)
                        {
                            // top-right, bottom-right, and bottom-left
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x + 1, y + 1));
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x, y + 2));
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x, y + 1));
                        }
                        else if (tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.X)
                        {
                            // top-right, bottom-right, and bottom-left
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x + 1, y));
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x, y + 1));
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x - 1, y));
                        }
                        else if (tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.Y)
                        {
                            // top-right, bottom-right, and bottom-left
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x, y + 1));
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x, y + 2));
                            points.Add(TmxMath.TileCornerInGridCoordinates(tmxMap, x - 1, y + 1));
                        }
                    }
                }
            }

            // Can take for granted that background is always white
            float             invScale   = 1.0f / scale;
            List <RectangleF> rectangles = new List <RectangleF>(points.Count);

            foreach (var p in points)
            {
                RectangleF rc = new RectangleF(p.X, p.Y, PreviewImage.GridSize * invScale, PreviewImage.GridSize * invScale);
                rc.Offset(-PreviewImage.GridSize * 0.5f * invScale, -PreviewImage.GridSize * 0.5f * invScale);
                rectangles.Add(rc);
            }

            using (Pen pen = new Pen(Brushes.Black, invScale))
            {
                g.DrawRectangles(pen, rectangles.ToArray());
            }
        }
示例#13
0
        private static void DrawTilesInTileLayer(SKCanvas canvas, TmxMap tmxMap, TmxLayer layer)
        {
            using (SKPaint paint = new SKPaint())
            {
                // Set the opacity for the layer
                paint.Color = SKColors.White.WithAlpha((byte)(layer.Opacity * byte.MaxValue));

                // The range of x and y depends on the render order of the tiles
                // By default we draw right and down but may reverse the tiles we visit
                var range_x = Enumerable.Range(0, GetMaxTilesWide(layer));
                var range_y = Enumerable.Range(0, GetMaxTilesHigh(layer));

                if (tmxMap.DrawOrderHorizontal == -1)
                {
                    range_x = range_x.Reverse();
                }

                if (tmxMap.DrawOrderVertical == -1)
                {
                    range_y = range_y.Reverse();
                }

                // Visit the tiles we are going to draw
                var tiles = from y in range_y
                            from x in range_x
                            let rawTileId = layer.GetRawTileIdAt(x, y)
                                            let tileId = layer.GetTileIdAt(x, y)
                                                         where tileId != 0

                                                         let tile = tmxMap.Tiles[tileId]

                                                                    // Support for animated tiles. Just show the first frame of the animation.
                                                                    let frame = tmxMap.Tiles[tile.Animation.Frames[0].GlobalTileId]

                                                                                select new
                {
                    Tile                  = frame,
                    Position              = tmxMap.GetMapPositionAt(x, y, frame),
                    Bitmap                = frame.TmxImage.ImageBitmap,
                    IsFlippedDiagnoally   = TmxMath.IsTileFlippedDiagonally(rawTileId),
                    IsFlippedHorizontally = TmxMath.IsTileFlippedHorizontally(rawTileId),
                    IsFlippedVertically   = TmxMath.IsTileFlippedVertically(rawTileId),
                };

                foreach (var t in tiles)
                {
                    PointF location = t.Position;

                    using (new SKAutoCanvasRestore(canvas))
                    {
                        bool flip_h = t.IsFlippedHorizontally;
                        bool flip_v = t.IsFlippedVertically;
                        bool flip_d = t.IsFlippedDiagnoally;

                        // Move to the center of the tile on location and perform and transforms
                        SKPoint center = new SKPoint(t.Tile.TileSize.Width * 0.5f, t.Tile.TileSize.Height * 0.5f);
                        canvas.Translate(center.X, center.Y);
                        canvas.Translate(location.X, location.Y);

                        // Flip transformations (logic taken from Tiled source: maprenderer.cpp)
                        {
                            // If we're flipping diagonally then rotate 90 degrees and reverse h/v flip flags
                            float rotate = 0;
                            if (flip_d)
                            {
                                rotate = 90;
                                flip_h = t.IsFlippedVertically;
                                flip_v = !t.IsFlippedHorizontally;
                            }

                            // Scale based on flip flags
                            float scale_x = flip_h ? -1.0f : 1.0f;
                            float scale_y = flip_v ? -1.0f : 1.0f;

                            canvas.Scale(scale_x, scale_y);
                            canvas.RotateDegrees(rotate);
                        }

                        // Move us back out of the center
                        canvas.Translate(-center.X, -center.Y);

                        // Draw the tile
                        SKRect dest   = SKRect.Create(0, 0, t.Tile.TileSize.Width, t.Tile.TileSize.Height);
                        SKRect source = SKRect.Create(t.Tile.LocationOnSource.X, t.Tile.LocationOnSource.Y, t.Tile.TileSize.Width, t.Tile.TileSize.Height);
                        canvas.DrawBitmap(t.Bitmap, source, dest, paint);
                    }
                }
            }
        }
示例#14
0
        private static SKRect CalculateBoundary(TmxMap tmxMap)
        {
            SKRect rcMap = SKRect.Create(0, 0, tmxMap.MapSizeInPixels.Width, tmxMap.MapSizeInPixels.Height);

            // Any tile layers in the map can be offset
            var tileLayerBounds = from layer in tmxMap.EnumerateTileLayers()
                                  where layer.Visible == true
                                  let offset = layer.GetCombinedOffset()
                                               select SKRect.Create(offset.X, offset.Y, rcMap.Size.Width, rcMap.Size.Height);

            // Take boundaries from object groups
            var objBounds = from g in tmxMap.EnumerateObjectLayers()
                            from o in g.Objects
                            where o.Visible == true
                            let b = o.GetOffsetWorldBounds()
                                    select SKRect.Create(b.X, b.Y, b.Width, b.Height);

            // Take boundaries from objects embedded in tiles
            var tileBounds = from layer in tmxMap.EnumerateTileLayers()
                             where layer.Visible == true
                             from y in Enumerable.Range(0, layer.Height)
                             from x in Enumerable.Range(0, layer.Width)
                             let tileId = layer.GetTileIdAt(x, y)
                                          where tileId != 0
                                          let tile = tmxMap.Tiles[tileId]
                                                     from o in tile.ObjectGroup.Objects
                                                     let bound                         = o.GetOffsetWorldBounds()
                                                                             let point = TmxMath.TileCornerInScreenCoordinates(tmxMap, x, y)
                                                                                         select SKRect.Create(bound.X + point.X, bound.Y + point.Y, bound.Width, bound.Height);

            var allBounds = tileLayerBounds.Concat(objBounds).Concat(tileBounds);
            var union     = allBounds.Aggregate(rcMap, SKRect.Union);

            // Inflate a tile size to make room for the grid
            union.Inflate(tmxMap.TileWidth, tmxMap.TileHeight);
            union.Inflate(PreviewImage.GridSize, PreviewImage.GridSize);

            return(union);
        }
示例#15
0
        private static void DrawObjectCollider(SKCanvas canvas, TmxMap tmxMap, TmxObject tmxObject, SKColor color)
        {
            using (new SKAutoCanvasRestore(canvas))
                using (SKPaint paint = new SKPaint())
                {
                    PointF xfPosition = TmxMath.ObjectPointFToMapSpace(tmxMap, tmxObject.Position);
                    canvas.Translate(xfPosition.ToSKPoint());
                    canvas.RotateDegrees(tmxObject.Rotation);

                    if (tmxObject.GetType() == typeof(TmxObjectPolygon))
                    {
                        DrawPolygon(canvas, color, tmxMap, tmxObject as TmxObjectPolygon);
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectRectangle))
                    {
                        if (tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
                        {
                            TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(tmxMap, tmxObject as TmxObjectRectangle);
                            DrawPolygon(canvas, color, tmxMap, tmxIsometricRectangle);
                        }
                        else
                        {
                            // Rectangles are polygons
                            DrawPolygon(canvas, color, tmxMap, tmxObject as TmxObjectPolygon);
                        }
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectEllipse))
                    {
                        DrawEllipse(canvas, color, tmxMap, tmxObject as TmxObjectEllipse);
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectPolyline))
                    {
                        DrawPolyline(canvas, color, tmxMap, tmxObject as TmxObjectPolyline);
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectTile))
                    {
                        using (new SKAutoCanvasRestore(canvas))
                        {
                            TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile;
                            PrepareTransformForTileObject(canvas, tmxMap, tmxObjectTile);

                            // Draw the collisions
                            // Temporarily set orienation to Orthogonal for tile colliders
                            TmxMap.MapOrientation restoreOrientation = tmxMap.Orientation;
                            tmxMap.Orientation = TmxMap.MapOrientation.Orthogonal;
                            {
                                // Make up for the fact that the bottom-left corner is the origin
                                canvas.Translate(0, -tmxObjectTile.Tile.TileSize.Height);
                                foreach (var obj in tmxObjectTile.Tile.ObjectGroup.Objects)
                                {
                                    TmxObjectType type = tmxMap.ObjectTypes.GetValueOrDefault(obj.Type);
                                    DrawObjectCollider(canvas, tmxMap, obj, type.Color.ToSKColor());
                                }
                            }
                            tmxMap.Orientation = restoreOrientation;
                        }
                    }
                    else
                    {
                        Logger.WriteWarning("Unhandled object: {0}", tmxObject.GetNonEmptyName());
                    }
                }
        }
示例#16
0
        private static void DrawObjectCollider(Graphics g, TmxMap tmxMap, TmxObject tmxObject, Color color)
        {
            using (Brush brush = TmxHelper.CreateObjectColliderBrush(color))
                using (Pen pen = new Pen(color))
                {
                    GraphicsState state = g.Save();

                    PointF xfPosition = TmxMath.ObjectPointFToMapSpace(tmxMap, tmxObject.Position);
                    g.TranslateTransform(xfPosition.X, xfPosition.Y);
                    g.RotateTransform(tmxObject.Rotation);

                    if (tmxObject.GetType() == typeof(TmxObjectPolygon))
                    {
                        DrawPolygon(g, pen, brush, tmxMap, tmxObject as TmxObjectPolygon);
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectRectangle))
                    {
                        if (tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
                        {
                            TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(tmxMap, tmxObject as TmxObjectRectangle);
                            DrawPolygon(g, pen, brush, tmxMap, tmxIsometricRectangle);
                        }
                        else
                        {
                            // Rectangles are polygons
                            DrawPolygon(g, pen, brush, tmxMap, tmxObject as TmxObjectPolygon);
                        }
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectEllipse))
                    {
                        DrawEllipse(g, pen, brush, tmxMap, tmxObject as TmxObjectEllipse);
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectPolyline))
                    {
                        DrawPolyline(g, pen, tmxMap, tmxObject as TmxObjectPolyline);
                    }
                    else if (tmxObject.GetType() == typeof(TmxObjectTile))
                    {
                        GraphicsState tileState     = g.Save();
                        TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile;

                        // Isometric tiles are off by a half-width
                        if (tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
                        {
                            g.TranslateTransform(-tmxMap.TileWidth * 0.5f, 0);
                        }

                        // Apply scale
                        SizeF scale = tmxObjectTile.GetTileObjectScale();
                        g.ScaleTransform(scale.Width, scale.Height);

                        // Apply horizontal flip
                        if (tmxObjectTile.FlippedHorizontal)
                        {
                            g.TranslateTransform(tmxObjectTile.Tile.TileSize.Width, 0);
                            g.ScaleTransform(-1, 1);
                        }

                        // Apply vertical flip
                        if (tmxObjectTile.FlippedVertical)
                        {
                            g.TranslateTransform(0, -tmxObjectTile.Tile.TileSize.Height);
                            g.ScaleTransform(1, -1);
                        }

                        // (Note: Now we can draw the tile and collisions as normal as the transforms have been set up.)

                        // Draw the tile
                        Rectangle destination = new Rectangle(0, -tmxObjectTile.Tile.TileSize.Height, tmxObjectTile.Tile.TileSize.Width, tmxObjectTile.Tile.TileSize.Height);
                        Rectangle source      = new Rectangle(tmxObjectTile.Tile.LocationOnSource, tmxObjectTile.Tile.TileSize);
                        g.DrawImage(tmxObjectTile.Tile.TmxImage.ImageBitmap, destination, source, GraphicsUnit.Pixel);

                        // Put a black border around the tile so it sticks out a bit as an object
                        g.DrawRectangle(Pens.Black, destination);

                        // Draw the collisions
                        // Temporarily set orienation to Orthogonal for tile colliders
                        TmxMap.MapOrientation restoreOrientation = tmxMap.Orientation;
                        tmxMap.Orientation = TmxMap.MapOrientation.Orthogonal;
                        {
                            // Make up for the fact that the bottom-left corner is the origin
                            g.TranslateTransform(0, -tmxObjectTile.Tile.TileSize.Height);
                            foreach (var obj in tmxObjectTile.Tile.ObjectGroup.Objects)
                            {
                                DrawObjectCollider(g, tmxMap, obj, Color.Gray);
                            }
                        }
                        tmxMap.Orientation = restoreOrientation;

                        g.Restore(tileState);
                    }
                    else
                    {
                        g.Restore(state);
                        Logger.WriteWarning("Unhandled object: {0}", tmxObject.GetNonEmptyName());
                    }

                    // Restore our state
                    g.Restore(state);
                }
        }
示例#17
0
        private static void DrawPolyline(Graphics g, Pen pen, TmxMap tmxMap, TmxObjectPolyline tmxPolyline)
        {
            var points = TmxMath.GetPointsInMapSpace(tmxMap, tmxPolyline).ToArray();

            g.DrawLines(pen, points);
        }
示例#18
0
        private static void DrawGridQuad(SKCanvas canvas, TmxMap tmxMap)
        {
            HashSet <Point> points = new HashSet <Point>();

            for (int x = 0; x < GetMaxTilesWide(tmxMap); ++x)
            {
                for (int y = 0; y < GetMaxTilesHigh(tmxMap); ++y)
                {
                    // Add the "top-left" corner of a tile
                    points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x, y));

                    // Add all other corners of the tile to our list of grid points
                    // This is complicated by different map types (espcially staggered isometric)
                    if (tmxMap.Orientation == TmxMap.MapOrientation.Orthogonal || tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
                    {
                        points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x + 1, y));
                        points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x + 1, y + 1));
                        points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x, y + 1));
                    }
                    else if (tmxMap.Orientation == TmxMap.MapOrientation.Staggered)
                    {
                        bool sx = TmxMath.DoStaggerX(tmxMap, x);
                        bool sy = TmxMath.DoStaggerY(tmxMap, y);

                        if (sx)
                        {
                            // top-right, bottom-right, and bottom-left
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x + 1, y + 1));
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x, y + 1));
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x - 1, y + 1));
                        }
                        else if (sy)
                        {
                            // top-right, bottom-right, and bottom-left
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x + 1, y + 1));
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x, y + 2));
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x, y + 1));
                        }
                        else if (tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.X)
                        {
                            // top-right, bottom-right, and bottom-left
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x + 1, y));
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x, y + 1));
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x - 1, y));
                        }
                        else if (tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.Y)
                        {
                            // top-right, bottom-right, and bottom-left
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x, y + 1));
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x, y + 2));
                            points.Add(TmxMath.TileCornerFromGridCoordinates(tmxMap, x - 1, y + 1));
                        }
                    }
                }
            }

            // Can take for granted that background is always white in drawing black rectangles
            using (SKPaint paint = new SKPaint())
            {
                paint.Color       = SKColors.Black;
                paint.Style       = SKPaintStyle.Stroke;
                paint.StrokeWidth = StrokeWidthThin;
                foreach (var p in points)
                {
                    SKRect rc = SKRect.Create(p.X, p.Y, PreviewImage.GridSize, PreviewImage.GridSize);
                    rc.Offset(-PreviewImage.GridSize * 0.5f, -PreviewImage.GridSize * 0.5f);
                    canvas.DrawRect(rc, paint);
                }
            }
        }