コード例 #1
0
        private void FixTileColliderObjects(TmxMap tmxMap)
        {
            // Objects inside of tiles are colliders that will be merged with the colliders on neighboring tiles.
            // In order to promote this merging we have to perform the following clean up operations ...
            // - All rectangles objects are made into polygon objects
            // - All polygon objects will have their rotations burned into the polygon points (and Rotation set to zero)
            // - All cooridinates will be "sanitized" to make up for floating point errors due to rotation and poor placement of colliders
            // (The sanitation will round all numbers to the nearest 1/256th)

            // Replace rectangles with polygons
            for (int i = 0; i < this.ObjectGroup.Objects.Count; i++)
            {
                TmxObject tmxObject = this.ObjectGroup.Objects[i];
                if (tmxObject is TmxObjectRectangle)
                {
                    TmxObjectPolygon tmxObjectPolygon = TmxObjectPolygon.FromRectangle(tmxMap, tmxObject as TmxObjectRectangle);
                    this.ObjectGroup.Objects[i] = tmxObjectPolygon;
                }
            }

            // Burn rotation into all polygon points, sanitizing the point locations as we go
            foreach (TmxObject tmxObject in this.ObjectGroup.Objects)
            {
                TmxHasPoints tmxHasPoints = tmxObject as TmxHasPoints;
                if (tmxHasPoints != null)
                {
                    var pointfs = tmxHasPoints.Points.ToArray();

                    // Rotate our points by the rotation and position in the object
                    TmxMath.RotatePoints(pointfs, tmxObject);

                    // Sanitize our points to make up for floating point precision errors
                    pointfs = pointfs.Select(TmxMath.Sanitize).ToArray();

                    // Set the points back into the object
                    tmxHasPoints.Points = pointfs.ToList();

                    // Zero out our rotation
                    tmxObject.BakeRotation();
                }
            }
        }
コード例 #2
0
 private void FixTileColliderObjects(TmxMap tmxMap)
 {
     for (int i = 0; i < ObjectGroup.Objects.Count; i++)
     {
         TmxObject tmxObject = ObjectGroup.Objects[i];
         if (tmxObject is TmxObjectRectangle)
         {
             TmxObjectPolygon value = TmxObjectPolygon.FromRectangle(tmxMap, tmxObject as TmxObjectRectangle);
             ObjectGroup.Objects[i] = value;
         }
     }
     foreach (TmxObject @object in ObjectGroup.Objects)
     {
         TmxHasPoints tmxHasPoints = @object as TmxHasPoints;
         if (tmxHasPoints != null)
         {
             PointF[] array = tmxHasPoints.Points.ToArray();
             TmxMath.RotatePoints(array, @object);
             array = array.Select(TmxMath.Sanitize).ToArray();
             tmxHasPoints.Points = array.ToList();
             @object.BakeRotation();
         }
     }
 }
コード例 #3
0
        private List <XElement> CreateObjectElementList(TmxObjectGroup objectGroup)
        {
            List <XElement> elements = new List <XElement>();

            foreach (TmxObject tmxObject in objectGroup.Objects)
            {
                // All the objects/colliders in our object group need to be separate game objects because they can have unique tags/layers
                XElement xmlObject = new XElement("GameObject", new XAttribute("name", tmxObject.GetNonEmptyName()));

                // Transform object locaction into map space (needed for isometric and hex modes)
                PointF xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position);
                PointF pos        = PointFToUnityVector(xfPosition);
                xmlObject.SetAttributeValue("x", pos.X);
                xmlObject.SetAttributeValue("y", pos.Y);
                xmlObject.SetAttributeValue("rotation", tmxObject.Rotation);

                AssignUnityProperties(tmxObject, xmlObject, PrefabContext.Object);
                AssignTiledProperties(tmxObject, xmlObject);

                // If we're not using a unity:layer override and there is an Object Type to go with this object then use it
                if (String.IsNullOrEmpty(objectGroup.UnityLayerOverrideName))
                {
                    xmlObject.SetAttributeValue("layer", tmxObject.Type);
                }

                XElement objElement = null;

                if (tmxObject.GetType() == typeof(TmxObjectRectangle))
                {
                    if (this.tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
                    {
                        TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(this.tmxMap, tmxObject as TmxObjectRectangle);
                        objElement = CreatePolygonColliderElement(tmxIsometricRectangle);
                    }
                    else
                    {
                        objElement = CreateBoxColliderElement(tmxObject as TmxObjectRectangle);
                    }
                }
                else if (tmxObject.GetType() == typeof(TmxObjectEllipse))
                {
                    objElement = CreateCircleColliderElement(tmxObject as TmxObjectEllipse, objectGroup.Name);
                }
                else if (tmxObject.GetType() == typeof(TmxObjectPolygon))
                {
                    objElement = CreatePolygonColliderElement(tmxObject as TmxObjectPolygon);
                }
                else if (tmxObject.GetType() == typeof(TmxObjectPolyline))
                {
                    objElement = CreateEdgeColliderElement(tmxObject as TmxObjectPolyline);
                }
                else if (tmxObject.GetType() == typeof(TmxObjectTile))
                {
                    TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile;

                    // Apply z-cooridnate for use with the depth buffer
                    // (Again, this is complicated by the fact that object tiles position is WRT the bottom edge of a tile)
                    if (Tiled2Unity.Settings.DepthBufferEnabled)
                    {
                        float mapLogicalHeight  = this.tmxMap.MapSizeInPixels().Height;
                        float tileLogicalHeight = this.tmxMap.TileHeight;
                        float logicalPos_y      = (-pos.Y / Tiled2Unity.Settings.Scale) - tileLogicalHeight;

                        float depth_z = CalculateFaceDepth(logicalPos_y, mapLogicalHeight);
                        xmlObject.SetAttributeValue("z", depth_z);
                    }

                    AddTileObjectElements(tmxObject as TmxObjectTile, xmlObject);
                }
                else
                {
                    Logger.WriteLine("Object '{0}' has been added for use with custom importers", tmxObject);
                }

                if (objElement != null)
                {
                    xmlObject.Add(objElement);
                }

                elements.Add(xmlObject);
            }

            return(elements);
        }
