Example #1
0
        internal static Polygon Ellipse(Vector mid, double a, double b, double angle, int steps)
        {
            var    p       = new Polygon();
            double beta    = -angle * Constants.DegToRad;
            double sinBeta = Math.Sin(beta);
            double cosBeta = Math.Cos(beta);

            for (int i = 0; i < steps; i++)
            {
                double currentAngle = i * 360.0 / steps;
                double alpha        = currentAngle * Constants.DegToRad;
                double sinAlpha     = Math.Sin(alpha);
                double cosAlpha     = Math.Cos(alpha);
                p.Add(new Vector(mid.X + a * cosAlpha * cosBeta - b * sinAlpha * sinBeta,
                                 mid.Y + a * cosAlpha * sinBeta + b * sinAlpha * cosBeta));
            }

            p.UpdateDecomposition();
            return(p);
        }
Example #2
0
 internal static void Decompose(List <Polygon> polygons)
 {
     for (int i = 0; i < polygons.Count; i++)
     {
         Polygon poly = polygons[i];
         if (poly.Count <= 3)
         {
             continue;
         }
         int firstDiagonal  = 0;
         int secondDiagonal = 2;
         var newPoly        = new Polygon();
         for (int j = firstDiagonal; j <= secondDiagonal; j++)
         {
             newPoly.Add(poly.Vertices[j]);
         }
         poly.RemoveRange(firstDiagonal + 1, secondDiagonal - firstDiagonal - 1);
         polygons.Add(newPoly);
         i -= 1;
     }
 }
Example #3
0
        private void LoadFromBytes(byte[] level)
        {
            Size          = level.Length;
            LevStartMagic = Encoding.UTF8.GetString(level, 0, 5);
            if (!IsElmaLevel && !IsAcrossLevel && !IsLeb)
            {
                throw new LevelException(
                          "Unknown file type. This is neither an Elma level, an Across level nor a LEB file.");
            }

            var sp = 7;

            if (IsAcrossLevel)
            {
                sp -= 2;
            }
            Identifier = BitConverter.ToInt32(level, sp);
            sp        += 4;
            for (var i = 0; i <= 3; i++)
            {
                Integrity[i] = BitConverter.ToDouble(level, sp);
                sp          += 8;
            }

            Title = Utils.ReadNullTerminatedString(level, sp, 60);
            if (IsAcrossLevel)
            {
                sp = 100;
            }
            else
            {
                sp                = 94;
                LgrFile           = Utils.ReadNullTerminatedString(level, sp, 16);
                sp               += 16;
                GroundTextureName = Utils.ReadNullTerminatedString(level, sp, 12).ToLower();
                sp               += 10;
                SkyTextureName    = Utils.ReadNullTerminatedString(level, sp, 12).ToLower();
                sp               += 10;
            }

            var polygonCount = (int)Math.Round(BitConverter.ToDouble(level, sp) - MagicDouble);

            sp += 8;
            var objectCount = -1;

            if (IsLeb)
            {
                objectCount = (int)Math.Round(BitConverter.ToDouble(level, sp) - MagicDouble);
                sp         += 8;
            }

            var isGrassPolygon = false;

            Polygons = new List <Polygon>();
            for (var i = 0; i < polygonCount; i++)
            {
                int numVertice;
                if (IsAcrossLevel)
                {
                    numVertice = level[sp] + 256 * level[sp + 1];
                    sp        += 4;
                }
                else
                {
                    numVertice     = level[sp + 4] + 256 * level[sp + 5];
                    sp            += 8;
                    isGrassPolygon = level[sp - 8] == 1;
                }

                var poly = new Polygon();
                for (var j = 0; j < numVertice; j++)
                {
                    var x = BitConverter.ToDouble(level, sp);
                    var y = BitConverter.ToDouble(level, sp + 8);
                    poly.Add(new Vector(x, y));
                    sp += 16;
                }

                poly.IsGrass = isGrassPolygon;
                Polygons.Add(poly);
            }

            if (!IsLeb)
            {
                objectCount = (int)Math.Round(BitConverter.ToDouble(level, sp) - MagicDouble);
                sp         += 8;
            }

            Apples = new List <LevObject>();
            var startFound = false;

            for (var i = 0; i < objectCount; i++)
            {
                var x          = BitConverter.ToDouble(level, sp);
                var y          = BitConverter.ToDouble(level, sp + 8);
                var objectType = (ObjectType)(level[sp + 16]);
                if (objectType == ObjectType.Start)
                {
                    startFound = true;
                }

                var appleType = AppleType.Normal;
                var animNum   = 0;
                if (!IsAcrossLevel)
                {
                    appleType = (AppleType)(BitConverter.ToInt32(level, sp + 20));
                    animNum   = BitConverter.ToInt32(level, sp + 24);
                    sp       += 28;
                }
                else
                {
                    sp += 20;
                }

                var objectToAdd = new LevObject(new Vector(x, y), objectType, appleType, animNum + 1);
                Objects.Add(objectToAdd);
                if (objectType == ObjectType.Apple)
                {
                    Apples.Add(objectToAdd);
                }
            }

            if (!startFound)
            {
                Objects.Add(new LevObject(new Vector(0, 0), ObjectType.Start, AppleType.Normal));
            }

            if (!IsAcrossLevel)
            {
                var numberOfPicturesPlusTextures = (int)Math.Round(BitConverter.ToDouble(level, sp) - MagicDouble2);
                sp += 8;
                for (var i = 0; i < numberOfPicturesPlusTextures; i++)
                {
                    if (level[sp] == 0)
                    {
                        _textureData.Add(new LevelFileTexture(Utils.ReadNullTerminatedString(level, sp + 10, 10),
                                                              Utils.ReadNullTerminatedString(level, sp + 20, 10),
                                                              new Vector(BitConverter.ToDouble(level, sp + 30),
                                                                         BitConverter.ToDouble(level, sp + 38)),
                                                              BitConverter.ToInt32(level, sp + 46),
                                                              ((ClippingType)(BitConverter.ToInt32(level, sp + 50)))));
                    }
                    else
                    {
                        _textureData.Add(new LevelFileTexture(Utils.ReadNullTerminatedString(level, sp, 10), null,
                                                              new Vector(BitConverter.ToDouble(level, sp + 30),
                                                                         BitConverter.ToDouble(level, sp + 38)),
                                                              BitConverter.ToInt32(level, sp + 46),
                                                              ((ClippingType)(BitConverter.ToInt32(level, sp + 50)))));
                    }
                    sp += 54;
                }
            }

            if (sp != level.Length)
            {
                sp += 4; //Skip end of data magic number
                CryptTop10(level, sp);
                try
                {
                    Top10.SinglePlayer = ReadTop10Part(level, sp, (a, b, t) => new Top10EntrySingle(a, b, t));
                    Top10.MultiPlayer  = ReadTop10Part(level, sp + 344, (a, b, t) => new Top10EntryMulti(a, b, t));
                }
                catch (IndexOutOfRangeException)
                {
                    throw new LevelException(
                              "Top 10 list is corrupted. The list will be cleared if you save the level.");
                }
            }

            UpdateBounds();
        }
