using UnityEngine;
using System.Collections.Generic;

[System.Serializable]
public class Map : MonoBehaviour
{
    [HideInInspector]
    private TileType[,] mTiles;
    private SpriteRenderer[,] mTilesSprites;

    public Vector3 mPosition;

    public int mWidth = 80;
    public int mHeight = 60;

    public SpriteRenderer mTilePrefab;

    public const int cTileSize = 16;


    public List<Sprite> mDirtSprites;

    public TileCollisionType[,] mTilesCollision;

    private static List<Vector2i> mOverlappingAreas = new List<Vector2i>(4);

    /// <summary>
    /// A set of areas in which at least one tile has been destroyed
    /// </summary>
    private HashSet<Vector2i> mUpdatedAreas;

    /// <summary>
    /// How many collision areas are there on the map horizontally.
    /// </summary>
    [HideInInspector]
    public int mHorizontalAreasCount;

    /// <summary>
    /// How many collision areas are there on the map vertically.
    /// </summary>
    [HideInInspector]
    public int mVerticalAreasCount;

    [SerializeField]
    public int mGridAreaWidth = 16;
    [SerializeField]
    public int mGridAreaHeight = 16;
    [HideInInspector]
    public List<MovingObject>[,] mObjectsInArea;

    public static List<MovingObject> mCollisionRequestObjects = new List<MovingObject>();

    public void RemoveObjectFromAreas(MovingObject obj)
    {
        for (int i = 0; i < obj.mAreas.Count; ++i)
            RemoveObjectFromArea(obj.mAreas[i], obj.mIdsInAreas[i], obj);
        obj.mAreas.Clear();
        obj.mIdsInAreas.Clear();
    }

    public void DebugPrintAreas()
    {
        Debug.Log("Objects in areas:");

        for (int y = 0; y < mVerticalAreasCount; ++y)
        {
            for (int x = 0; x < mHorizontalAreasCount; ++x)
            {
                var objs = mObjectsInArea[x, y];
                if (objs.Count > 0)
                {
                    Debug.Log("Area X: " + x + " Y: " + y + " obj count: " + objs.Count);
                    for (int i = 0; i < objs.Count; ++i)
                    {
                        Debug.Log(objs[i].name);
                    }
                }
            }
        }

        Debug.Log("Object in areas End");
    }

    public void RemoveObjectFromArea(Vector2i areaIndex, int objIndexInArea, MovingObject obj)
    {
        var area = mObjectsInArea[areaIndex.x, areaIndex.y];

        if (Debug.isDebugBuild && area.Count == 0)
        {
            Debug.Log("Removing object from an area that doesn't contain any objects, areaIndex: " + areaIndex.x + ", " + areaIndex.y + ", objIndexInArea: " + objIndexInArea);
            Debug.Break();
        }

        //swap the last item with the one we are removing
        var tmp = area[area.Count - 1];
        area[area.Count - 1] = obj;
        area[objIndexInArea] = tmp;

        var tmpIds = tmp.mIdsInAreas;
        var tmpAreas = tmp.mAreas;
        for (int i = 0; i < tmpAreas.Count; ++i)
        {
            if (tmpAreas[i] == areaIndex)
            {
                tmpIds[i] = objIndexInArea;
                break;
            }
        }

        //remove the last item
        area.RemoveAt(area.Count - 1);
    }

    public void AddObjectToArea(Vector2i areaIndex, MovingObject obj)
    {
        var area = mObjectsInArea[areaIndex.x, areaIndex.y];

        //save the index of  the object in the area
        obj.mAreas.Add(areaIndex);
        obj.mIdsInAreas.Add(area.Count);

        //add the object to the area
        area.Add(obj);
    }

    public void UpdateAreas(MovingObject obj)
    {
        //get the areas at the aabb's corners
        var topLeft = GetMapTileAtPoint((Vector2)obj.mAABB.Center + new Vector2(-obj.mAABB.HalfSize.x, obj.mAABB.HalfSizeY));
        var topRight = GetMapTileAtPoint(obj.mAABB.Center + obj.mAABB.HalfSize);
        var bottomLeft = GetMapTileAtPoint(obj.mAABB.Center - obj.mAABB.HalfSize);
        var bottomRight = new Vector2i();

        topLeft.x /= mGridAreaWidth;
        topLeft.y /= mGridAreaHeight;

        topRight.x /= mGridAreaWidth;
        topRight.y /= mGridAreaHeight;

        bottomLeft.x /= mGridAreaWidth;
        bottomLeft.y /= mGridAreaHeight;

        /*topLeft.x = Mathf.Clamp(topLeft.x, 0, mHorizontalAreasCount - 1);
        topLeft.y = Mathf.Clamp(topLeft.y, 0, mVerticalAreasCount - 1);

        topRight.x = Mathf.Clamp(topRight.x, 0, mHorizontalAreasCount - 1);
        topRight.y = Mathf.Clamp(topRight.y, 0, mVerticalAreasCount - 1);

        bottomLeft.x = Mathf.Clamp(bottomLeft.x, 0, mHorizontalAreasCount - 1);
        bottomLeft.y = Mathf.Clamp(bottomLeft.y, 0, mVerticalAreasCount - 1);*/

        bottomRight.x = topRight.x;
        bottomRight.y = bottomLeft.y;

        //see how many different areas we have
        if (topLeft.x == topRight.x && topLeft.y == bottomLeft.y)
        {
            mOverlappingAreas.Add(topLeft);
        }
        else if (topLeft.x == topRight.x)
        {
            mOverlappingAreas.Add(topLeft);
            mOverlappingAreas.Add(bottomLeft);
        }
        else if (topLeft.y == bottomLeft.y)
        {
            mOverlappingAreas.Add(topLeft);
            mOverlappingAreas.Add(topRight);
        }
        else
        {
            mOverlappingAreas.Add(topLeft);
            mOverlappingAreas.Add(bottomLeft);
            mOverlappingAreas.Add(topRight);
            mOverlappingAreas.Add(bottomRight);
        }

        var areas = obj.mAreas;
        var ids = obj.mIdsInAreas;

        for (int i = 0; i < areas.Count; ++i)
        {
            if (!mOverlappingAreas.Contains(areas[i]))
            {
                RemoveObjectFromArea(areas[i], ids[i], obj);
                //object no longer has an index in the area
                areas.RemoveAt(i);
                ids.RemoveAt(i);
                --i;
            }
        }

        for (var i = 0; i < mOverlappingAreas.Count; ++i)
        {
            var area = mOverlappingAreas[i];
            if (!areas.Contains(area))
                AddObjectToArea(area, obj);
        }

        mOverlappingAreas.Clear();
    }

    public TileType GetTile(int x, int y)
    {
        if (x < 0 || x >= mWidth
            || y < 0 || y >= mHeight)
            return TileType.Block;

        return mTiles[x, y];
    }

    public bool IsOneWayPlatform(int x, int y)
    {
        if (x < 0 || x >= mWidth
            || y < 0 || y >= mHeight)
            return false;

        return (mTiles[x, y] == TileType.OneWay);
    }

    public bool IsGround(int x, int y)
    {
        if (x < 0 || x >= mWidth
           || y < 0 || y >= mHeight)
            return false;

        return (mTiles[x, y] == TileType.OneWay || mTiles[x, y] == TileType.Block);
    }

    public bool IsGround(Vector2i pos)
    {
        return IsGround(pos.x, pos.y);
    }


    public bool IsObstacle(int x, int y)
    {
        if (x < 0 || x >= mWidth
            || y < 0 || y >= mHeight)
            return true;

        return (mTiles[x, y] == TileType.Block);
    }

    public bool IsEmpty(int x, int y)
    {
        if (x < 0 || x >= mWidth
            || y < 0 || y >= mHeight)
            return false;

        return (mTiles[x, y] == TileType.Empty);
    }

    public bool IsNotEmpty(int x, int y)
    {
        if (x < 0 || x >= mWidth
            || y < 0 || y >= mHeight)
            return true;

        return (mTiles[x, y] != TileType.Empty);
    }

    public void GetMapTileAtPoint(Vector2 point, out int tileIndexX, out int tileIndexY)
    {
        tileIndexY = (int)((point.y - mPosition.y + cTileSize / 2.0f) / (float)(cTileSize));
        tileIndexX = (int)((point.x - mPosition.x + cTileSize / 2.0f) / (float)(cTileSize));
    }

    public int GetMapTileYAtPoint(float y)
    {
        return (int)((y - mPosition.y + cTileSize / 2.0f) / (float)(cTileSize));
    }

    public int GetMapTileXAtPoint(float x)
    {
        return (int)((x - mPosition.x + cTileSize / 2.0f) / (float)(cTileSize));
    }