コード例 #4
0
        private List <XElement> CreateObjectElementList(TmxObjectGroup objectGroup)
        {
            List <XElement> elements = new List <XElement>();

            foreach (TmxObject tmxObject in objectGroup.Objects)
            {
                // All the objects/colliders in our object group need to be separate game objects because they can have unique tags/layers
                XElement xmlObject = new XElement("GameObject", new XAttribute("name", tmxObject.GetNonEmptyName()));

                // Transform object locaction into map space (needed for isometric and hex modes)
                PointF xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position);
                PointF pos        = PointFToUnityVector(xfPosition);
                xmlObject.SetAttributeValue("x", pos.X);
                xmlObject.SetAttributeValue("y", pos.Y);
                xmlObject.SetAttributeValue("rotation", tmxObject.Rotation);

                AssignUnityProperties(tmxObject, xmlObject, PrefabContext.Object);
                AssignTiledProperties(tmxObject, xmlObject);

                // If we're not using a unity:layer override and there is an Object Type to go with this object then use it
                if (String.IsNullOrEmpty(objectGroup.UnityLayerOverrideName))
                {
                    // why would we /ever/ do this, christ
                    //xmlObject.SetAttributeValue("layer", tmxObject.Type);
                }

                XElement objElement   = null;
                XElement objComponent = new XElement("TmxObjectComponent",
                                                     new XAttribute("tmx-object-id", tmxObject.Id),
                                                     new XAttribute("tmx-object-name", tmxObject.Name),
                                                     new XAttribute("tmx-object-type", tmxObject.Type),
                                                     new XAttribute("tmx-object-x", tmxObject.Position.X),
                                                     new XAttribute("tmx-object-y", tmxObject.Position.Y),
                                                     new XAttribute("tmx-object-width", tmxObject.Size.Width),
                                                     new XAttribute("tmx-object-height", tmxObject.Size.Height),
                                                     new XAttribute("tmx-object-rotation", tmxObject.Rotation));

                // Do not create colliders if the are being ignored. (Still want to creat the game object though)
                bool ignoringCollisions = (objectGroup.Ignore == TmxLayerNode.IgnoreSettings.Collision);

                if (!ignoringCollisions && tmxObject.GetType() == typeof(TmxObjectRectangle))
                {
                    if (this.tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
                    {
                        TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(this.tmxMap, tmxObject as TmxObjectRectangle);
                        objElement = CreatePolygonColliderElement(tmxIsometricRectangle);
                    }
                    else
                    {
                        objElement = CreateBoxColliderElement(tmxObject as TmxObjectRectangle);
                    }

                    // Set object component type
                    objComponent.Name = "RectangleObjectComponent";
                }
                else if (!ignoringCollisions && tmxObject.GetType() == typeof(TmxObjectEllipse))
                {
                    objElement = CreateCircleColliderElement(tmxObject as TmxObjectEllipse, objectGroup.Name);

                    // Set the component type
                    objComponent.Name = "CircleObjectComponent";
                }
                else if (!ignoringCollisions && tmxObject.GetType() == typeof(TmxObjectPolygon))
                {
                    objElement = CreatePolygonColliderElement(tmxObject as TmxObjectPolygon);

                    // Set the component type
                    objComponent.Name = "PolygonObjectComponent";
                }
                else if (!ignoringCollisions && tmxObject.GetType() == typeof(TmxObjectPolyline))
                {
                    objElement = CreateEdgeColliderElement(tmxObject as TmxObjectPolyline);

                    // Set the component type
                    objComponent.Name = "PolylineObjectComponent";
                }
                else if (tmxObject.GetType() == typeof(TmxObjectTile))
                {
                    TmxObjectTile tmxObjectTile = tmxObject as TmxObjectTile;

                    // Apply z-cooridnate for use with the depth buffer
                    if (Tiled2Unity.Settings.DepthBufferEnabled)
                    {
                        float depth_z = CalculateFaceDepth(tmxObjectTile.Position.Y, tmxMap.MapSizeInPixels.Height);
                        xmlObject.SetAttributeValue("z", depth_z);
                    }

                    AddTileObjectElements(tmxObjectTile, xmlObject, objComponent);
                }
                else
                {
                    Logger.WriteLine("Object '{0}' has been added for use with custom importers", tmxObject);
                }

                if (objElement != null)
                {
                    xmlObject.Add(objComponent);
                    xmlObject.Add(objElement);
                }

                elements.Add(xmlObject);
            }

            return(elements);
        }