Example #4
0
        private void LoadFromStream(Stream data)
        {
            var lev = new BinaryReader(data, Encoding.ASCII);

            LevStartMagic = lev.ReadString(5);
            if (!IsElmaLevel && !IsAcrossLevel && !IsLeb)
            {
                throw new BadFileException(
                          "Unknown file type. This is neither an Elma level, an Across level nor a LEB file.");
            }

            if (!IsAcrossLevel)
            {
                lev.ReadInt16();
            }

            Identifier = lev.ReadInt32();
            for (var i = 0; i < 4; i++)
            {
                Integrity[i] = lev.ReadDouble();
            }

            Title = lev.ReadNullTerminatedString(IsAcrossLevel ? 59 : 51);
            if (!IsAcrossLevel)
            {
                LgrFile           = lev.ReadNullTerminatedString(16);
                GroundTextureName = lev.ReadNullTerminatedString(10).ToLower();
                SkyTextureName    = lev.ReadNullTerminatedString(10).ToLower();
            }

            var polygonCount = (int)Math.Round(lev.ReadDouble() - MagicDouble);
            var objectCount  = -1;

            if (IsLeb)
            {
                objectCount = (int)Math.Round(lev.ReadDouble() - MagicDouble);
            }

            Polygons = new List <Polygon>();
            for (var i = 0; i < polygonCount; i++)
            {
                var isGrassPolygon = false;
                if (!IsAcrossLevel)
                {
                    isGrassPolygon = lev.ReadInt32() == 1;
                }

                var numVertice = lev.ReadInt32();
                var poly       = new Polygon();
                for (var j = 0; j < numVertice; j++)
                {
                    var x = lev.ReadDouble();
                    var y = lev.ReadDouble();
                    poly.Add(new Vector(x, y));
                }

                poly.IsGrass = isGrassPolygon;
                Polygons.Add(poly);
            }

            if (!IsLeb)
            {
                objectCount = (int)Math.Round(lev.ReadDouble() - MagicDouble);
            }

            var startFound = false;

            for (var i = 0; i < objectCount; i++)
            {
                var x          = lev.ReadDouble();
                var y          = lev.ReadDouble();
                var objectType = (ObjectType)lev.ReadInt32();
                if (objectType == ObjectType.Start)
                {
                    startFound = true;
                }

                var appleType = AppleType.Normal;
                var animNum   = 0;
                if (!IsAcrossLevel)
                {
                    appleType = (AppleType)lev.ReadInt32();
                    animNum   = lev.ReadInt32();
                }

                var objectToAdd = new LevObject(new Vector(x, y), objectType, appleType, animNum + 1);
                Objects.Add(objectToAdd);
            }

            if (!startFound)
            {
                Objects.Add(new LevObject(new Vector(0, 0), ObjectType.Start, AppleType.Normal));
            }

            if (!IsAcrossLevel)
            {
                var numberOfPicturesPlusTextures = (int)Math.Round(lev.ReadDouble() - MagicDouble2);
                for (var i = 0; i < numberOfPicturesPlusTextures; i++)
                {
                    var pictureName = lev.ReadNullTerminatedString(10);
                    var textureName = lev.ReadNullTerminatedString(10);
                    var maskName    = lev.ReadNullTerminatedString(10);
                    var x           = lev.ReadDouble();
                    var y           = lev.ReadDouble();
                    var distance    = lev.ReadInt32();
                    var clipping    = (ClippingType)lev.ReadInt32();
                    if (pictureName == "")
                    {
                        _textureData.Add(new LevelFileTexture(textureName,
                                                              maskName, new Vector(x, y),
                                                              distance,
                                                              clipping));
                    }
                    else
                    {
                        _textureData.Add(new LevelFileTexture(pictureName,
                                                              null, new Vector(x, y),
                                                              distance,
                                                              clipping));
                    }
                }
            }

            HandleLevEndRead(lev);
            UpdateBounds();
        }