    public Vector2i GetMapTileAtPoint(Vector2 point)
    {
        return new Vector2i((int)((point.x - mPosition.x + cTileSize / 2.0f) / (float)(cTileSize)),
                    (int)((point.y - mPosition.y + cTileSize / 2.0f) / (float)(cTileSize)));
    }

    public Vector2 GetMapTilePosition(int tileIndexX, int tileIndexY)
    {
        return new Vector2(
                (float)(tileIndexX * cTileSize) + mPosition.x,
                (float)(tileIndexY * cTileSize) + mPosition.y
            );
    }

    public Vector2 GetMapTilePosition(Vector2i tileCoords)
    {
        return new Vector2(
            (float)(tileCoords.x * cTileSize) + mPosition.x,
            (float)(tileCoords.y * cTileSize) + mPosition.y
            );
    }

    public TileCollisionType GetCollisionType(Vector2i pos)
    {
        if (pos.x <= -1 || pos.x >= mWidth
            || pos.y <= -1 || pos.y >= mHeight)
            return TileCollisionType.Empty;

        return mTilesCollision[pos.x, pos.y];
    }

    public TileCollisionType GetCollisionType(int x, int y)
    {
        if (x <= -1 || x >= mWidth
            || y <= -1 || y >= mHeight)
            return TileCollisionType.Empty;

        return mTilesCollision[x, y];
    }