コード例 #5
0
        private List <XElement> CreateObjectElementList(TmxObjectGroup objectGroup)
        {
            List <XElement> elements = new List <XElement>();

            foreach (TmxObject tmxObject in objectGroup.Objects)
            {
                // All the objects/colliders in our object group need to be separate game objects because they can have unique tags/layers
                XElement xmlObject = new XElement("GameObject", new XAttribute("name", tmxObject.GetNonEmptyName()));

                // Transform object locaction into map space (needed for isometric and hex modes)
                PointF xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position);
                PointF pos        = PointFToUnityVector(xfPosition);
                xmlObject.SetAttributeValue("x", pos.X);
                xmlObject.SetAttributeValue("y", pos.Y);
                xmlObject.SetAttributeValue("rotation", tmxObject.Rotation);

                AssignUnityProperties(tmxObject, xmlObject, PrefabContext.Object);
                AssignTiledProperties(tmxObject, xmlObject);

                XElement objElement = null;

                if (tmxObject.GetType() == typeof(TmxObjectRectangle))
                {
                    if (this.tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
                    {
                        TmxObjectPolygon tmxIsometricRectangle = TmxObjectPolygon.FromRectangle(this.tmxMap, tmxObject as TmxObjectRectangle);
                        objElement = CreatePolygonColliderElement(tmxIsometricRectangle);
                    }
                    else
                    {
                        objElement = CreateBoxColliderElement(tmxObject as TmxObjectRectangle);
                    }
                }
                else if (tmxObject.GetType() == typeof(TmxObjectEllipse))
                {
                    objElement = CreateCircleColliderElement(tmxObject as TmxObjectEllipse, objectGroup.Name);
                }
                else if (tmxObject.GetType() == typeof(TmxObjectPolygon))
                {
                    objElement = CreatePolygonColliderElement(tmxObject as TmxObjectPolygon);
                }
                else if (tmxObject.GetType() == typeof(TmxObjectPolyline))
                {
                    objElement = CreateEdgeColliderElement(tmxObject as TmxObjectPolyline);
                }
                else if (tmxObject.GetType() == typeof(TmxObjectTile))
                {
                    AddTileObjectElements(tmxObject as TmxObjectTile, xmlObject);
                }
                else
                {
                    Program.WriteLine("Object '{0}' has been added for use with custom importers", tmxObject);
                }

                if (objElement != null)
                {
                    xmlObject.Add(objElement);
                }

                elements.Add(xmlObject);
            }

            return(elements);
        }
コード例 #6
0
        private void DrawObjectCollider(Graphics g, TmxObject tmxObject, Color color)
        {
            Color brushColor = Color.FromArgb(128, color);

            using (Brush brush = new HatchBrush(HatchStyle.BackwardDiagonal, color, brushColor))
                using (Pen pen = new Pen(color))
                {
                    pen.Alignment = PenAlignment.Inset;

                    GraphicsState state = g.Save();

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

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

                        // 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
                        // 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, obj, Color.Gray);
                        }

                        g.Restore(tileState);
                    }
                    else
                    {
                        g.Restore(state);
                        RectangleF bounds = tmxObject.GetWorldBounds();
                        g.FillRectangle(Brushes.Red, bounds.X, bounds.Y, bounds.Width, bounds.Height);
                        g.DrawRectangle(Pens.White, bounds.X, bounds.Y, bounds.Width, bounds.Height);
                        string message = String.Format("Unhandled object: {0}", tmxObject.GetNonEmptyName());
                        DrawString(g, message, bounds.X, bounds.Y);
                    }

                    // Restore our state
                    g.Restore(state);
                }
        }