/// <summary>
        /// X 方向の移動、地形判定
        /// </summary>
        /// <param name="Map">地形判定を行う場合の対象となるマップ</param>
        private void MoveX()
        {
            // 移動量を反映
            Position.X += MoveDistance.X;
            // 現在のセクション
            Map.Section CurrentlySection = Map.Sections[Map.CurrentlySectionID];
            // ワールドに対する絶対座標での当たり判定
            Rectangle AbsoluteHitbox;

            // 地形判定を行う場合
            if (!IsNoclip)
            {
                // 右側地形判定
                if (MoveDistance.X > 0)
                {
                    // 当たり判定をスライスする個数 (マップチップ1枚のサイズごとにスライス)
                    AbsoluteHitbox = GetAbsoluteHitbox();
                    int SplitNumber = (int)Math.Ceiling((float)AbsoluteHitbox.Height / Const.MapchipTileSize) + 1;
                    for (int i = 0; i < SplitNumber; i++)
                    {
                        Point HitCheckPosition;
                        if (i == SplitNumber - 1)
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.Right - 1, AbsoluteHitbox.Bottom - 1);
                        }
                        else
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.Right - 1, AbsoluteHitbox.Y + Const.MapchipTileSize * i);
                        }
                        // 判定実行
                        if (Map.PositionToTerrainType(HitCheckPosition) == Map.TerrainTypes.Wall)
                        {
                            // 接触していた地形にギリギリ接触しない位置に押し戻す
                            int FitX         = (HitCheckPosition.X / Const.MapchipTileSize * Const.MapchipTileSize) - 1;
                            int NewPositionX = FitX - (RelativeHitbox.Width - 1 + RelativeHitbox.X);
                            Position.X     = NewPositionX;
                            MoveDistance.X = 0;
                        }
                    }
                    // 重力に従うエンティティが接地中に移動した場合、足元のスロープに移動後の高さを合わせる
                    if (!IsInAir && !IsIgnoreGravity)
                    {
                        // 当たり判定を更新
                        AbsoluteHitbox = GetAbsoluteHitbox();

                        Point            HitCheckPosition = new Point(AbsoluteHitbox.Left, AbsoluteHitbox.Bottom + 2);
                        Map.TerrainTypes Index            = Map.PositionToTerrainType(HitCheckPosition);
                        if (Map.IsSlope(Index, "right"))
                        {
                            Point HitCheckPositionInTile = new Point(HitCheckPosition.X - HitCheckPosition.X / Const.MapchipTileSize * Const.MapchipTileSize, HitCheckPosition.Y - HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize);
                            int   FloorY = Map.GetSlopeFloorY(Index, HitCheckPositionInTile.X);
                            if (HitCheckPositionInTile.Y >= FloorY)
                            {
                                int FitY         = (HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize) + FloorY - 1;
                                int NewPositionY = FitY - (RelativeHitbox.Height - 1 + RelativeHitbox.Y);
                                Position.Y     = NewPositionY;
                                MoveDistance.Y = 0;
                                IsInAir        = false;
                            }
                        }
                        // スロープから降りる時
                        else if (Index == Map.TerrainTypes.Wall)
                        {
                            int FitY         = (HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize) - 1;
                            int NewPositionY = FitY - (RelativeHitbox.Height - 1 + RelativeHitbox.Y);
                            Position.Y     = NewPositionY;
                            MoveDistance.Y = 0;
                            IsInAir        = false;
                        }
                    }
                }
                // 左側地形判定
                else if (MoveDistance.X < 0)
                {
                    // 当たり判定をスライスする個数 (マップチップ1枚のサイズごとにスライス)
                    AbsoluteHitbox = GetAbsoluteHitbox();
                    int SplitNumber = (int)Math.Ceiling((float)AbsoluteHitbox.Height / Const.MapchipTileSize) + 1;
                    for (int i = 0; i < SplitNumber; i++)
                    {
                        Point HitCheckPosition;
                        if (i == SplitNumber - 1)
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.X, AbsoluteHitbox.Bottom - 1);
                        }
                        else
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.X, AbsoluteHitbox.Y + Const.MapchipTileSize * i);
                        }
                        // 判定実行
                        if (Map.PositionToTerrainType(HitCheckPosition) == Map.TerrainTypes.Wall)
                        {
                            // 接触していた地形にギリギリ接触しない位置に押し戻す
                            int FitX         = (AbsoluteHitbox.X) / Const.MapchipTileSize * Const.MapchipTileSize + (Const.MapchipTileSize);
                            int NewPositionX = FitX - RelativeHitbox.X;
                            Position.X     = NewPositionX;
                            MoveDistance.X = 0;
                        }
                    }
                    // 重力に従うエンティティが接地中に移動した場合、足元のスロープに移動後の高さを合わせる
                    if (!IsInAir && !IsIgnoreGravity)
                    {
                        // 当たり判定を更新
                        AbsoluteHitbox = GetAbsoluteHitbox();

                        Point            HitCheckPosition = new Point(AbsoluteHitbox.Right - 1, AbsoluteHitbox.Bottom + 2);
                        Map.TerrainTypes Index            = Map.PositionToTerrainType(HitCheckPosition);
                        if (Map.IsSlope(Index, "left"))
                        {
                            Point HitCheckPositionInTile = new Point(HitCheckPosition.X - HitCheckPosition.X / Const.MapchipTileSize * Const.MapchipTileSize, HitCheckPosition.Y - HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize);
                            int   FloorY = Map.GetSlopeFloorY(Index, HitCheckPositionInTile.X);
                            if (HitCheckPositionInTile.Y >= FloorY)
                            {
                                int FitY         = (HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize) + FloorY - 1;
                                int NewPositionY = FitY - (RelativeHitbox.Height - 1 + RelativeHitbox.Y);
                                Position.Y     = NewPositionY;
                                MoveDistance.Y = 0;
                                IsInAir        = false;
                            }
                        }
                        // スロープから降りる時
                        else if (Index == Map.TerrainTypes.Wall)
                        {
                            int FitY         = (HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize) - 1;
                            int NewPositionY = FitY - (RelativeHitbox.Height - 1 + RelativeHitbox.Y);
                            Position.Y     = NewPositionY;
                            MoveDistance.Y = 0;
                            IsInAir        = false;
                        }
                    }
                }
                // 現在のセクションからはみ出た場合にその方向が壁属性であれば押し戻す
                AbsoluteHitbox = GetAbsoluteHitbox();
                if (CurrentlySection.RightIsWall && AbsoluteHitbox.Right > Const.MapchipTileSize * CurrentlySection.Area.X + Const.MapchipTileSize * CurrentlySection.Area.Width)
                {
                    int FitX         = Const.MapchipTileSize * CurrentlySection.Area.X + Const.MapchipTileSize * CurrentlySection.Area.Width - 1;
                    int NewPositionX = FitX - (RelativeHitbox.Width - 1 + RelativeHitbox.X);
                    Position.X     = NewPositionX;
                    MoveDistance.X = 0;
                }
                else if (CurrentlySection.LeftIsWall && AbsoluteHitbox.X < Const.MapchipTileSize * CurrentlySection.Area.X)
                {
                    int FitX         = Const.MapchipTileSize * CurrentlySection.Area.X;
                    int NewPositionX = FitX - RelativeHitbox.X;
                    Position.X     = NewPositionX;
                    MoveDistance.X = 0;
                }
            }
        }
        /// <summary>
        /// Y 方向の移動、地形判定
        /// </summary>
        /// <param name="Map">地形判定を行う場合の対象となるマップ</param>
        private void MoveY()
        {
            // 移動量を反映
            Position.Y += MoveDistance.Y;
            // 現在のセクション
            Map.Section CurrentlySection = Map.Sections[Map.CurrentlySectionID];
            // ワールドに対する絶対座標での当たり判定
            Rectangle AbsoluteHitbox;
            // 1フレーム前の AbsoluteHitbox
            Rectangle OldAbsoluteHitbox;

            // 地形判定を行う場合
            if (!IsNoclip)
            {
                // 下側地形判定
                if (MoveDistance.Y > 0)
                {
                    // 当たり判定をスライスする個数 (マップチップ1枚のサイズごとにスライス)
                    AbsoluteHitbox    = GetAbsoluteHitbox();
                    OldAbsoluteHitbox = GetOldAbsoluteHitbox();
                    int SplitNumber = (int)Math.Ceiling((float)AbsoluteHitbox.Width / Const.MapchipTileSize) + 1;
                    for (int i = 0; i < SplitNumber; i++)
                    {
                        Point HitCheckPosition;
                        if (i == SplitNumber - 1)
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.Right - 1, AbsoluteHitbox.Bottom - 1);
                        }
                        else
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.X + Const.MapchipTileSize * i, AbsoluteHitbox.Bottom - 1);
                        }
                        // 地形判定実行, 梯子の上辺だった場合も着地したことにする
                        Map.TerrainTypes Index = Map.PositionToTerrainType(HitCheckPosition);
                        if (Index == Map.TerrainTypes.Wall ||
                            Index == Map.TerrainTypes.OneWay && OldAbsoluteHitbox.Bottom - 1 < HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize ||
                            Map.CheckPositionLadderTop(HitCheckPosition) && OldAbsoluteHitbox.Bottom - 1 < HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize)
                        {
                            // 接触した地形にギリギリ接触しない位置に移動する
                            int FitY         = (HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize) - 1;
                            int NewPositionY = FitY - (RelativeHitbox.Height - 1 + RelativeHitbox.Y);
                            Position.Y     = NewPositionY;
                            MoveDistance.Y = 0;
                            IsInAir        = false;
                        }
                        // Platform エンティティとの当たり判定
                        else if (RidingEntity == null)
                        {
                            // Platform が Platform に乗ることはない
                            if (Type != Types.Platform)
                            {
                                foreach (Entity Entity in Main.Entities)
                                {
                                    // エンティティの属性が Platform の場合
                                    if (Entity.Type == Types.Platform && Entity.GetAbsoluteHitbox().Contains(HitCheckPosition) && Entity != this &&
                                        OldAbsoluteHitbox.Bottom - 1 <= Entity.GetAbsoluteHitbox().Top)
                                    {
                                        // 接触したエンティティにギリギリ接触しない位置に移動する
                                        int FitY         = Entity.GetAbsoluteHitbox().Top - 1;
                                        int NewPositionY = FitY - (RelativeHitbox.Height - 1 + RelativeHitbox.Y);
                                        Position.Y     = NewPositionY;
                                        MoveDistance.Y = 0;
                                        IsInAir        = false;
                                        RidingEntity   = Entity;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                // 上側地形判定
                else if (MoveDistance.Y < 0)
                {
                    // 当たり判定をスライスする個数 (マップチップ1枚のサイズごとにスライス)
                    AbsoluteHitbox = GetAbsoluteHitbox();
                    int SplitNumber = (int)Math.Ceiling((float)AbsoluteHitbox.Width / Const.MapchipTileSize) + 1;
                    for (int i = 0; i < SplitNumber; i++)
                    {
                        Point HitCheckPosition;
                        if (i == SplitNumber - 1)
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.Right - 1, AbsoluteHitbox.Y);
                        }
                        else
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.X + Const.MapchipTileSize * i, AbsoluteHitbox.Y);
                        }
                        // 判定実行
                        Map.TerrainTypes Index = Map.PositionToTerrainType(HitCheckPosition);
                        if (Index == Map.TerrainTypes.Wall ||
                            Map.IsSlope(Index))
                        {
                            // 接触した地形にギリギリ接触しない位置に移動する
                            int FitY         = HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize + (Const.MapchipTileSize);
                            int NewPositionY = FitY - RelativeHitbox.Y;
                            Position.Y     = NewPositionY;
                            MoveDistance.Y = 0;
                        }
                    }
                }
                // 現在のセクションからはみ出た場合にその方向が壁属性であれば押し戻す
                AbsoluteHitbox = GetAbsoluteHitbox();
                if (CurrentlySection.BottomIsWall && AbsoluteHitbox.Bottom > Const.MapchipTileSize * CurrentlySection.Area.Y + Const.MapchipTileSize * CurrentlySection.Area.Height)
                {
                    int FitY         = Const.MapchipTileSize * CurrentlySection.Area.Y + Const.MapchipTileSize * CurrentlySection.Area.Height - 1;
                    int NewPositionY = FitY - (RelativeHitbox.Height - 1 + RelativeHitbox.Y);
                    Position.Y     = NewPositionY;
                    MoveDistance.Y = 0;
                    IsInAir        = false;
                }
                else if (CurrentlySection.TopIsWall && AbsoluteHitbox.Y < Const.MapchipTileSize * CurrentlySection.Area.Y)
                {
                    int FitY         = Const.MapchipTileSize * CurrentlySection.Area.Y;
                    int NewPositionY = FitY - RelativeHitbox.Y;
                    Position.Y     = NewPositionY;
                    MoveDistance.Y = 0;
                }
                // スロープにめり込んでいた場合押し出す
                {
                    AbsoluteHitbox = GetAbsoluteHitbox();
                    int SplitNumber = (int)Math.Ceiling((float)AbsoluteHitbox.Width / Const.MapchipTileSize) + 1;
                    for (int i = 0; i < SplitNumber; i++)
                    {
                        Point HitCheckPosition;
                        if (i == SplitNumber - 1)
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.Right - 1, AbsoluteHitbox.Bottom - 1);
                        }
                        else
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.X + Const.MapchipTileSize * i, AbsoluteHitbox.Bottom - 1);
                        }
                        Map.TerrainTypes Index = Map.PositionToTerrainType(HitCheckPosition);
                        if (Map.IsSlope(Index))
                        {
                            Point HitCheckPositionInTile = new Point(HitCheckPosition.X - HitCheckPosition.X / Const.MapchipTileSize * Const.MapchipTileSize, HitCheckPosition.Y - HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize);
                            int   FloorY = Map.GetSlopeFloorY(Index, HitCheckPositionInTile.X);
                            if (HitCheckPositionInTile.Y >= FloorY)
                            {
                                int FitY         = (HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize) + FloorY - 1;
                                int NewPositionY = FitY - (RelativeHitbox.Height - 1 + RelativeHitbox.Y);
                                Position.Y     = NewPositionY;
                                MoveDistance.Y = 0;
                                IsInAir        = false;
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 指定した方向が地形に接触しているかどうかを取得する。Platform エンティティは対象にならない。
        /// </summary>
        /// <param name="Direction">取得したい方向を "Top", "Bottom", "Left", "Bottom" のいずれかで指定する</param>
        public bool IsTouchTerrain(string Direction)
        {
            bool Result = false;

            if (Direction == "Top")
            {
                Map.Section CurrentlySection = Map.Sections[Map.CurrentlySectionID];
                Rectangle   AbsoluteHitbox   = GetAbsoluteHitbox();
                // セクションの端も壁属性であった場合は地形と見なす
                if (CurrentlySection.TopIsWall && AbsoluteHitbox.Y - 1 < Const.MapchipTileSize * CurrentlySection.Area.Y)
                {
                    Result = true;
                }
                else
                {
                    // 当たり判定をスライスする個数 (マップチップ1枚のサイズごとにスライス)
                    int SplitNumber = (int)Math.Ceiling((float)AbsoluteHitbox.Width / Const.MapchipTileSize) + 1;
                    for (int i = 0; i < SplitNumber; i++)
                    {
                        Point HitCheckPosition;
                        if (i == SplitNumber - 1)
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.Right - 1, AbsoluteHitbox.Y - 1);
                        }
                        else
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.X + Const.MapchipTileSize * i, AbsoluteHitbox.Y - 1);
                        }
                        // 判定実行
                        Map.TerrainTypes Index = Map.PositionToTerrainType(HitCheckPosition);
                        if (Index == Map.TerrainTypes.Wall || Map.IsSlope(Index))
                        {
                            Result = true;
                        }
                    }
                }
            }
            else if (Direction == "Bottom")
            {
                if (!IsInAir)
                {
                    Result = true;
                }
                else
                {
                    Map.Section CurrentlySection = Map.Sections[Map.CurrentlySectionID];
                    Rectangle   AbsoluteHitbox   = GetAbsoluteHitbox();
                    // セクションの端も壁属性であった場合は地形と見なす
                    if (CurrentlySection.BottomIsWall && AbsoluteHitbox.Bottom + 1 > Const.MapchipTileSize * CurrentlySection.Area.Y + Const.MapchipTileSize * CurrentlySection.Area.Height)
                    {
                        Result = true;
                    }
                    else
                    {
                        // 当たり判定をスライスする個数 (マップチップ1枚のサイズごとにスライス)
                        int SplitNumber = (int)Math.Ceiling((float)AbsoluteHitbox.Width / Const.MapchipTileSize) + 1;
                        for (int i = 0; i < SplitNumber; i++)
                        {
                            Point HitCheckPosition;
                            if (i == SplitNumber - 1)
                            {
                                HitCheckPosition = new Point(AbsoluteHitbox.Right - 1, AbsoluteHitbox.Bottom);
                            }
                            else
                            {
                                HitCheckPosition = new Point(AbsoluteHitbox.X + Const.MapchipTileSize * i, AbsoluteHitbox.Bottom);
                            }
                            // 判定実行
                            Map.TerrainTypes Index = Map.PositionToTerrainType(HitCheckPosition);
                            if (Index == Map.TerrainTypes.Wall)
                            {
                                Result = true;
                            }
                            else if (Map.IsSlope(Index))
                            {
                                Point HitCheckPositionInTile = new Point(HitCheckPosition.X - HitCheckPosition.X / Const.MapchipTileSize * Const.MapchipTileSize, HitCheckPosition.Y - HitCheckPosition.Y / Const.MapchipTileSize * Const.MapchipTileSize);
                                int   FloorY = Map.GetSlopeFloorY(Index, HitCheckPositionInTile.X);
                                if (HitCheckPositionInTile.Y >= FloorY)
                                {
                                    Result = true;
                                }
                            }
                        }
                    }
                }
            }
            else if (Direction == "Left")
            {
                Map.Section CurrentlySection = Map.Sections[Map.CurrentlySectionID];
                Rectangle   AbsoluteHitbox   = GetAbsoluteHitbox();
                // セクションの端も壁属性であった場合は地形と見なす
                if (CurrentlySection.LeftIsWall && AbsoluteHitbox.X - 1 < Const.MapchipTileSize * CurrentlySection.Area.X)
                {
                    Result = true;
                }
                else
                {
                    // 当たり判定をスライスする個数 (マップチップ1枚のサイズごとにスライス)
                    int SplitNumber = (int)Math.Ceiling((float)AbsoluteHitbox.Height / Const.MapchipTileSize) + 1;
                    for (int i = 0; i < SplitNumber; i++)
                    {
                        Point HitCheckPosition;
                        if (i == SplitNumber - 1)
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.X - 1, AbsoluteHitbox.Bottom - 1);
                        }
                        else
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.X - 1, AbsoluteHitbox.Y + Const.MapchipTileSize * i);
                        }
                        // 判定実行
                        if (Map.PositionToTerrainType(HitCheckPosition) == Map.TerrainTypes.Wall)
                        {
                            Result = true;
                        }
                    }
                }
            }
            else if (Direction == "Right")
            {
                Map.Section CurrentlySection = Map.Sections[Map.CurrentlySectionID];
                Rectangle   AbsoluteHitbox   = GetAbsoluteHitbox();
                // セクションの端も壁属性であった場合は地形と見なす
                if (CurrentlySection.RightIsWall && AbsoluteHitbox.Right + 1 > Const.MapchipTileSize * CurrentlySection.Area.X + Const.MapchipTileSize * CurrentlySection.Area.Width)
                {
                    Result = true;
                }
                else
                {
                    // 当たり判定をスライスする個数 (マップチップ1枚のサイズごとにスライス)
                    int SplitNumber = (int)Math.Ceiling((float)AbsoluteHitbox.Height / Const.MapchipTileSize) + 1;
                    for (int i = 0; i < SplitNumber; i++)
                    {
                        Point HitCheckPosition;
                        if (i == SplitNumber - 1)
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.Right, AbsoluteHitbox.Bottom - 1);
                        }
                        else
                        {
                            HitCheckPosition = new Point(AbsoluteHitbox.Right, AbsoluteHitbox.Y + Const.MapchipTileSize * i);
                        }
                        // 判定実行
                        if (Map.PositionToTerrainType(HitCheckPosition) == Map.TerrainTypes.Wall)
                        {
                            Result = true;
                        }
                    }
                }
            }
            return(Result);
        }