    public TileCollisionType SetSprite(SpriteRenderer spr, TileType type)
    {
        var collisionType = TileCollisionType.Empty;
        sbyte tilesRotation = 0, tilesScaleX = 1, tilesScaleY = 1;
        int id = 0;

        if (type == TileType.Block)
        {
            id = 0;
            spr.sprite = mDirtSprites[id];
            spr.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
            spr.transform.localEulerAngles = new Vector3(0.0f, 0.0f, 0.0f);
            return TileCollisionType.Full;
        }
        else if (type == TileType.OneWay)
        {
            id = 25;
            spr.sprite = mDirtSprites[id];
            spr.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
            spr.transform.localEulerAngles = new Vector3(0.0f, 0.0f, 0.0f);
            return TileCollisionType.OneWayFull;
        }

        switch (type)
        {
            #region testSlope

            case TileType.TestSlope45:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 0;
                collisionType = TileCollisionType.Slope45;
                break;
            case TileType.TestSlope45FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 0;
                collisionType = TileCollisionType.Slope45FX;
                break;
            case TileType.TestSlope45FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 0;
                collisionType = TileCollisionType.Slope45FY;
                break;
            case TileType.TestSlope45FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 0;
                collisionType = TileCollisionType.Slope45FXY;
                break;
            case TileType.TestSlope45F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 0;
                collisionType = TileCollisionType.Slope45F90;
                break;
            case TileType.TestSlope45F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 0;
                collisionType = TileCollisionType.Slope45F90X;
                break;
            case TileType.TestSlope45F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 0;
                collisionType = TileCollisionType.Slope45F90Y;
                break;
            case TileType.TestSlope45F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 0;
                collisionType = TileCollisionType.Slope45F90XY;
                break;

            case TileType.TestSlopeMid1:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 1;
                collisionType = TileCollisionType.SlopeMid1;
                break;
            case TileType.TestSlopeMid1FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 1;
                collisionType = TileCollisionType.SlopeMid1FX;
                break;
            case TileType.TestSlopeMid1FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 1;
                collisionType = TileCollisionType.SlopeMid1FY;
                break;
            case TileType.TestSlopeMid1FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 1;
                collisionType = TileCollisionType.SlopeMid1FXY;
                break;
            case TileType.TestSlopeMid1F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 1;
                collisionType = TileCollisionType.SlopeMid1F90;
                break;
            case TileType.TestSlopeMid1F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 1;
                collisionType = TileCollisionType.SlopeMid1F90X;
                break;
            case TileType.TestSlopeMid1F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 1;
                collisionType = TileCollisionType.SlopeMid1F90Y;
                break;
            case TileType.TestSlopeMid1F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 1;
                collisionType = TileCollisionType.SlopeMid1F90XY;
                break;

            case TileType.TestSlopeMid1Rev:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 2;
                collisionType = TileCollisionType.SlopeMid1Rev;
                break;
            case TileType.TestSlopeMid1RevFX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 2;
                collisionType = TileCollisionType.SlopeMid1RevFX;
                break;
            case TileType.TestSlopeMid1RevFY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 2;
                collisionType = TileCollisionType.SlopeMid1RevFY;
                break;
            case TileType.TestSlopeMid1RevFXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 2;
                collisionType = TileCollisionType.SlopeMid1RevFXY;
                break;
            case TileType.TestSlopeMid1RevF90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 2;
                collisionType = TileCollisionType.SlopeMid1RevF90;
                break;
            case TileType.TestSlopeMid1RevF90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 2;
                collisionType = TileCollisionType.SlopeMid1RevF90X;
                break;
            case TileType.TestSlopeMid1RevF90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 2;
                collisionType = TileCollisionType.SlopeMid1RevF90Y;
                break;
            case TileType.TestSlopeMid1RevF90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 2;
                collisionType = TileCollisionType.SlopeMid1RevF90XY;
                break;

            case TileType.TestSlope22P1:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 3;
                collisionType = TileCollisionType.Slope22P1;
                break;
            case TileType.TestSlope22P1FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 3;
                collisionType = TileCollisionType.Slope22P1FX;
                break;
            case TileType.TestSlope22P1FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 3;
                collisionType = TileCollisionType.Slope22P1FY;
                break;
            case TileType.TestSlope22P1FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 3;
                collisionType = TileCollisionType.Slope22P1FXY;
                break;
            case TileType.TestSlope22P1F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 3;
                collisionType = TileCollisionType.Slope22P1F90;
                break;
            case TileType.TestSlope22P1F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 3;
                collisionType = TileCollisionType.Slope22P1F90X;
                break;
            case TileType.TestSlope22P1F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 3;
                collisionType = TileCollisionType.Slope22P1F90Y;
                break;
            case TileType.TestSlope22P1F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 3;
                collisionType = TileCollisionType.Slope22P1F90XY;
                break;

            case TileType.TestSlope22P2:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 4;
                collisionType = TileCollisionType.Slope22P2;
                break;
            case TileType.TestSlope22P2FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 4;
                collisionType = TileCollisionType.Slope22P2FX;
                break;
            case TileType.TestSlope22P2FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 4;
                collisionType = TileCollisionType.Slope22P2FY;
                break;
            case TileType.TestSlope22P2FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 4;
                collisionType = TileCollisionType.Slope22P2FXY;
                break;
            case TileType.TestSlope22P2F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 4;
                collisionType = TileCollisionType.Slope22P2F90;
                break;
            case TileType.TestSlope22P2F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 4;
                collisionType = TileCollisionType.Slope22P2F90X;
                break;
            case TileType.TestSlope22P2F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 4;
                collisionType = TileCollisionType.Slope22P2F90Y;
                break;
            case TileType.TestSlope22P2F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 4;
                collisionType = TileCollisionType.Slope22P2F90XY;
                break;

            case TileType.TestSlopeMid2:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 5;
                collisionType = TileCollisionType.SlopeMid2;
                break;
            case TileType.TestSlopeMid2FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 5;
                collisionType = TileCollisionType.SlopeMid2FX;
                break;
            case TileType.TestSlopeMid2FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 5;
                collisionType = TileCollisionType.SlopeMid2FY;
                break;
            case TileType.TestSlopeMid2FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 5;
                collisionType = TileCollisionType.SlopeMid2FXY;
                break;
            case TileType.TestSlopeMid2F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 5;
                collisionType = TileCollisionType.SlopeMid2F90;
                break;
            case TileType.TestSlopeMid2F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 5;
                collisionType = TileCollisionType.SlopeMid2F90X;
                break;
            case TileType.TestSlopeMid2F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 5;
                collisionType = TileCollisionType.SlopeMid2F90Y;
                break;
            case TileType.TestSlopeMid2F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 5;
                collisionType = TileCollisionType.SlopeMid2F90XY;
                break;

            case TileType.TestSlopeMid2Rev:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 6;
                collisionType = TileCollisionType.SlopeMid2Rev;
                break;
            case TileType.TestSlopeMid2RevFX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 6;
                collisionType = TileCollisionType.SlopeMid2RevFX;
                break;
            case TileType.TestSlopeMid2RevFY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 6;
                collisionType = TileCollisionType.SlopeMid2RevFY;
                break;
            case TileType.TestSlopeMid2RevFXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 6;
                collisionType = TileCollisionType.SlopeMid2RevFXY;
                break;
            case TileType.TestSlopeMid2RevF90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 6;
                collisionType = TileCollisionType.SlopeMid2RevF90;
                break;
            case TileType.TestSlopeMid2RevF90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 6;
                collisionType = TileCollisionType.SlopeMid2RevF90X;
                break;
            case TileType.TestSlopeMid2RevF90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 6;
                collisionType = TileCollisionType.SlopeMid2RevF90Y;
                break;
            case TileType.TestSlopeMid2RevF90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 6;
                collisionType = TileCollisionType.SlopeMid2RevF90XY;
                break;

            case TileType.TestSlope15P1:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 7;
                collisionType = TileCollisionType.Slope15P1;
                break;
            case TileType.TestSlope15P1FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 7;
                collisionType = TileCollisionType.Slope15P1FX;
                break;
            case TileType.TestSlope15P1FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 7;
                collisionType = TileCollisionType.Slope15P1FY;
                break;
            case TileType.TestSlope15P1FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 7;
                collisionType = TileCollisionType.Slope15P1FXY;
                break;
            case TileType.TestSlope15P1F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 7;
                collisionType = TileCollisionType.Slope15P1F90;
                break;
            case TileType.TestSlope15P1F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 7;
                collisionType = TileCollisionType.Slope15P1F90X;
                break;
            case TileType.TestSlope15P1F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 7;
                collisionType = TileCollisionType.Slope15P1F90Y;
                break;
            case TileType.TestSlope15P1F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 7;
                collisionType = TileCollisionType.Slope15P1F90XY;
                break;

            case TileType.TestSlope15P2:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 8;
                collisionType = TileCollisionType.Slope15P2;
                break;
            case TileType.TestSlope15P2FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 8;
                collisionType = TileCollisionType.Slope15P2FX;
                break;
            case TileType.TestSlope15P2FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 8;
                collisionType = TileCollisionType.Slope15P2FY;
                break;
            case TileType.TestSlope15P2FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 8;
                collisionType = TileCollisionType.Slope15P2FXY;
                break;
            case TileType.TestSlope15P2F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 8;
                collisionType = TileCollisionType.Slope15P2F90;
                break;
            case TileType.TestSlope15P2F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 8;
                collisionType = TileCollisionType.Slope15P2F90X;
                break;
            case TileType.TestSlope15P2F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 8;
                collisionType = TileCollisionType.Slope15P2F90Y;
                break;
            case TileType.TestSlope15P2F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 8;
                collisionType = TileCollisionType.Slope15P2F90XY;
                break;

            case TileType.TestSlope15P3:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 9;
                collisionType = TileCollisionType.Slope15P3;
                break;
            case TileType.TestSlope15P3FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 9;
                collisionType = TileCollisionType.Slope15P3FX;
                break;
            case TileType.TestSlope15P3FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 9;
                collisionType = TileCollisionType.Slope15P3FY;
                break;
            case TileType.TestSlope15P3FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 9;
                collisionType = TileCollisionType.Slope15P3FXY;
                break;
            case TileType.TestSlope15P3F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 9;
                collisionType = TileCollisionType.Slope15P3F90;
                break;
            case TileType.TestSlope15P3F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 9;
                collisionType = TileCollisionType.Slope15P3F90X;
                break;
            case TileType.TestSlope15P3F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 9;
                collisionType = TileCollisionType.Slope15P3F90Y;
                break;
            case TileType.TestSlope15P3F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 9;
                collisionType = TileCollisionType.Slope15P3F90XY;
                break;

            case TileType.TestSlopeMid3:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 10;
                collisionType = TileCollisionType.SlopeMid3;
                break;
            case TileType.TestSlopeMid3FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 10;
                collisionType = TileCollisionType.SlopeMid3FX;
                break;
            case TileType.TestSlopeMid3FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 10;
                collisionType = TileCollisionType.SlopeMid3FY;
                break;
            case TileType.TestSlopeMid3FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 10;
                collisionType = TileCollisionType.SlopeMid3FXY;
                break;
            case TileType.TestSlopeMid3F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 10;
                collisionType = TileCollisionType.SlopeMid3F90;
                break;
            case TileType.TestSlopeMid3F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 10;
                collisionType = TileCollisionType.SlopeMid3F90X;
                break;
            case TileType.TestSlopeMid3F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 10;
                collisionType = TileCollisionType.SlopeMid3F90Y;
                break;
            case TileType.TestSlopeMid3F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 10;
                collisionType = TileCollisionType.SlopeMid3F90XY;
                break;

            case TileType.TestSlopeMid3Rev:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 11;
                collisionType = TileCollisionType.SlopeMid3Rev;
                break;
            case TileType.TestSlopeMid3RevFX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 11;
                collisionType = TileCollisionType.SlopeMid3RevFX;
                break;
            case TileType.TestSlopeMid3RevFY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 11;
                collisionType = TileCollisionType.SlopeMid3RevFY;
                break;
            case TileType.TestSlopeMid3RevFXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 11;
                collisionType = TileCollisionType.SlopeMid3RevFXY;
                break;
            case TileType.TestSlopeMid3RevF90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 11;
                collisionType = TileCollisionType.SlopeMid3RevF90;
                break;
            case TileType.TestSlopeMid3RevF90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 11;
                collisionType = TileCollisionType.SlopeMid3RevF90X;
                break;
            case TileType.TestSlopeMid3RevF90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 11;
                collisionType = TileCollisionType.SlopeMid3RevF90Y;
                break;
            case TileType.TestSlopeMid3RevF90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 11;
                collisionType = TileCollisionType.SlopeMid3RevF90XY;
                break;

            case TileType.TestSlope11P1:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 12;
                collisionType = TileCollisionType.Slope11P1;
                break;
            case TileType.TestSlope11P1FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 12;
                collisionType = TileCollisionType.Slope11P1FX;
                break;
            case TileType.TestSlope11P1FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 12;
                collisionType = TileCollisionType.Slope11P1FY;
                break;
            case TileType.TestSlope11P1FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 12;
                collisionType = TileCollisionType.Slope11P1FXY;
                break;
            case TileType.TestSlope11P1F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 12;
                collisionType = TileCollisionType.Slope11P1F90;
                break;
            case TileType.TestSlope11P1F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 12;
                collisionType = TileCollisionType.Slope11P1F90X;
                break;
            case TileType.TestSlope11P1F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 12;
                collisionType = TileCollisionType.Slope11P1F90Y;
                break;
            case TileType.TestSlope11P1F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 12;
                collisionType = TileCollisionType.Slope11P1F90XY;
                break;

            case TileType.TestSlope11P2:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 13;
                collisionType = TileCollisionType.Slope11P2;
                break;
            case TileType.TestSlope11P2FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 13;
                collisionType = TileCollisionType.Slope11P2FX;
                break;
            case TileType.TestSlope11P2FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 13;
                collisionType = TileCollisionType.Slope11P2FY;
                break;
            case TileType.TestSlope11P2FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 13;
                collisionType = TileCollisionType.Slope11P2FXY;
                break;
            case TileType.TestSlope11P2F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 13;
                collisionType = TileCollisionType.Slope11P2F90;
                break;
            case TileType.TestSlope11P2F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 13;
                collisionType = TileCollisionType.Slope11P2F90X;
                break;
            case TileType.TestSlope11P2F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 13;
                collisionType = TileCollisionType.Slope11P2F90Y;
                break;
            case TileType.TestSlope11P2F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 13;
                collisionType = TileCollisionType.Slope11P2F90XY;
                break;

            case TileType.TestSlope11P3:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 14;
                collisionType = TileCollisionType.Slope11P3;
                break;
            case TileType.TestSlope11P3FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 14;
                collisionType = TileCollisionType.Slope11P3FX;
                break;
            case TileType.TestSlope11P3FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 14;
                collisionType = TileCollisionType.Slope11P3FY;
                break;
            case TileType.TestSlope11P3FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 14;
                collisionType = TileCollisionType.Slope11P3FXY;
                break;
            case TileType.TestSlope11P3F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 14;
                collisionType = TileCollisionType.Slope11P3F90;
                break;
            case TileType.TestSlope11P3F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 14;
                collisionType = TileCollisionType.Slope11P3F90X;
                break;
            case TileType.TestSlope11P3F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 14;
                collisionType = TileCollisionType.Slope11P3F90Y;
                break;
            case TileType.TestSlope11P3F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 14;
                collisionType = TileCollisionType.Slope11P3F90XY;
                break;

            case TileType.TestSlope11P4:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 15;
                collisionType = TileCollisionType.Slope11P4;
                break;
            case TileType.TestSlope11P4FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 15;
                collisionType = TileCollisionType.Slope11P4FX;
                break;
            case TileType.TestSlope11P4FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 15;
                collisionType = TileCollisionType.Slope11P4FY;
                break;
            case TileType.TestSlope11P4FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 15;
                collisionType = TileCollisionType.Slope11P4FXY;
                break;
            case TileType.TestSlope11P4F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 15;
                collisionType = TileCollisionType.Slope11P4F90;
                break;
            case TileType.TestSlope11P4F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 15;
                collisionType = TileCollisionType.Slope11P4F90X;
                break;
            case TileType.TestSlope11P4F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 15;
                collisionType = TileCollisionType.Slope11P4F90Y;
                break;
            case TileType.TestSlope11P4F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 15;
                collisionType = TileCollisionType.Slope11P4F90XY;
                break;

            case TileType.TestSlopeMid4:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 16;
                collisionType = TileCollisionType.SlopeMid4;
                break;
            case TileType.TestSlopeMid4FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 16;
                collisionType = TileCollisionType.SlopeMid4FX;
                break;
            case TileType.TestSlopeMid4FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 16;
                collisionType = TileCollisionType.SlopeMid4FY;
                break;
            case TileType.TestSlopeMid4FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 16;
                collisionType = TileCollisionType.SlopeMid4FXY;
                break;
            case TileType.TestSlopeMid4F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 16;
                collisionType = TileCollisionType.SlopeMid4F90;
                break;
            case TileType.TestSlopeMid4F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 16;
                collisionType = TileCollisionType.SlopeMid4F90X;
                break;
            case TileType.TestSlopeMid4F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 16;
                collisionType = TileCollisionType.SlopeMid4F90Y;
                break;
            case TileType.TestSlopeMid4F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 16;
                collisionType = TileCollisionType.SlopeMid4F90XY;
                break;

            case TileType.TestSlopeMid4Rev:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 17;
                collisionType = TileCollisionType.SlopeMid4Rev;
                break;
            case TileType.TestSlopeMid4RevFX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 17;
                collisionType = TileCollisionType.SlopeMid4RevFX;
                break;
            case TileType.TestSlopeMid4RevFY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 17;
                collisionType = TileCollisionType.SlopeMid4RevFY;
                break;
            case TileType.TestSlopeMid4RevFXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 17;
                collisionType = TileCollisionType.SlopeMid4RevFXY;
                break;
            case TileType.TestSlopeMid4RevF90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 17;
                collisionType = TileCollisionType.SlopeMid4RevF90;
                break;
            case TileType.TestSlopeMid4RevF90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 17;
                collisionType = TileCollisionType.SlopeMid4RevF90X;
                break;
            case TileType.TestSlopeMid4RevF90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 17;
                collisionType = TileCollisionType.SlopeMid4RevF90Y;
                break;
            case TileType.TestSlopeMid4RevF90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 17;
                collisionType = TileCollisionType.SlopeMid4RevF90XY;
                break;
            #endregion
            #region testOneWayOneWaySlope

            case TileType.TestOneWaySlope45:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 0;
                collisionType = TileCollisionType.OneWaySlope45;
                break;
            case TileType.TestOneWaySlope45FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 0;
                collisionType = TileCollisionType.OneWaySlope45FX;
                break;
            case TileType.TestOneWaySlope45FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 0;
                collisionType = TileCollisionType.OneWaySlope45FY;
                break;
            case TileType.TestOneWaySlope45FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 0;
                collisionType = TileCollisionType.OneWaySlope45FXY;
                break;
            case TileType.TestOneWaySlope45F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 0;
                collisionType = TileCollisionType.OneWaySlope45F90;
                break;
            case TileType.TestOneWaySlope45F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 0;
                collisionType = TileCollisionType.OneWaySlope45F90X;
                break;
            case TileType.TestOneWaySlope45F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 0;
                collisionType = TileCollisionType.OneWaySlope45F90Y;
                break;
            case TileType.TestOneWaySlope45F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 0;
                collisionType = TileCollisionType.OneWaySlope45F90XY;
                break;

            case TileType.TestOneWaySlopeMid1:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 1;
                collisionType = TileCollisionType.OneWaySlopeMid1;
                break;
            case TileType.TestOneWaySlopeMid1FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 1;
                collisionType = TileCollisionType.OneWaySlopeMid1FX;
                break;
            case TileType.TestOneWaySlopeMid1FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 1;
                collisionType = TileCollisionType.OneWaySlopeMid1FY;
                break;
            case TileType.TestOneWaySlopeMid1FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 1;
                collisionType = TileCollisionType.OneWaySlopeMid1FXY;
                break;
            case TileType.TestOneWaySlopeMid1F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 1;
                collisionType = TileCollisionType.OneWaySlopeMid1F90;
                break;
            case TileType.TestOneWaySlopeMid1F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 1;
                collisionType = TileCollisionType.OneWaySlopeMid1F90X;
                break;
            case TileType.TestOneWaySlopeMid1F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 1;
                collisionType = TileCollisionType.OneWaySlopeMid1F90Y;
                break;
            case TileType.TestOneWaySlopeMid1F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 1;
                collisionType = TileCollisionType.OneWaySlopeMid1F90XY;
                break;

            case TileType.TestOneWaySlopeMid1Rev:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 2;
                collisionType = TileCollisionType.OneWaySlopeMid1Rev;
                break;
            case TileType.TestOneWaySlopeMid1RevFX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 2;
                collisionType = TileCollisionType.OneWaySlopeMid1RevFX;
                break;
            case TileType.TestOneWaySlopeMid1RevFY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 2;
                collisionType = TileCollisionType.OneWaySlopeMid1RevFY;
                break;
            case TileType.TestOneWaySlopeMid1RevFXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 2;
                collisionType = TileCollisionType.OneWaySlopeMid1RevFXY;
                break;
            case TileType.TestOneWaySlopeMid1RevF90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 2;
                collisionType = TileCollisionType.OneWaySlopeMid1RevF90;
                break;
            case TileType.TestOneWaySlopeMid1RevF90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 2;
                collisionType = TileCollisionType.OneWaySlopeMid1RevF90X;
                break;
            case TileType.TestOneWaySlopeMid1RevF90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 2;
                collisionType = TileCollisionType.OneWaySlopeMid1RevF90Y;
                break;
            case TileType.TestOneWaySlopeMid1RevF90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 2;
                collisionType = TileCollisionType.OneWaySlopeMid1RevF90XY;
                break;

            case TileType.TestOneWaySlope22P1:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 3;
                collisionType = TileCollisionType.OneWaySlope22P1;
                break;
            case TileType.TestOneWaySlope22P1FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 3;
                collisionType = TileCollisionType.OneWaySlope22P1FX;
                break;
            case TileType.TestOneWaySlope22P1FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 3;
                collisionType = TileCollisionType.OneWaySlope22P1FY;
                break;
            case TileType.TestOneWaySlope22P1FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 3;
                collisionType = TileCollisionType.OneWaySlope22P1FXY;
                break;
            case TileType.TestOneWaySlope22P1F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 3;
                collisionType = TileCollisionType.OneWaySlope22P1F90;
                break;
            case TileType.TestOneWaySlope22P1F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 3;
                collisionType = TileCollisionType.OneWaySlope22P1F90X;
                break;
            case TileType.TestOneWaySlope22P1F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 3;
                collisionType = TileCollisionType.OneWaySlope22P1F90Y;
                break;
            case TileType.TestOneWaySlope22P1F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 3;
                collisionType = TileCollisionType.OneWaySlope22P1F90XY;
                break;

            case TileType.TestOneWaySlope22P2:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 4;
                collisionType = TileCollisionType.OneWaySlope22P2;
                break;
            case TileType.TestOneWaySlope22P2FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 4;
                collisionType = TileCollisionType.OneWaySlope22P2FX;
                break;
            case TileType.TestOneWaySlope22P2FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 4;
                collisionType = TileCollisionType.OneWaySlope22P2FY;
                break;
            case TileType.TestOneWaySlope22P2FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 4;
                collisionType = TileCollisionType.OneWaySlope22P2FXY;
                break;
            case TileType.TestOneWaySlope22P2F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 4;
                collisionType = TileCollisionType.OneWaySlope22P2F90;
                break;
            case TileType.TestOneWaySlope22P2F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 4;
                collisionType = TileCollisionType.OneWaySlope22P2F90X;
                break;
            case TileType.TestOneWaySlope22P2F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 4;
                collisionType = TileCollisionType.OneWaySlope22P2F90Y;
                break;
            case TileType.TestOneWaySlope22P2F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 4;
                collisionType = TileCollisionType.OneWaySlope22P2F90XY;
                break;

            case TileType.TestOneWaySlopeMid2:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 5;
                collisionType = TileCollisionType.OneWaySlopeMid2;
                break;
            case TileType.TestOneWaySlopeMid2FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 5;
                collisionType = TileCollisionType.OneWaySlopeMid2FX;
                break;
            case TileType.TestOneWaySlopeMid2FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 5;
                collisionType = TileCollisionType.OneWaySlopeMid2FY;
                break;
            case TileType.TestOneWaySlopeMid2FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 5;
                collisionType = TileCollisionType.OneWaySlopeMid2FXY;
                break;
            case TileType.TestOneWaySlopeMid2F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 5;
                collisionType = TileCollisionType.OneWaySlopeMid2F90;
                break;
            case TileType.TestOneWaySlopeMid2F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 5;
                collisionType = TileCollisionType.OneWaySlopeMid2F90X;
                break;
            case TileType.TestOneWaySlopeMid2F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 5;
                collisionType = TileCollisionType.OneWaySlopeMid2F90Y;
                break;
            case TileType.TestOneWaySlopeMid2F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 5;
                collisionType = TileCollisionType.OneWaySlopeMid2F90XY;
                break;

            case TileType.TestOneWaySlopeMid2Rev:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 6;
                collisionType = TileCollisionType.OneWaySlopeMid2Rev;
                break;
            case TileType.TestOneWaySlopeMid2RevFX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 6;
                collisionType = TileCollisionType.OneWaySlopeMid2RevFX;
                break;
            case TileType.TestOneWaySlopeMid2RevFY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 6;
                collisionType = TileCollisionType.OneWaySlopeMid2RevFY;
                break;
            case TileType.TestOneWaySlopeMid2RevFXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 6;
                collisionType = TileCollisionType.OneWaySlopeMid2RevFXY;
                break;
            case TileType.TestOneWaySlopeMid2RevF90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 6;
                collisionType = TileCollisionType.OneWaySlopeMid2RevF90;
                break;
            case TileType.TestOneWaySlopeMid2RevF90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 6;
                collisionType = TileCollisionType.OneWaySlopeMid2RevF90X;
                break;
            case TileType.TestOneWaySlopeMid2RevF90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 6;
                collisionType = TileCollisionType.OneWaySlopeMid2RevF90Y;
                break;
            case TileType.TestOneWaySlopeMid2RevF90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 6;
                collisionType = TileCollisionType.OneWaySlopeMid2RevF90XY;
                break;

            case TileType.TestOneWaySlope15P1:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 7;
                collisionType = TileCollisionType.OneWaySlope15P1;
                break;
            case TileType.TestOneWaySlope15P1FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 7;
                collisionType = TileCollisionType.OneWaySlope15P1FX;
                break;
            case TileType.TestOneWaySlope15P1FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 7;
                collisionType = TileCollisionType.OneWaySlope15P1FY;
                break;
            case TileType.TestOneWaySlope15P1FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 7;
                collisionType = TileCollisionType.OneWaySlope15P1FXY;
                break;
            case TileType.TestOneWaySlope15P1F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 7;
                collisionType = TileCollisionType.OneWaySlope15P1F90;
                break;
            case TileType.TestOneWaySlope15P1F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 7;
                collisionType = TileCollisionType.OneWaySlope15P1F90X;
                break;
            case TileType.TestOneWaySlope15P1F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 7;
                collisionType = TileCollisionType.OneWaySlope15P1F90Y;
                break;
            case TileType.TestOneWaySlope15P1F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 7;
                collisionType = TileCollisionType.OneWaySlope15P1F90XY;
                break;

            case TileType.TestOneWaySlope15P2:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 8;
                collisionType = TileCollisionType.OneWaySlope15P2;
                break;
            case TileType.TestOneWaySlope15P2FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 8;
                collisionType = TileCollisionType.OneWaySlope15P2FX;
                break;
            case TileType.TestOneWaySlope15P2FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 8;
                collisionType = TileCollisionType.OneWaySlope15P2FY;
                break;
            case TileType.TestOneWaySlope15P2FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 8;
                collisionType = TileCollisionType.OneWaySlope15P2FXY;
                break;
            case TileType.TestOneWaySlope15P2F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 8;
                collisionType = TileCollisionType.OneWaySlope15P2F90;
                break;
            case TileType.TestOneWaySlope15P2F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 8;
                collisionType = TileCollisionType.OneWaySlope15P2F90X;
                break;
            case TileType.TestOneWaySlope15P2F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 8;
                collisionType = TileCollisionType.OneWaySlope15P2F90Y;
                break;
            case TileType.TestOneWaySlope15P2F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 8;
                collisionType = TileCollisionType.OneWaySlope15P2F90XY;
                break;

            case TileType.TestOneWaySlope15P3:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 9;
                collisionType = TileCollisionType.OneWaySlope15P3;
                break;
            case TileType.TestOneWaySlope15P3FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 9;
                collisionType = TileCollisionType.OneWaySlope15P3FX;
                break;
            case TileType.TestOneWaySlope15P3FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 9;
                collisionType = TileCollisionType.OneWaySlope15P3FY;
                break;
            case TileType.TestOneWaySlope15P3FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 9;
                collisionType = TileCollisionType.OneWaySlope15P3FXY;
                break;
            case TileType.TestOneWaySlope15P3F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 9;
                collisionType = TileCollisionType.OneWaySlope15P3F90;
                break;
            case TileType.TestOneWaySlope15P3F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 9;
                collisionType = TileCollisionType.OneWaySlope15P3F90X;
                break;
            case TileType.TestOneWaySlope15P3F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 9;
                collisionType = TileCollisionType.OneWaySlope15P3F90Y;
                break;
            case TileType.TestOneWaySlope15P3F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 9;
                collisionType = TileCollisionType.OneWaySlope15P3F90XY;
                break;

            case TileType.TestOneWaySlopeMid3:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 10;
                collisionType = TileCollisionType.OneWaySlopeMid3;
                break;
            case TileType.TestOneWaySlopeMid3FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 10;
                collisionType = TileCollisionType.OneWaySlopeMid3FX;
                break;
            case TileType.TestOneWaySlopeMid3FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 10;
                collisionType = TileCollisionType.OneWaySlopeMid3FY;
                break;
            case TileType.TestOneWaySlopeMid3FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 10;
                collisionType = TileCollisionType.OneWaySlopeMid3FXY;
                break;
            case TileType.TestOneWaySlopeMid3F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 10;
                collisionType = TileCollisionType.OneWaySlopeMid3F90;
                break;
            case TileType.TestOneWaySlopeMid3F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 10;
                collisionType = TileCollisionType.OneWaySlopeMid3F90X;
                break;
            case TileType.TestOneWaySlopeMid3F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 10;
                collisionType = TileCollisionType.OneWaySlopeMid3F90Y;
                break;
            case TileType.TestOneWaySlopeMid3F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 10;
                collisionType = TileCollisionType.OneWaySlopeMid3F90XY;
                break;

            case TileType.TestOneWaySlopeMid3Rev:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 11;
                collisionType = TileCollisionType.OneWaySlopeMid3Rev;
                break;
            case TileType.TestOneWaySlopeMid3RevFX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 11;
                collisionType = TileCollisionType.OneWaySlopeMid3RevFX;
                break;
            case TileType.TestOneWaySlopeMid3RevFY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 11;
                collisionType = TileCollisionType.OneWaySlopeMid3RevFY;
                break;
            case TileType.TestOneWaySlopeMid3RevFXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 11;
                collisionType = TileCollisionType.OneWaySlopeMid3RevFXY;
                break;
            case TileType.TestOneWaySlopeMid3RevF90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 11;
                collisionType = TileCollisionType.OneWaySlopeMid3RevF90;
                break;
            case TileType.TestOneWaySlopeMid3RevF90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 11;
                collisionType = TileCollisionType.OneWaySlopeMid3RevF90X;
                break;
            case TileType.TestOneWaySlopeMid3RevF90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 11;
                collisionType = TileCollisionType.OneWaySlopeMid3RevF90Y;
                break;
            case TileType.TestOneWaySlopeMid3RevF90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 11;
                collisionType = TileCollisionType.OneWaySlopeMid3RevF90XY;
                break;

            case TileType.TestOneWaySlope11P1:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 12;
                collisionType = TileCollisionType.OneWaySlope11P1;
                break;
            case TileType.TestOneWaySlope11P1FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 12;
                collisionType = TileCollisionType.OneWaySlope11P1FX;
                break;
            case TileType.TestOneWaySlope11P1FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 12;
                collisionType = TileCollisionType.OneWaySlope11P1FY;
                break;
            case TileType.TestOneWaySlope11P1FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 12;
                collisionType = TileCollisionType.OneWaySlope11P1FXY;
                break;
            case TileType.TestOneWaySlope11P1F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 12;
                collisionType = TileCollisionType.OneWaySlope11P1F90;
                break;
            case TileType.TestOneWaySlope11P1F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 12;
                collisionType = TileCollisionType.OneWaySlope11P1F90X;
                break;
            case TileType.TestOneWaySlope11P1F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 12;
                collisionType = TileCollisionType.OneWaySlope11P1F90Y;
                break;
            case TileType.TestOneWaySlope11P1F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 12;
                collisionType = TileCollisionType.OneWaySlope11P1F90XY;
                break;

            case TileType.TestOneWaySlope11P2:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 13;
                collisionType = TileCollisionType.OneWaySlope11P2;
                break;
            case TileType.TestOneWaySlope11P2FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 13;
                collisionType = TileCollisionType.OneWaySlope11P2FX;
                break;
            case TileType.TestOneWaySlope11P2FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 13;
                collisionType = TileCollisionType.OneWaySlope11P2FY;
                break;
            case TileType.TestOneWaySlope11P2FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 13;
                collisionType = TileCollisionType.OneWaySlope11P2FXY;
                break;
            case TileType.TestOneWaySlope11P2F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 13;
                collisionType = TileCollisionType.OneWaySlope11P2F90;
                break;
            case TileType.TestOneWaySlope11P2F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 13;
                collisionType = TileCollisionType.OneWaySlope11P2F90X;
                break;
            case TileType.TestOneWaySlope11P2F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 13;
                collisionType = TileCollisionType.OneWaySlope11P2F90Y;
                break;
            case TileType.TestOneWaySlope11P2F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 13;
                collisionType = TileCollisionType.OneWaySlope11P2F90XY;
                break;

            case TileType.TestOneWaySlope11P3:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 14;
                collisionType = TileCollisionType.OneWaySlope11P3;
                break;
            case TileType.TestOneWaySlope11P3FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 14;
                collisionType = TileCollisionType.OneWaySlope11P3FX;
                break;
            case TileType.TestOneWaySlope11P3FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 14;
                collisionType = TileCollisionType.OneWaySlope11P3FY;
                break;
            case TileType.TestOneWaySlope11P3FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 14;
                collisionType = TileCollisionType.OneWaySlope11P3FXY;
                break;
            case TileType.TestOneWaySlope11P3F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 14;
                collisionType = TileCollisionType.OneWaySlope11P3F90;
                break;
            case TileType.TestOneWaySlope11P3F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 14;
                collisionType = TileCollisionType.OneWaySlope11P3F90X;
                break;
            case TileType.TestOneWaySlope11P3F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 14;
                collisionType = TileCollisionType.OneWaySlope11P3F90Y;
                break;
            case TileType.TestOneWaySlope11P3F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 14;
                collisionType = TileCollisionType.OneWaySlope11P3F90XY;
                break;

            case TileType.TestOneWaySlope11P4:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 15;
                collisionType = TileCollisionType.OneWaySlope11P4;
                break;
            case TileType.TestOneWaySlope11P4FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 15;
                collisionType = TileCollisionType.OneWaySlope11P4FX;
                break;
            case TileType.TestOneWaySlope11P4FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 15;
                collisionType = TileCollisionType.OneWaySlope11P4FY;
                break;
            case TileType.TestOneWaySlope11P4FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 15;
                collisionType = TileCollisionType.OneWaySlope11P4FXY;
                break;
            case TileType.TestOneWaySlope11P4F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 15;
                collisionType = TileCollisionType.OneWaySlope11P4F90;
                break;
            case TileType.TestOneWaySlope11P4F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 15;
                collisionType = TileCollisionType.OneWaySlope11P4F90X;
                break;
            case TileType.TestOneWaySlope11P4F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 15;
                collisionType = TileCollisionType.OneWaySlope11P4F90Y;
                break;
            case TileType.TestOneWaySlope11P4F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 15;
                collisionType = TileCollisionType.OneWaySlope11P4F90XY;
                break;

            case TileType.TestOneWaySlopeMid4:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 16;
                collisionType = TileCollisionType.OneWaySlopeMid4;
                break;
            case TileType.TestOneWaySlopeMid4FX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 16;
                collisionType = TileCollisionType.OneWaySlopeMid4FX;
                break;
            case TileType.TestOneWaySlopeMid4FY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 16;
                collisionType = TileCollisionType.OneWaySlopeMid4FY;
                break;
            case TileType.TestOneWaySlopeMid4FXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 16;
                collisionType = TileCollisionType.OneWaySlopeMid4FXY;
                break;
            case TileType.TestOneWaySlopeMid4F90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 16;
                collisionType = TileCollisionType.OneWaySlopeMid4F90;
                break;
            case TileType.TestOneWaySlopeMid4F90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 16;
                collisionType = TileCollisionType.OneWaySlopeMid4F90X;
                break;
            case TileType.TestOneWaySlopeMid4F90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 16;
                collisionType = TileCollisionType.OneWaySlopeMid4F90Y;
                break;
            case TileType.TestOneWaySlopeMid4F90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 16;
                collisionType = TileCollisionType.OneWaySlopeMid4F90XY;
                break;

            case TileType.TestOneWaySlopeMid4Rev:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 17;
                collisionType = TileCollisionType.OneWaySlopeMid4Rev;
                break;
            case TileType.TestOneWaySlopeMid4RevFX:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 17;
                collisionType = TileCollisionType.OneWaySlopeMid4RevFX;
                break;
            case TileType.TestOneWaySlopeMid4RevFY:
                tilesRotation = 0;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 17;
                collisionType = TileCollisionType.OneWaySlopeMid4RevFY;
                break;
            case TileType.TestOneWaySlopeMid4RevFXY:
                tilesRotation = 0;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 17;
                collisionType = TileCollisionType.OneWaySlopeMid4RevFXY;
                break;
            case TileType.TestOneWaySlopeMid4RevF90:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = 1;
                id = 17;
                collisionType = TileCollisionType.OneWaySlopeMid4RevF90;
                break;
            case TileType.TestOneWaySlopeMid4RevF90X:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = 1;
                id = 17;
                collisionType = TileCollisionType.OneWaySlopeMid4RevF90X;
                break;
            case TileType.TestOneWaySlopeMid4RevF90Y:
                tilesRotation = 1;
                tilesScaleX = 1;
                tilesScaleY = -1;
                id = 17;
                collisionType = TileCollisionType.OneWaySlopeMid4RevF90Y;
                break;
            case TileType.TestOneWaySlopeMid4RevF90XY:
                tilesRotation = 1;
                tilesScaleX = -1;
                tilesScaleY = -1;
                id = 17;
                collisionType = TileCollisionType.OneWaySlopeMid4RevF90XY;
                break;
                #endregion
        }

        if (Slopes.IsOneWay(collisionType))
            id += 18;

        spr.enabled = true;

        if (tilesRotation == 0)
        {
            spr.transform.localScale = new Vector3(tilesScaleX * 1.0f, tilesScaleY * 1.0f, 1.0f);
            spr.transform.localEulerAngles = new Vector3(0.0f, 0.0f, 0.0f);
        }
        else
        {
            spr.transform.localScale = new Vector3(-tilesScaleY * 1.0f, -tilesScaleX * 1.0f, 1.0f);
            spr.transform.localEulerAngles = new Vector3(0.0f, 0.0f, 90.0f);
        }

        spr.sprite = mDirtSprites[26 + id];

        return collisionType;
    }