Example #5
0
        internal static Polygon Connect(Polygon p1, Polygon p2, Vector v1, Vector v2, double connectRadius)
        {
            if (p1.IntersectsWith(p2))
            {
                return(null);
            }
            bool isContained = p1.AreaHasPoint(p2[0]) || p2.AreaHasPoint(p1[0]);
            var  p1C         = new Polygon(p1);
            var  p2C         = new Polygon(p2);

            if (p1C.IsCounterClockwise)
            {
                p1C.ChangeOrientation();
            }
            if (p2C.IsCounterClockwise ^ isContained)
            {
                p2C.ChangeOrientation();
            }
            int    numberOfIntersectionsP1C = 0;
            int    numberOfIntersectionsP2C = 0;
            Vector p1IsectPoint             = null;
            Vector p2IsectPoint             = null;

            Vector.MarkDefault = VectorMark.Selected;
            for (int i = 0; i < p1.Vertices.Count; i++)
            {
                Vector isectPoint = GetIntersectionPoint(p1[i], p1[i + 1], v1, v2);
                if ((object)isectPoint != null)
                {
                    p1IsectPoint = isectPoint;
                    p1C.InsertIntersection(p1IsectPoint, Constants.Tolerance);
                    numberOfIntersectionsP1C++;
                }
            }

            if (numberOfIntersectionsP1C != 1)
            {
                return(null);
            }
            for (int i = 0; i < p2.Vertices.Count; i++)
            {
                Vector isectPoint = GetIntersectionPoint(p2[i], p2[i + 1], v1, v2);
                if ((object)isectPoint != null)
                {
                    p2IsectPoint = isectPoint;
                    p2C.InsertIntersection(p2IsectPoint, Constants.Tolerance);
                    numberOfIntersectionsP2C++;
                }
            }

            Vector.MarkDefault = VectorMark.None;
            if (numberOfIntersectionsP2C != 1)
            {
                return(null);
            }
            var    result          = new Polygon();
            int    p1Index         = 0;
            int    p2Index         = p2C.IndexOf(p2IsectPoint);
            bool   p1CCurrent      = true;
            Vector p1ConnectVector = null;
            Vector p2ConnectVector = null;

            while (!(p1Index == 0 && p1CCurrent && result.Count > 0))
            {
                if (p1CCurrent)
                {
                    if (p1C[p1Index].Mark != VectorMark.Selected)
                    {
                        result.Add(p1C[p1Index]);
                    }
                    else
                    {
                        p1ConnectVector  = p1C[p1Index + 1] - p1C[p1Index - 1];
                        p1ConnectVector /= p1ConnectVector.Length;
                        var p1AngleAbs = Math.Abs(p1ConnectVector.AngleBetween(v2 - v1));
                        if (p1AngleAbs < Constants.Tolerance)
                        {
                            return(null);
                        }

                        p1ConnectVector *= connectRadius /
                                           Math.Sin(p1AngleAbs * Constants.DegToRad);
                        double distance1 = (p1C[p1Index + 1] - p1C[p1Index]).Length;
                        double distance2 = (p1C[p1Index] - p1C[p1Index - 1]).Length;
                        if (p1ConnectVector.Length > Math.Min(distance1, distance2))
                        {
                            p1ConnectVector = p1ConnectVector / p1ConnectVector.Length *
                                              Math.Min(distance1, distance2) /
                                              2;
                        }
                        result.Add(p1IsectPoint - p1ConnectVector);

                        p2ConnectVector  = p2C[p2Index + 1] - p2C[p2Index - 1];
                        p2ConnectVector /= p2ConnectVector.Length;
                        var p2AngleAbs = Math.Abs(p2ConnectVector.AngleBetween(v2 - v1));
                        if (p2AngleAbs < Constants.Tolerance)
                        {
                            return(null);
                        }

                        p2ConnectVector *= connectRadius /
                                           Math.Sin(p2AngleAbs * Constants.DegToRad);
                        double dist1 = (p2C[p2Index + 1] - p2C[p2Index]).Length;
                        double dist2 = (p2C[p2Index] - p2C[p2Index - 1]).Length;
                        if (p2ConnectVector.Length > Math.Min(dist1, dist2))
                        {
                            p2ConnectVector = p2ConnectVector / p2ConnectVector.Length * Math.Min(dist1, dist2) / 2;
                        }
                        result.Add(p2IsectPoint + p2ConnectVector);

                        p2Index++;
                        p1CCurrent = false;
                    }

                    p1Index++;
                    p1Index = p1Index % p1C.Count;
                }
                else
                {
                    if (p2C[p2Index].Mark != VectorMark.Selected)
                    {
                        result.Add(p2C[p2Index]);
                    }
                    else
                    {
                        result.Add(p2IsectPoint - p2ConnectVector);
                        result.Add(p1IsectPoint + p1ConnectVector);
                        p1CCurrent = true;
                    }

                    p2Index++;
                }
            }

            result.UpdateDecomposition();
            return(result);
        }
