Example #1
0
        // TODO: Implement rotation! -> ok, you can rotate inside tiled...
        /// <summary>
        /// Generates Clipper's Path. As Clipper uses Integer for calculations, all point values are pre-multiplied by a factor of ClipperScale to minimize precision lost.
        /// </summary>
        /// <param name="tileX">Tile X position in the scene</param>
        /// <param name="tileY">Tile Y position in the scene</param>
        /// <param name="spriteEffects">The Tile's SpriteEffects in the TileLayer to generate its correct path if it is rotated.</param>
        /// <returns>List of IntPoints to be used with ClipperLib functions</returns>
        public List<IntPoint> GetPath(int tileX, int tileY, SpriteEffects spriteEffects, int mapTileWidth, int mapTileHeight)
        {
            List<IntPoint> path = new List<IntPoint>();
            // First we copy this object's point to a list, generating Box points' if needed and approximating an ellipse
            List<Vector2> points = new List<Vector2>();

            // For tiles higher than the tileset, we must add this differente to the points.
            // This only happens with ImageCollections TileSets, for normal TileSets, heightDifference == 0.
            float heightDifference = (TileHeight - mapTileHeight) / (float)mapTileHeight;

            switch (ObjectType)
            {
                case ObjectType.Box:
                    points.Add(new Vector2(Bounds.xMin, Bounds.yMin - heightDifference));
                    points.Add(new Vector2(Bounds.xMax, Bounds.yMin - heightDifference));
                    points.Add(new Vector2(Bounds.xMax, Bounds.yMax - heightDifference));
                    points.Add(new Vector2(Bounds.xMin, Bounds.yMax - heightDifference));
                    break;
                case ObjectType.Ellipse:
                    #region Approximate Ellipse
                    // Segments per quadrant
                    int incFactor = Mathf.FloorToInt(XUniTMXConfiguration.Instance.EllipsoideColliderApproximationFactor / 4.0f);
                    float minIncrement = 2 * Mathf.PI / (incFactor * XUniTMXConfiguration.Instance.EllipsoideColliderApproximationFactor / 2.0f);
                    int currentInc = 0;
                    // grow represents if we are going right on x-axis (true) or left (false)
                    bool grow = true;

                    // Ellipsoide center
                    //Vector2 center = new Vector2(Bounds.x + Bounds.width / 2.0f, heightRatio - Bounds.y - Bounds.height / 2.0f - heightDifference);
                    Vector2 center = new Vector2(Bounds.x + Bounds.width / 2.0f, Bounds.y + Bounds.height / 2.0f - heightDifference);

                    float r = 0;
                    float angle = 0;
                    for (int i = 0; i < XUniTMXConfiguration.Instance.EllipsoideColliderApproximationFactor; i++)
                    {
                        // Calculate radius at each point
                        angle += currentInc * minIncrement;

                        r = Bounds.width * Bounds.height / Mathf.Sqrt(Mathf.Pow(Bounds.height * Mathf.Cos(angle), 2) + Mathf.Pow(Bounds.width * Mathf.Sin(angle), 2)) / 2.0f;

                        // Define the point localization using the calculated radius, angle and center
                        points.Add(r * new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) + center);

                        // if we are "growing", increment the angle, else, start decrementing it to close the polygon
                        if (grow)
                            currentInc++;
                        else
                            currentInc--;
                        if (currentInc > incFactor - 1 || currentInc < 1)
                            grow = !grow;
                    }
                    #endregion
                    break;
                case ObjectType.Polygon:
                case ObjectType.Polyline:
                    for (int i = 0; i < Points.Count; i++)
                    {
                        points.Add(new Vector2(Points[i].x + Bounds.x, Points[i].y + Bounds.y - heightDifference));
                    }
                    break;
            }

            // Then, rotate / flip if needed
            Vector2 flipAnchor = Vector2.one;
            Vector2 rotateAnchor = new Vector2(0.5f, 0.5f);
            if (Rotation != 0)
            {
                for (int i = 0; i < points.Count; i++)
                {
                    points[i] = points[i].RotatePoint(Bounds.x, Bounds.y, Rotation * Mathf.Deg2Rad);
                }
            }

            if (spriteEffects != null)
            {
                if (spriteEffects.flippedAntiDiagonally || spriteEffects.flippedHorizontally || spriteEffects.flippedVertically)
                {
                    if (spriteEffects.flippedHorizontally == true &&
                        spriteEffects.flippedVertically == false &&
                        spriteEffects.flippedAntiDiagonally == false)
                    {
                        for (int i = 0; i < points.Count; i++)
                        {
                            points[i] = points[i].FlipPointHorizontally(flipAnchor);
                        }
                    }

                    if (spriteEffects.flippedHorizontally == false &&
                        spriteEffects.flippedVertically == true &&
                        spriteEffects.flippedAntiDiagonally == false)
                    {
                        for (int i = 0; i < points.Count; i++)
                        {
                            points[i] = points[i].FlipPointVertically(flipAnchor);
                        }
                    }

                    if (spriteEffects.flippedHorizontally == true &&
                        spriteEffects.flippedVertically == true &&
                        spriteEffects.flippedAntiDiagonally == false)
                    {
                        for (int i = 0; i < points.Count; i++)
                        {
                            points[i] = points[i].FlipPointDiagonally(flipAnchor);
                        }
                    }

                    if (spriteEffects.flippedHorizontally == false &&
                        spriteEffects.flippedVertically == false &&
                        spriteEffects.flippedAntiDiagonally == true)
                    {
                        for (int i = 0; i < points.Count; i++)
                        {
                            points[i] = points[i].RotatePoint(rotateAnchor, 90 * Mathf.Deg2Rad);
                            //points[i] = points[i].FlipPointDiagonally(flipAnchor);
                            points[i] = points[i].FlipPointVertically(flipAnchor);
                        }
                    }

                    if (spriteEffects.flippedHorizontally == true &&
                        spriteEffects.flippedVertically == false &&
                        spriteEffects.flippedAntiDiagonally == true)
                    {
                        for (int i = 0; i < points.Count; i++)
                        {
                            points[i] = points[i].RotatePoint(rotateAnchor, 90 * Mathf.Deg2Rad);
                            points[i] = points[i].FlipPointDiagonally(flipAnchor);
                        }
                    }

                    if (spriteEffects.flippedHorizontally == false &&
                        spriteEffects.flippedVertically == true &&
                        spriteEffects.flippedAntiDiagonally == true)
                    {
                        for (int i = 0; i < points.Count; i++)
                        {
                            points[i] = points[i].RotatePoint(rotateAnchor, -90 * Mathf.Deg2Rad);
                            points[i] = points[i].FlipPointDiagonally(flipAnchor);
                        }
                    }

                    if (spriteEffects.flippedHorizontally == true &&
                        spriteEffects.flippedVertically == true &&
                        spriteEffects.flippedAntiDiagonally == true)
                    {
                        for (int i = 0; i < points.Count; i++)
                        {
                            points[i] = points[i].RotatePoint(rotateAnchor, -90 * Mathf.Deg2Rad);
                            points[i] = points[i].FlipPointVertically(flipAnchor);
                        }
                    }
                }
            }

            // Finally, position the points using tileX and tileY position, apply ClipperScale and add to the path
            for (int i = 0; i < points.Count; i++)
            {
                path.Add(
                    new IntPoint(
                        (points[i].x + tileX) * ClipperScale,
                        (points[i].y + tileY) * ClipperScale
                    )
                );
            }

            return path;
        }