    public void SetTile(int x, int y, TileType type)
    {
        if (x <= 1 || x >= mWidth - 2 || y <= 1 || y >= mHeight - 2)
            return;

        mTiles[x, y] = type;

        var collisionType = TileCollisionType.Empty;

        sbyte tilesRotation = 0;
        sbyte tilesScaleX = 1;
        sbyte tilesScaleY = 1;
        sbyte id = 0;

        if (type == TileType.Block)
        {
            AutoTile(type, x, y, 1, 8, 4, 4, 4, 4);
            mTilesSprites[x, y].enabled = true;
            collisionType = TileCollisionType.Full;
        }
        else if (type == TileType.OneWay)
        {
            mTilesSprites[x, y].enabled = true;
            collisionType = TileCollisionType.OneWayFull;
            mTilesSprites[x, y].transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
            mTilesSprites[x, y].transform.eulerAngles = new Vector3(0.0f, 0.0f, 0.0f);
            mTilesSprites[x, y].sprite = mDirtSprites[25];
        }
        else if (type != TileType.Empty)
        {
            collisionType = SetSprite(mTilesSprites[x, y], type);
        }
        else
        {
            mTilesSprites[x, y].enabled = false;
        }

        mTilesCollision[x,y] = collisionType;

        AutoTile(type, x - 1, y, 1, 8, 4, 4, 4, 4);
        AutoTile(type, x + 1, y, 1, 8, 4, 4, 4, 4);
        AutoTile(type, x, y - 1, 1, 8, 4, 4, 4, 4);
        AutoTile(type, x, y + 1, 1, 8, 4, 4, 4, 4);
    }

