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); }
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); } }
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); } }
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); } }
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); } }
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); } }
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); } } } } }
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); }
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); } }
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 } }
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); } }
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()); } }
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); } } } }
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); }
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()); } } }
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); } }
private static void DrawPolyline(Graphics g, Pen pen, TmxMap tmxMap, TmxObjectPolyline tmxPolyline) { var points = TmxMath.GetPointsInMapSpace(tmxMap, tmxPolyline).ToArray(); g.DrawLines(pen, points); }
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); } } }