Example #2
0
        private void Initialize(Map map, uint[] data, List<Material> materials)
        {
            Tiles = new TileGrid(Width, Height);
            BaseMap = map;
            BaseMaterials = materials;
            LayerTileSets = new List<TileSet>();
            // data is left-to-right, top-to-bottom
            for (int x = 0; x < Width; x++)
            {
                for (int y = 0; y < Height; y++)
                {
                    uint id = data[y * Width + x];

                    // compute the SpriteEffects to apply to this tile
                    SpriteEffects spriteEffects = new SpriteEffects();

                    // MARIO: new method to verify flipped tiles
                    spriteEffects.flippedHorizontally = (id & FlippedHorizontallyFlag) == FlippedHorizontallyFlag;
                    spriteEffects.flippedVertically = (id & FlippedVerticallyFlag) == FlippedVerticallyFlag;
                    spriteEffects.flippedAntiDiagonally = (id & FlippedAntiDiagonallyFlag) == FlippedAntiDiagonallyFlag;

                    // MARIO: new strip out the flip flags to get the real ID
                    // Fixed for AntiDiagonallyFlgs
                    id &= ~(FlippedHorizontallyFlag |
                            FlippedVerticallyFlag |
                            FlippedAntiDiagonallyFlag);

                    // get the tile
                    Tile t = null;
                    BaseMap.Tiles.TryGetValue((int)id, out t);

                    // if the tile is non-null...
                    if (t != null)
                    {
                        // if we want unique instances, clone it
                        if (MakeUniqueTiles)
                        {
                            t = t.Clone();
                            t.SpriteEffects = spriteEffects;
                        }

                        // otherwise we may need to clone if the tile doesn't have the correct effects
                        // in this world a flipped tile is different than a non-flipped one; just because
                        // they have the same source rect doesn't mean they're equal.
                        else if (t.SpriteEffects != spriteEffects)
                        {
                            t = t.Clone();
                            t.SpriteEffects = spriteEffects;
                        }

                        // Add this Tile's TileSet to LayerTileSets list, if it is not there yet
                        if (!LayerTileSets.Contains(t.TileSet))
                            LayerTileSets.Add(t.TileSet);
                    }

                    // put that tile in our grid
                    Tiles[x, y] = t;
                }
            }

            GenerateLayer();
        }