    public void Init()
    {
        mRandomNumber = new System.Random();
        //set the position
        mPosition = transform.position;

        mTiles = new TileType[mWidth, mHeight];
        mTilesCollision = new TileCollisionType[mWidth, mHeight];
        mTilesSprites = new SpriteRenderer[mWidth, mHeight];

        mUpdatedAreas = new HashSet<Vector2i>();

        mHorizontalAreasCount = Mathf.CeilToInt((float)mWidth / (float)mGridAreaWidth);
        mVerticalAreasCount = Mathf.CeilToInt((float)mHeight / (float)mGridAreaHeight);

        mObjectsInArea = new List<MovingObject>[mHorizontalAreasCount, mVerticalAreasCount];

        for (var y = 0; y < mVerticalAreasCount; ++y)
        {
            for (var x = 0; x < mHorizontalAreasCount; ++x)
                mObjectsInArea[x, y] = new List<MovingObject>();
        }

        for (int y = 0; y < mHeight; ++y)
        {
            for (int x = 0; x < mWidth; ++x)
            {
                mTilesSprites[x, y] = Instantiate<SpriteRenderer>(mTilePrefab);
                mTilesSprites[x, y].transform.parent = transform;
                mTilesSprites[x, y].transform.position = mPosition + new Vector3(cTileSize * x, cTileSize * y, 10.0f);

                if (y > mHeight / 4)
                    SetTile(x, y, TileType.Empty);
                else if (y == mHeight / 2 + 4)
                    SetTile(x, y, TileType.OneWay);
                else
                    SetTile(x, y, TileType.Block);
            }
        }

        int groundLevel = mHeight / 4 + 1;

        int left = mWidth / 4;

        for (int i = left - 20; i < left - 4; i += 2)
            SetTile( i, groundLevel, TileType.TestSlopeMid1);

        for (int i = left - 19; i < left - 4; i += 2)
            SetTile(i, groundLevel+2, TileType.TestSlopeMid1FY);

        for (int i = left - 19; i < left - 4; i += 1)
            SetTile(i, groundLevel + 3, TileType.Block);

        for (int i = 0; i < 20; ++i)
        {
            SetTile(left + i, groundLevel + i, TileType.TestOneWaySlope45);
            SetTile(left + i, groundLevel + 20, TileType.OneWay);
        }

        SetTile(left + 19, groundLevel + 20, TileType.TestOneWaySlope45FX);

        for (int i = 20; i < mWidth; ++i)
        {
            SetTile(left + i, groundLevel + 19, TileType.OneWay);
        }

        SetTile(left + 10, groundLevel, TileType.TestSlope11P4F90X);
        SetTile(left + 10, groundLevel + 1, TileType.TestSlope11P3F90X);
        SetTile(left + 10, groundLevel + 2, TileType.TestSlope11P2F90X);
        SetTile(left + 10, groundLevel + 3, TileType.TestSlope11P1F90X);

        SetTile(left + 11, groundLevel + 4, TileType.TestSlope15P3F90X);
        SetTile(left + 11, groundLevel + 5, TileType.TestSlope15P2F90X);
        SetTile(left + 11, groundLevel + 6, TileType.TestSlope15P1F90X);

        SetTile(left + 12, groundLevel + 7, TileType.TestSlope22P2F90X);
        SetTile(left + 12, groundLevel + 8, TileType.TestSlope22P1F90X);

        SetTile(left + 13, groundLevel + 9, TileType.TestSlope45);

        SetTile(left + 14, groundLevel + 10, TileType.TestSlope22P1);
        SetTile(left + 15, groundLevel + 10, TileType.TestSlope22P2);

        SetTile(left + 16, groundLevel + 11, TileType.TestSlope15P1);
        SetTile(left + 17, groundLevel + 11, TileType.TestSlope15P2);
        SetTile(left + 18, groundLevel + 11, TileType.TestSlope15P3);

        SetTile(left + 19, groundLevel + 12, TileType.TestSlope11P1);
        SetTile(left + 20, groundLevel + 12, TileType.TestSlope11P2);
        SetTile(left + 21, groundLevel + 12, TileType.TestSlope11P3);
        SetTile(left + 22, groundLevel + 12, TileType.TestSlope11P4);

        SetTile(left + 23, groundLevel + 12, TileType.Block);

        SetTile(left + 24, groundLevel + 12, TileType.TestSlope11P4FX);
        SetTile(left + 25, groundLevel + 12, TileType.TestSlope11P3FX);
        SetTile(left + 26, groundLevel + 12, TileType.TestSlope11P2FX);
        SetTile(left + 27, groundLevel + 12, TileType.TestSlope11P1FX);

        SetTile(left + 28, groundLevel + 11, TileType.TestSlope15P3FX);
        SetTile(left + 29, groundLevel + 11, TileType.TestSlope15P2FX);
        SetTile(left + 30, groundLevel + 11, TileType.TestSlope15P1FX);

        SetTile(left + 31, groundLevel + 10, TileType.TestSlope22P2FX);
        SetTile(left + 32, groundLevel + 10, TileType.TestSlope22P1FX);

        SetTile(left + 33, groundLevel + 9, TileType.TestSlope45FX);

        SetTile(left + 34, groundLevel + 7, TileType.TestSlope22P2F90);
        SetTile(left + 34, groundLevel + 8, TileType.TestSlope22P1F90);

        SetTile(left + 35, groundLevel + 4, TileType.TestSlope15P3F90);
        SetTile(left + 35, groundLevel + 5, TileType.TestSlope15P2F90);
        SetTile(left + 35, groundLevel + 6, TileType.TestSlope15P1F90);

        SetTile(left + 36, groundLevel, TileType.TestSlope11P4F90);
        SetTile(left + 36, groundLevel + 1, TileType.TestSlope11P3F90);
        SetTile(left + 36, groundLevel + 2, TileType.TestSlope11P2F90);
        SetTile(left + 36, groundLevel + 3, TileType.TestSlope11P1F90);
        
        for (int x = left + 11; x <= left + 35; ++x)
            SetTile(x, groundLevel, TileType.Block);
        for (int x = left + 11; x <= left + 35; ++x)
            SetTile(x, groundLevel + 1, TileType.Block);
        for (int x = left + 11; x <= left + 35; ++x)
            SetTile(x, groundLevel + 2, TileType.Block);
        for (int x = left + 11; x <= left + 35; ++x)
            SetTile(x, groundLevel + 3, TileType.Block);

        for (int x = left + 12; x <= left + 34; ++x)
            SetTile(x, groundLevel + 4, TileType.Block);
        for (int x = left + 12; x <= left + 34; ++x)
            SetTile(x, groundLevel + 5, TileType.Block);
        for (int x = left + 12; x <= left + 34; ++x)
            SetTile(x, groundLevel + 6, TileType.Block);

        for (int x = left + 13; x <= left + 33; ++x)
            SetTile(x, groundLevel + 7, TileType.Block);
        for (int x = left + 13; x <= left + 33; ++x)
            SetTile(x, groundLevel + 8, TileType.Block);

        for (int x = left + 14; x <= left + 32; ++x)
            SetTile(x, groundLevel + 9, TileType.Block);

        for (int x = left + 16; x <= left + 30; ++x)
            SetTile(x, groundLevel + 10, TileType.Block);

        for (int x = left + 19; x <= left + 27; ++x)
            SetTile(x, groundLevel + 11, TileType.Block);
            

        for (int y = 0; y < mHeight; ++y)
        {
            mTiles[1, y] = TileType.Block;
            mTiles[mWidth - 2, y] = TileType.Block;
        }

        for (int x = 0; x < mWidth; ++x)
        {
            mTiles[x, 1] = TileType.Block;
            mTiles[x, mHeight - 2] = TileType.Block;
        }

        SetTile(8, groundLevel + 5, TileType.Block);
        SetTile(7, groundLevel + 5, TileType.Block);
        SetTile(7, groundLevel + 6, TileType.Block);

        SetTile(20, groundLevel + 5, TileType.Block);
        SetTile(21, groundLevel + 5, TileType.Block);
        SetTile(21, groundLevel + 6, TileType.Block);

        SetTile(20, groundLevel + 16, TileType.Block);
        SetTile(21, groundLevel + 16, TileType.Block);
        SetTile(21, groundLevel + 15, TileType.Block);

        SetTile(8, groundLevel + 16, TileType.Block);
        SetTile(7, groundLevel + 16, TileType.Block);
        SetTile(7, groundLevel + 15, TileType.Block);
    }