Example #6
0
        internal static Level LoadLevelFromImage(string imageFileName)
        {
            var lev = new Level();
            var vr  = new VectRast(false, false);

            byte[,] pixelOn;
            Bitmap    bmp;
            var       transformMatrix = Matrix2D.identityM();
            const int numFlowers      = 0;

            try
            {
                vr.loadAsBmp(imageFileName, out bmp, out pixelOn,
                             Math.Abs(transformMatrix.elements[0, 0]) + Math.Abs(transformMatrix.elements[1, 1]),
                             1, numFlowers);
            }
            catch (ArgumentException)
            {
                throw new VectrastException(string.Format("The image file {0} is invalid.", imageFileName));
            }

            try
            {
                vr.collapseVectors(vr.createVectors(pixelOn, bmp));
            }
            catch (Exception e)
            {
                throw new VectrastException(e.Message);
            }

            transformMatrix = Matrix2D.translationM(-bmp.Width / 2.0, -bmp.Height / 2.0) * transformMatrix;
            transformMatrix = transformMatrix * Matrix2D.scaleM(0.1, 0.1);
            bmp.Dispose();

            try
            {
                vr.transformVectors(transformMatrix);
            }
            catch (Exception e)
            {
                throw new VectrastException(e.Message);
            }

            if (vr.polygons.Count == 0)
            {
                throw new VectrastException(string.Format("Failed to vectorize the image file {0}.", imageFileName));
            }

            foreach (ArrayList polygon in vr.polygons)
            {
                var elmaPolygon = new Polygon();
                foreach (DoubleVector2 vertex in polygon)
                {
                    elmaPolygon.Add(new Vector(vertex.x, vertex.y));
                }

                lev.Polygons.Add(elmaPolygon);
            }

            return(lev);
        }