    System.Random mRandomNumber;

    void AutoTile(TileType type, int x, int y, int rand4NeighbourTiles, int rand3NeighbourTiles,
        int rand2NeighbourPipeTiles, int rand2NeighbourCornerTiles, int rand1NeighbourTiles, int rand0NeighbourTiles)
    {
        if (x >= mWidth || x < 0 || y >= mHeight || y < 0)
            return;

        if (mTiles[x, y] != TileType.Block)
            return;

        int tileOnLeft = mTiles[x - 1, y] == mTiles[x, y] ? 1 : 0;
        int tileOnRight = mTiles[x + 1, y] == mTiles[x, y] ? 1 : 0;
        int tileOnTop = mTiles[x, y + 1] == mTiles[x, y] ? 1 : 0;
        int tileOnBottom = mTiles[x, y - 1] == mTiles[x, y] ? 1 : 0;

        float scaleX = 1.0f;
        float scaleY = 1.0f;
        float rot = 0.0f;
        int id = 0;

        int sum = tileOnLeft + tileOnRight + tileOnTop + tileOnBottom;

        switch (sum)
        {
            case 0:
                id = 1 + mRandomNumber.Next(rand0NeighbourTiles);

                break;
            case 1:
                id = 1 + rand0NeighbourTiles + mRandomNumber.Next(rand1NeighbourTiles);

                if (tileOnRight == 1)
                    scaleX = -1;
                else if (tileOnTop == 1)
                    rot = -1;
                else if (tileOnBottom == 1)
                {
                    rot = 1;
                    scaleY = -1;
                }

                break;
            case 2:

                if (tileOnLeft + tileOnBottom == 2)
                {
                    id = 1 + rand0NeighbourTiles + rand1NeighbourTiles + rand2NeighbourPipeTiles
                        + mRandomNumber.Next(rand2NeighbourCornerTiles);
                }
                else if (tileOnRight + tileOnBottom == 2)
                {
                    id = 1 + rand0NeighbourTiles + rand1NeighbourTiles + rand2NeighbourPipeTiles
                        + mRandomNumber.Next(rand2NeighbourCornerTiles);
                    scaleX = -1;
                }
                else if (tileOnTop + tileOnLeft == 2)
                {
                    id = 1 + rand0NeighbourTiles + rand1NeighbourTiles + rand2NeighbourPipeTiles
                        + mRandomNumber.Next(rand2NeighbourCornerTiles);
                    scaleY = -1;
                }
                else if (tileOnTop + tileOnRight == 2)
                {
                    id = 1 + rand0NeighbourTiles + rand1NeighbourTiles + rand2NeighbourPipeTiles
                        + mRandomNumber.Next(rand2NeighbourCornerTiles);
                    scaleX = -1;
                    scaleY = -1;
                }
                else if (tileOnTop + tileOnBottom == 2)
                {
                    id = 1 + rand0NeighbourTiles + rand1NeighbourTiles + mRandomNumber.Next(rand2NeighbourPipeTiles);
                    rot = 1;
                }
                else if (tileOnRight + tileOnLeft == 2)
                    id = 1 + rand0NeighbourTiles + rand1NeighbourTiles + mRandomNumber.Next(rand2NeighbourPipeTiles);

                break;
            case 3:
                id = 1 + rand0NeighbourTiles + rand1NeighbourTiles + rand2NeighbourPipeTiles
                    + rand2NeighbourCornerTiles + mRandomNumber.Next(rand3NeighbourTiles);

                if (tileOnLeft == 0)
                {
                    rot = 1;
                    scaleX = -1;
                }
                else if (tileOnRight == 0)
                {
                    rot = 1;
                    scaleY = -1;
                }
                else if (tileOnBottom == 0)
                    scaleY = -1;

                break;

            case 4:
                id = 1 + rand0NeighbourTiles + rand1NeighbourTiles + rand2NeighbourPipeTiles
                    + rand2NeighbourCornerTiles + rand3NeighbourTiles + mRandomNumber.Next(rand4NeighbourTiles);

                break;


        }

        mTilesSprites[x, y].transform.localScale = new Vector3(scaleX, scaleY, 1.0f);
        mTilesSprites[x, y].transform.localEulerAngles = new Vector3(0.0f, 0.0f, rot * 90.0f);

        mTilesSprites[x, y].sprite = mDirtSprites[id - 1];
    }

    bool SweepTest(MovingObject obj1, MovingObject obj2, out float u0, out float u1)
    {
        AABB a = obj1.mAABB;
        AABB b = obj2.mAABB;

        Vector2 va = obj1.mSpeed * Time.deltaTime;
        Vector2 vb = obj2.mSpeed * Time.deltaTime;

        Vector2 v = vb - va;

        Vector2 u_0 = Vector2.zero;
        Vector2 u_1 = Vector2.one;

        if (a.Overlaps(b))
        {
            u0 = u1 = 0.0f;
            return true;
        }
        else if (v.x == 0.0f && v.y == 0.0f)
        {
            u0 = u1 = 0.0f;
            return false;
        }

        Vector2 maxA = a.Max();
        Vector2 minA = a.Min();
        Vector2 maxB = b.Max();
        Vector2 minB = b.Min();

        if (maxA.x < minB.x && v.x < 0.0f)
            u_0.x = (maxA.x - minB.x) / v.x;
        else if (maxB.x < minA.x && v.x > 0.0f)
            u_0.x = (minA.x - minB.x) / v.x;

        if (maxA.y < minB.y && v.y < 0.0f)
            u_0.y = (maxA.y - minB.y) / v.y;
        else if (maxB.y < minA.y && v.y > 0.0f)
            u_0.y = (minA.y - minB.y) / v.y;

        if (maxB.x > minA.x && v.x < 0.0f)
            u_1.x = (minA.x - maxB.x) / v.x;
        else if (maxA.x > minB.x && v.x > 0.0f)
            u_1.x = (maxA.x - minB.x) / v.x;

        if (maxB.y > minA.y && v.y < 0.0f)
            u_1.y = (minA.y - maxB.y) / v.y;
        else if (maxA.y > minB.y && v.y > 0.0f)
            u_1.y = (maxA.y - minB.y) / v.y;

        u0 = Mathf.Max(u_0.x, u_0.y);
        u1 = Mathf.Min(u_1.x, u_1.y);

        return u0 <= u1;
    }

    public void CheckCollisions()
    {
        float overlapWidth, overlapHeight;

        for (int y = 0; y < mVerticalAreasCount; ++y)
        {
            for (int x = 0; x < mHorizontalAreasCount; ++x)
            {
                var objectsInArea = mObjectsInArea[x, y];
                for (int i = 0; i < objectsInArea.Count - 1; ++i)
                {
                    var obj1 = objectsInArea[i];
                    for (int j = i + 1; j < objectsInArea.Count; ++j)
                    {
                        var obj2 = objectsInArea[j];

                        if (obj1.mAABB.OverlapsSigned(obj2.mAABB, out overlapWidth, out overlapHeight) && !obj1.HasCollisionDataFor(obj2))
                        {
                            obj1.mAllCollidingObjects.Add(new CollisionData(obj2, new Vector2(overlapWidth, overlapHeight), obj1.mSpeed, obj2.mSpeed, obj1.mOldPosition, obj2.mOldPosition, obj1.mPosition, obj2.mPosition));
                            obj2.mAllCollidingObjects.Add(new CollisionData(obj1, -new Vector2(overlapWidth, overlapHeight), obj2.mSpeed, obj1.mSpeed, obj2.mOldPosition, obj1.mOldPosition, obj2.mPosition, obj1.mPosition));
                        }
                    }
                }
            }
        }
    }

    public void UpdateCollisionState(MovingObject obj)
    {
        if (obj.mSpeed.x > 0.0f)
        {
            obj.mSpeed.x = 0.0f;
            obj.mPS.pushesRight = true;
        }
        else if (obj.mSpeed.x < 0.0f)
        {
            obj.mSpeed.x = 0.0f;
            obj.mPS.pushesLeft = true;
        }

        if (obj.mSpeed.y > 0.0f)
        {
            obj.mSpeed.y = 0.0f;
            obj.mPS.pushesTop = true;
        }
        else if (obj.mSpeed.y < 0.0f)
        {
            obj.mSpeed.y = 0.0f;
            obj.mPS.pushesBottom = true;
        }
    }
}
