void Texturize(SS_Texture texture, Color targetColor, Color tint, bool highlights, bool shading)
        {
            Perlin perlin = new Perlin(0.025, 2, 0.5, 8, Seed, QualityMode.Low);

            SS_Texture BaseTexture = SS_StellarSprite.GenerateBaseTexture(Seed, texture.Width, texture.Height, 8 * (random.Range(1, 2)));

            for (int y = texture.Height / 2; y < texture.Height; y++)
            {
                for (int x = texture.Width / 2; x < texture.Width; x++)
                {
                    if (texture.GetPixel(x, y) == targetColor)
                    {
                        Color hullShade = BaseTexture.GetPixel(x, y);

                        // Pixel shade
                        float pixelNoise = (float)perlin.GetValue(x, y, 0);
                        pixelNoise = (pixelNoise + 3.0f) * 0.25f; // 0.5 to 1.0
                        pixelNoise = Mathf.Clamp(pixelNoise, 0.5f, 1f);

                        hullShade *= tint * pixelNoise;

                        if (shading)
                        {
                            SS_StellarSprite.PixelLighting(texture, x, y, ref hullShade);
                        }

                        hullShade.a = 1.0f;
                        texture.SetPixel(x, y, hullShade);
                    }
                }
            }
        }
Exemple #2
0
        private void CreateCockpit(SS_Texture targetTexture, Color baseColor)
        {
            // Temporary texture
            SS_Texture tmpTexture = new SS_Texture(Size, Size, Color.clear);

            // Data points for body edge
            List <SS_Point> topPoints    = new List <SS_Point>();
            List <SS_Point> bottomPoints = new List <SS_Point>();

            // Noise generator
            Perlin perlin = new Perlin(0.1, 2, 0.5, 8, Seed, QualityMode.Medium);

            // Calculated step points
            int step   = 2;
            int xStart = Sprite.Center.x + (BodyLength / 2) - (BodyLength / 4) - 2;

            for (int xCnt = 0; xCnt <= (BodyLength / 4); xCnt += step)
            {
                // Get some funky noise value
                float noise = (float)perlin.GetValue(xCnt, 0, 0);
                noise = (noise + 3.0f) * 0.25f; // Convert to 0 to 1
                noise = Mathf.Clamp(noise, 0.05f, 1f);

                int x = xStart + xCnt;
                int y = (int)(noise * 4);

                topPoints.Add(new SS_Point(x, Sprite.Center.y + y));
            }

            // Duplicate top points to bottom points but inverse the Y position
            for (int i = 0; i < topPoints.Count; i++)
            {
                SS_Point p = topPoints[i];
                p.y = Size - p.y - 1;
                bottomPoints.Add(p);
            }

            // Draw the body outline (one side only, the other will be mirrored)
            SS_Drawing.LineStrip(tmpTexture, topPoints.ToArray(), SS_StellarSprite.OutlineColor);
            SS_Drawing.LineStrip(tmpTexture, bottomPoints.ToArray(), SS_StellarSprite.OutlineColor);

            // Connect both sizes of lines
            SS_Drawing.Line(tmpTexture, topPoints[0].x, topPoints[0].y, topPoints[0].x, (Size - topPoints[0].y), SS_StellarSprite.OutlineColor);
            SS_Drawing.Line(tmpTexture, topPoints[topPoints.Count - 1].x, topPoints[topPoints.Count - 1].y, topPoints[topPoints.Count - 1].x, (Size - topPoints[topPoints.Count - 1].y), SS_StellarSprite.OutlineColor);

            // Fill with magenta
            SS_Drawing.FloodFillArea(tmpTexture, new SS_Point(xStart + 1, Sprite.Center.y), SS_StellarSprite.FillColor);

            // Texturize and shade
            if (!DebugDrawing)
            {
                Texturize(tmpTexture, SS_StellarSprite.FillColor, baseColor, false, true);
                SS_StellarSprite.ShadeEdge(tmpTexture);
            }
            SS_Drawing.MergeColors(targetTexture, tmpTexture, 0, 0);
        }
Exemple #3
0
        private void Texturize(SS_Texture texture, Color targetColor, Color tint, bool highlights, bool shading)
        {
            Perlin  perlin            = new Perlin(ColorDetail, 2, 0.5, 8, Seed, QualityMode.High);
            Voronoi hightlightVoronoi = new Voronoi(ColorDetail, 2, Seed, true);

            SS_Texture BaseTexture = SS_StellarSprite.GenerateBaseTexture(Seed, Size, Size, 16);

            for (int y = Size / 2; y < Size; y++)
            {
                for (int x = 0; x < Size; x++)
                {
                    if (texture.GetPixel(x, y) == targetColor)
                    {
                        Color hullShade = BaseTexture.GetPixel(x, y);

                        //Pixel shade
                        float pixelNoise = (float)perlin.GetValue(x, y, 0);
                        pixelNoise = (pixelNoise + 3.0f) * 0.25f; // 0.5 to 1.0
                        pixelNoise = Mathf.Clamp(pixelNoise, 0.5f, 1f);

                        hullShade *= tint * pixelNoise;

                        if (highlights)
                        {
                            // Pixel shade
                            float hightlightNoise = (float)hightlightVoronoi.GetValue(x, y, 0);
                            hightlightNoise = (hightlightNoise + 1.0f) * 0.5f; // 0.0 to 1.0
                            hightlightNoise = Mathf.Clamp(hightlightNoise, 0.0f, 1f);

                            if (hightlightNoise <= 0.75f)
                            {
                                hullShade = ColorBase * pixelNoise;
                            }
                            else
                            {
                                hullShade = ColorHighlight * pixelNoise;
                            }
                        }

                        // Check the current pixel and find when it hits a solid black outline.  if it does
                        // Make the current pixel a bit darker - do for all 4 dirtections
                        if (shading)
                        {
                            SS_StellarSprite.PixelLighting(texture, x, y, ref hullShade);
                        }

                        hullShade.a = 1.0f;
                        texture.SetPixel(x, y, hullShade);
                    }
                }
            }

            // Mirror
            SS_StellarSprite.Mirror(texture, SS_Mirror.Vertical);
        }
        void CreatePods(int count, int pW, int pH, int resolution, int distanceFromCenter, double scale, Color baseColor)
        {
            SS_Texture tmpTexture = new SS_Texture(Size, Size, Color.clear);

            int step = 360 / count;

            // Setup pod positions
            List <SS_Point> pods = new List <SS_Point>();

            for (int a = 0; a < 359; a += step)
            {
                int x = Sprite.Center.x + (int)(Mathf.Cos(a * Mathf.Deg2Rad) * distanceFromCenter);
                int y = Sprite.Center.y + (int)(Mathf.Sin(a * Mathf.Deg2Rad) * distanceFromCenter);

                pods.Add(new SS_Point(x, y));
            }

            // Draw pods
            for (int i = 0; i < pods.Count; i++)
            {
                SS_Point[] positions = new SS_Point[resolution + 1];

                // angle from
                float angleToStation = Mathf.Atan2(pods[i].y - Sprite.Center.x, pods[i].x - Sprite.Center.x) * Mathf.Rad2Deg;
                angleToStation += 90;

                for (int j = 0; j <= resolution; j++)
                {
                    // Angle from pod Sprite.Center
                    float angleToPod = (float)j / (float)resolution * 2.0f * Mathf.PI;

                    // Set the original pod point
                    float x = pods[i].x + ((short)((pW * scale) * Mathf.Cos(angleToPod)));
                    float y = pods[i].y + ((short)((pH * scale) * Mathf.Sin(angleToPod)));

                    // rotate the point based on it's angle from the Sprite.Center of the pod
                    float xRotated = pods[i].x + (x - pods[i].x) * Mathf.Cos(angleToStation * Mathf.Deg2Rad) - (y - pods[i].y) * Mathf.Sin(angleToStation * Mathf.Deg2Rad);
                    float yRotated = pods[i].y + (x - pods[i].x) * Mathf.Sin(angleToStation * Mathf.Deg2Rad) + (y - pods[i].y) * Mathf.Cos(angleToStation * Mathf.Deg2Rad);

                    positions[j] = new SS_Point((int)xRotated, (int)yRotated);
                }

                SS_Drawing.PolygonFill(tmpTexture, positions, SS_StellarSprite.OutlineColor, SS_StellarSprite.FillColor);
            }

            Texturize(tmpTexture, SS_StellarSprite.FillColor, baseColor, false, true);
            SS_StellarSprite.ShadeEdge(tmpTexture);
            SS_StellarSprite.Mirror(tmpTexture, SS_Mirror.TopRight);
            SS_Drawing.MergeColors(Sprite, tmpTexture, 0, 0);
        }
        public SS_Station(int seed, SS_StationType stationType, Color tint, int numberOfPods)
        {
            Seed = seed;

            random = new SS_Random(Seed);
            Sprite = new SS_Texture(Size, Size, Color.clear);

            if (stationType == SS_StationType.Cool)
            {
                CreateRing(random.Range(0.85f, 1.0f), random.Range(1, 4), true, random.NextColor(), false);
                CreateRing(random.Range(0.5f, 0.75f), random.Range(1, 4), true, random.NextColor(), true);

                // Draw lights
                for (int i = 0; i < LightPoints.Count; i++)
                {
                    CreateFlare(Sprite, LightPoints[i], 16, true, Color.white);
                }

                int podCount    = random.RangeEven(2, 8);
                int podWidth    = random.RangeEven(24, 32);
                int podHeight   = random.RangeEven(12, 24);
                int podDistance = random.RangeEven(64, Size / 2 - 32);
                CreatePods(podCount, podWidth, podHeight, 8, podDistance, 1.0, Color.grey);
                CreatePods(podCount, podWidth, podHeight, 8, podDistance, 0.75, Color.grey);

                Color[] flareColors = SS_Utilities.GenerateColorWheelColors(Seed, 3);
                CreateFlare(Sprite, new SS_Point(Sprite.Center.x, Sprite.Center.y), 128, true, flareColors[0]);
                CreateFlare(Sprite, new SS_Point(Sprite.Center.x, Sprite.Center.y), 64, true, flareColors[1]);
                CreateFlare(Sprite, new SS_Point(Sprite.Center.x, Sprite.Center.y), 32, true, flareColors[2]);
            }
            else if (stationType == SS_StationType.Pod)
            {
                int podCount    = numberOfPods;
                int podSize     = 64;
                int step        = 360 / podCount;
                int bridgeWidth = random.RangeEven(8, 16);

                // Setup pod positions
                List <SS_Point> podPositions = new List <SS_Point>();
                for (int a = 0; a < 359; a += step)
                {
                    int x = Sprite.Center.x + (int)(Mathf.Cos(a * Mathf.Deg2Rad) * 96);
                    int y = Sprite.Center.y + (int)(Mathf.Sin(a * Mathf.Deg2Rad) * 96);

                    podPositions.Add(new SS_Point(x, y));
                }

                for (int i = 0; i < podPositions.Count; i++)
                {
                    SS_Texture      tmpBridgeTexture = new SS_Texture(Size, Size, Color.clear);
                    List <SS_Point> points           = new List <SS_Point>();

                    int px1 = podPositions[i].x + (int)(Mathf.Cos((i * step - 90) * Mathf.Deg2Rad) * bridgeWidth);
                    int py1 = podPositions[i].y + (int)(Mathf.Sin((i * step - 90) * Mathf.Deg2Rad) * bridgeWidth);
                    int px2 = podPositions[i].x + (int)(Mathf.Cos((i * step + 90) * Mathf.Deg2Rad) * bridgeWidth);
                    int py2 = podPositions[i].y + (int)(Mathf.Sin((i * step + 90) * Mathf.Deg2Rad) * bridgeWidth);

                    int cx1 = Sprite.Center.x + (int)(Mathf.Cos((i * step - 90) * Mathf.Deg2Rad) * bridgeWidth);
                    int cy1 = Sprite.Center.y + (int)(Mathf.Sin((i * step - 90) * Mathf.Deg2Rad) * bridgeWidth);
                    int cx2 = Sprite.Center.x + (int)(Mathf.Cos((i * step + 90) * Mathf.Deg2Rad) * bridgeWidth);
                    int cy2 = Sprite.Center.y + (int)(Mathf.Sin((i * step + 90) * Mathf.Deg2Rad) * bridgeWidth);

                    points.Add(new SS_Point(cx1, cy1));
                    points.Add(new SS_Point(px1, py1));
                    points.Add(new SS_Point(px2, py2));
                    points.Add(new SS_Point(cx2, cy2));

                    SS_Drawing.PolygonFill(tmpBridgeTexture, points.ToArray(), SS_StellarSprite.FillColor, SS_StellarSprite.FillColor);
                    SS_Drawing.MergeColors(Sprite, tmpBridgeTexture, 0, 0);
                }

                int numPoints = random.RangeEven(6, 10);
                for (int i = 0; i < podPositions.Count; i++)
                {
                    float angleStep = 360.0f / numPoints;

                    List <SS_Point> controlPoints = new List <SS_Point>();
                    for (float angle = 0; angle < 360f; angle += angleStep)
                    {
                        int px = (int)(podPositions[i].x + (Mathf.Cos(angle * Mathf.Deg2Rad) * (podSize * 0.5)));
                        int py = (int)(podPositions[i].y + (Mathf.Sin(angle * Mathf.Deg2Rad) * (podSize * 0.5)));

                        controlPoints.Add(new SS_Point(px, py));
                    }

                    SS_Texture tmpPodTexture = new SS_Texture(Size, Size, Color.clear);
                    SS_Drawing.PolygonFill(tmpPodTexture, controlPoints.ToArray(), SS_StellarSprite.OutlineColor, SS_StellarSprite.FillColor);
                    SS_Drawing.MergeColors(Sprite, tmpPodTexture, 0, 0);

                    List <SS_Point> controlPoints2 = new List <SS_Point>();
                    for (float angle = 0; angle < 360f; angle += angleStep)
                    {
                        int px = (int)(podPositions[i].x + (Mathf.Cos(angle * Mathf.Deg2Rad) * (podSize * 0.4)));
                        int py = (int)(podPositions[i].y + (Mathf.Sin(angle * Mathf.Deg2Rad) * (podSize * 0.4)));

                        controlPoints2.Add(new SS_Point(px, py));
                        LightPoints.Add(new SS_Point(px, py));
                    }

                    SS_Texture tmpPodTexture2 = new SS_Texture(Size, Size, Color.clear);
                    SS_Drawing.PolygonFill(tmpPodTexture2, controlPoints2.ToArray(), SS_StellarSprite.OutlineColor, SS_StellarSprite.FillColor);
                    SS_Drawing.MergeColors(Sprite, tmpPodTexture2, 0, 0);
                }

                int hubSize      = random.RangeEven(64, 128);
                int numHubPoints = random.RangeEven(6, 10);

                float hubAngleSteps = 360.0f / numHubPoints;

                List <SS_Point> hubPoints = new List <SS_Point>();
                for (float angle = 0; angle < 360f; angle += hubAngleSteps)
                {
                    int px = (int)(Sprite.Center.x + (Mathf.Cos(angle * Mathf.Deg2Rad) * (hubSize * 0.5)));
                    int py = (int)(Sprite.Center.y + (Mathf.Sin(angle * Mathf.Deg2Rad) * (hubSize * 0.5)));

                    hubPoints.Add(new SS_Point(px, py));
                }

                SS_Texture tmpHub = new SS_Texture(Size, Size, Color.clear);
                SS_Drawing.PolygonFill(tmpHub, hubPoints.ToArray(), SS_StellarSprite.OutlineColor, SS_StellarSprite.FillColor);
                SS_Drawing.MergeColors(Sprite, tmpHub, 0, 0);

                List <SS_Point> hubPoints2 = new List <SS_Point>();
                for (float angle = 0; angle < 360f; angle += hubAngleSteps)
                {
                    int px = (int)(Sprite.Center.x + (Mathf.Cos(angle * Mathf.Deg2Rad) * (hubSize * 0.4)));
                    int py = (int)(Sprite.Center.y + (Mathf.Sin(angle * Mathf.Deg2Rad) * (hubSize * 0.4)));

                    hubPoints2.Add(new SS_Point(px, py));
                }

                SS_Texture tmpHub2 = new SS_Texture(Size, Size, Color.clear);
                SS_Drawing.PolygonFill(tmpHub2, hubPoints2.ToArray(), SS_StellarSprite.OutlineColor, SS_StellarSprite.FillColor);
                SS_Drawing.MergeColors(Sprite, tmpHub2, 0, 0);

                SS_Drawing.Outline(Sprite, Color.black);
                Texturize(Sprite, Color.magenta, tint, false, true);
                SS_StellarSprite.ShadeEdge(Sprite);

                SS_StellarSprite.Mirror(Sprite, SS_Mirror.TopRight);

                foreach (SS_Point p in podPositions)
                {
                    CreateFlare(Sprite, p, 32, false, Color.white);
                }

                foreach (SS_Point p in LightPoints)
                {
                    CreateFlare(Sprite, p, 16, true, Color.white);
                }

                CreateFlare(Sprite, Sprite.Center, hubSize, false, Color.white);
            }
        }
        void CreateRing(float scale, int sectionsPerQuarter, bool details, Color detailColor, bool lights)
        {
            //  Only draws top right quarter, the rest is mirrored
            List <SS_Point> DetailPoints = new List <SS_Point>();

            SS_Texture tmpTexture = new SS_Texture(Size, Size, Color.clear);

            int innerRadius = (int)((Size / 8) * scale);
            int outerRadius = (int)(((Size / 2) - 4) * scale);

            List <SS_Point> innerPoints = new List <SS_Point>();
            List <SS_Point> outerPoints = new List <SS_Point>();

            int step = 90 / sectionsPerQuarter;

            for (int a = 0; a <= 90; a += step)
            {
                int innerX = Sprite.Center.x + (int)(Mathf.Cos(a * Mathf.Deg2Rad) * innerRadius);
                int innerY = Sprite.Center.y + (int)(Mathf.Sin(a * Mathf.Deg2Rad) * innerRadius);

                innerPoints.Add(new SS_Point(innerX, innerY));

                int outerX = Sprite.Center.x + (int)(Mathf.Cos(a * Mathf.Deg2Rad) * outerRadius);
                int outerY = Sprite.Center.y + (int)(Mathf.Sin(a * Mathf.Deg2Rad) * outerRadius);

                outerPoints.Add(new SS_Point(outerX, outerY));

                if (lights)
                {
                    LightPoints.Add(new SS_Point(outerX, outerY));
                    LightPoints.Add(new SS_Point(Size - outerX, outerY));
                    LightPoints.Add(new SS_Point(Size - outerX, Size - outerY));
                    LightPoints.Add(new SS_Point(outerX, Size - outerY));
                }
            }

            // Determine centroids (detail points) for each ring section
            for (int i = 0; i < innerPoints.Count - 1; i++)
            {
                SS_Point[] points = new SS_Point[4];

                int j  = i;
                int j2 = i + 1;
                if (i == innerPoints.Count - 1)
                {
                    j2 = 0;
                }

                points[0] = innerPoints[j];
                points[1] = outerPoints[j];
                points[2] = outerPoints[j2];
                points[3] = innerPoints[j2];

                SS_Point centroid = SS_Utilities.Centroid(points);

                if (random.NextBool())
                {
                    DetailPoints.Add(centroid);
                }
            }

            List <SS_Point> ringPoints = new List <SS_Point>();

            for (int i = 0; i < innerPoints.Count; i++)
            {
                ringPoints.Add(innerPoints[i]);
            }

            for (int i = outerPoints.Count - 1; i >= 0; i--)
            {
                ringPoints.Add(outerPoints[i]);
            }

            SS_Drawing.PolygonFill(tmpTexture, ringPoints.ToArray(), SS_StellarSprite.OutlineColor, SS_StellarSprite.FillColor);

            // Add borders between sectons
            float colorVal      = 0;// random.Range(0.25f, 1f);
            Color sectionBorder = new Color(colorVal, colorVal, colorVal);

            for (int i = 0; i < innerPoints.Count; i++)
            {
                SS_Drawing.Line(tmpTexture, innerPoints[i].x, innerPoints[i].y, outerPoints[i].x, outerPoints[i].y, sectionBorder);
            }

            if (details)
            {
                for (int i = 0; i < DetailPoints.Count; i++)
                {
                    SS_Drawing.EllipseFill(tmpTexture, DetailPoints[i].x, DetailPoints[i].y, 8, 8, 12, SS_StellarSprite.OutlineColor, detailColor);
                }
            }

            // Texture the section
            Texturize(tmpTexture, SS_StellarSprite.FillColor, Color.grey, false, true);

            SS_StellarSprite.ShadeEdge(tmpTexture);
            SS_StellarSprite.Mirror(tmpTexture, SS_Mirror.TopRight);

            SS_Drawing.MergeColors(Sprite, tmpTexture, 0, 0);
        }
Exemple #7
0
        private void CreateEngine(SS_Texture targetTexture, int count)
        {
            // Temporary texture
            SS_Texture tmpTexture = new SS_Texture(Size, Size, Color.clear);

            // Noise generator
            Perlin perlin = new Perlin(0.1, 2, 0.5, 8, Seed, QualityMode.Medium);

            int yStep = Size / (1 + count);

            for (int i = 1; i <= count; i++)
            {
                // Data points for body edge
                List <SS_Point> topPoints    = new List <SS_Point>();
                List <SS_Point> bottomPoints = new List <SS_Point>();

                // Calculated step points
                int step   = 2;
                int xStart = (Size / 2) - (BodyLength / 2);

                for (int xCnt = 0; xCnt <= 16; xCnt += step)
                {
                    // Get some funky noise value
                    float noise = (float)perlin.GetValue(xCnt, 0, 0);
                    noise = (noise + 3.0f) * 0.25f; // Convert to 0 to 1
                    noise = Mathf.Clamp(noise, 0.05f, 1f);

                    int x   = xStart + xCnt;
                    int y   = (int)(noise * 4);
                    int mod = 0;
                    if (count >= 4)
                    {
                        mod = 2;
                    }

                    topPoints.Add(new SS_Point(x, i * yStep + y + mod));
                    bottomPoints.Add(new SS_Point(x, i * yStep - y - 1 + mod));
                }

                // Draw the body outline (one side only, the other will be mirrored)
                SS_Drawing.LineStrip(tmpTexture, topPoints.ToArray(), SS_StellarSprite.FillColor);
                SS_Drawing.LineStrip(tmpTexture, bottomPoints.ToArray(), SS_StellarSprite.FillColor);

                // Connect both sizes of lines
                SS_Drawing.Line(tmpTexture, topPoints[0].x, topPoints[0].y,
                                bottomPoints[0].x,
                                bottomPoints[0].y,
                                SS_StellarSprite.FillColor);
                SS_Drawing.Line(tmpTexture, topPoints[topPoints.Count - 1].x, topPoints[topPoints.Count - 1].y,
                                bottomPoints[bottomPoints.Count - 1].x,
                                bottomPoints[bottomPoints.Count - 1].y,
                                SS_StellarSprite.FillColor);

                SS_Point centroid = new SS_Point(xStart + 2, i * yStep + 1);

                // Fill with magenta
                SS_Drawing.FloodFillArea(tmpTexture, centroid, SS_StellarSprite.FillColor);

                // Create Exhaust Points
                ExhaustPoint.Add(new SS_Point(topPoints[0].x, bottomPoints[0].y + ((topPoints[0].y - bottomPoints[0].y) / 2)));
            }

            // Draw a bar connecting all the engines (no floaters)
            if (count > 1)
            {
                int top    = (Size / 2) + ((count * 8) / 2) + 1;
                int bottom = (Size / 2) - ((count * 8) / 2) - 1;
                SS_Drawing.Line(tmpTexture, (Size / 2) - (BodyLength / 2) + 10, bottom, (Size / 2) - (BodyLength / 2) + 10, top, SS_StellarSprite.FillColor);
                SS_Drawing.Line(tmpTexture, (Size / 2) - (BodyLength / 2) + 11, bottom, (Size / 2) - (BodyLength / 2) + 11, top, SS_StellarSprite.FillColor);
                SS_Drawing.Line(tmpTexture, (Size / 2) - (BodyLength / 2) + 12, bottom, (Size / 2) - (BodyLength / 2) + 12, top, SS_StellarSprite.FillColor);
            }

            // Outline engines
            SS_Drawing.Outline(tmpTexture, SS_StellarSprite.OutlineColor);

            // Texturize and shade
            if (!DebugDrawing)
            {
                Texturize(tmpTexture, SS_StellarSprite.FillColor, ColorEngine, false, true);
                SS_StellarSprite.ShadeEdge(tmpTexture);
            }
            SS_Drawing.MergeColors(targetTexture, tmpTexture, 0, 0);
        }
Exemple #8
0
        private void CreateWing(SS_Texture targetTexture, Color baseColor, bool highlights)
        {
            // Temporary texture
            SS_Texture tmpTexture = new SS_Texture(Size, Size, Color.clear);

            // Wing dimensions
            int wingLength  = 64;// (int)(random.RangeEven(32, 64));
            int wingSize    = (int)(random.Range(4, 12));
            int wingCenterX = wingSize / 2;
            int wingOffsetX = random.Range((Size / 2) - (BodyLength / 2), (Size / 2) + wingSize);

            // Data points for body edge
            List <SS_Point> fPoints = new List <SS_Point>();
            List <SS_Point> bPoints = new List <SS_Point>();

            // Noise generators
            RidgedMultifractal fWingNoise = new RidgedMultifractal(WingDetail, 2, 8, Seed, QualityMode.Medium);
            RidgedMultifractal bWingNoise = new RidgedMultifractal(WingDetail, 2, 8, Seed + 1, QualityMode.Medium);

            // Determine if wing has a flat edge
            int fEdgeMod = random.RangeEven(0, 8);
            int bEdgeMod = random.RangeEven(0, 8);

            // Start point of wing (this determinds if the wings are separated or joined
            int startY = 0;

            if (random.NextBool())
            {
                startY = random.RangeEven(2, 8);
            }

            int fEndY = Sprite.Center.y + (wingLength / 2) - fEdgeMod;
            int bEndY = Sprite.Center.y + (wingLength / 2) - bEdgeMod;

            // Calculate steps based on length of modified wing length
            int fStep = (fEndY - Sprite.Center.y) / 4;
            int bStep = (bEndY - Sprite.Center.y) / 4;

            // Front Edge
            for (int y = Sprite.Center.y + startY; y <= fEndY + 1; y += fStep)
            {
                // Get some funky noise value for the back of the wing
                float noise = (float)fWingNoise.GetValue(0, y, 0);
                noise = (noise + 1.0f) * 0.5f; // Convert to 0 to 1
                noise = Mathf.Clamp(noise, 0.05f, 1f);

                int x = (wingOffsetX + wingCenterX) + (int)(noise * wingSize);
                if (x > Size - 1)
                {
                    x = Size - 1;                 // Clamp to bounds
                }
                fPoints.Add(new SS_Point(x, y));
            }

            // Back Edge
            for (int y = Sprite.Center.y + startY; y <= bEndY + 1; y += bStep)
            {
                // Get some funky noise value for the front of the wing
                float noise = (float)bWingNoise.GetValue(0, y, 0);
                noise = (noise + 1.0f) * 0.5f; // Convert to 0 to 1
                noise = Mathf.Clamp(noise, 0.05f, 1f);

                int x = (wingOffsetX - wingCenterX) - (int)(noise * wingSize);
                if (x < 0)
                {
                    x = 0;          // Clamp to bounds
                }
                bPoints.Add(new SS_Point(x, y));
            }

            // Smoothing
            for (int j = 0; j < 2; j++)
            {
                for (int i = 0; i < fPoints.Count - 1; i++)
                {
                    float x = (fPoints[i].x + fPoints[i + 1].x) / 2f;
                    fPoints[i] = new SS_Point((int)x, fPoints[i].y);
                }

                for (int i = 0; i < bPoints.Count - 1; i++)
                {
                    float x = (bPoints[i].x + bPoints[i + 1].x) / 2f;
                    bPoints[i] = new SS_Point((int)x, bPoints[i].y);
                }
            }

            // Build polygon using both sets of points (left and right side)
            List <SS_Point> points = new List <SS_Point>();

            for (int i = 0; i < fPoints.Count; i++)
            {
                points.Add(fPoints[i]);
            }
            // Add the back edge points backwards to the point list to keep the vertex ordering correct
            for (int i = bPoints.Count - 1; i >= 0; i--)
            {
                points.Add(bPoints[i]);
            }

            // Create wing weapons before drawing the actual wing so they appear underneigth
            CreateWeapon(targetTexture, new SS_Point(wingOffsetX + wingCenterX, (Size / 2) + (startY + (wingLength / 4))), Color.yellow);
            CreateWeapon(targetTexture, new SS_Point(wingOffsetX + wingCenterX, (Size / 2) - (startY + (wingLength / 4))), Color.yellow);

            // Draw polygon for the wing
            SS_Drawing.PolygonFill(tmpTexture, points.ToArray(), SS_StellarSprite.FillColor, SS_StellarSprite.FillColor);

            // Mirror Vertically for the bottom/right wing
            int cntr = 1;

            for (int y = Sprite.Center.y; y < Size; y++)
            {
                for (int x = 0; x < Size; x++)
                {
                    int newY = y - cntr;
                    tmpTexture.SetPixel(x, newY, tmpTexture.GetPixel(x, y));
                }
                cntr += 2;
            }

            // Draw the wing(s) outline
            SS_Drawing.Outline(tmpTexture, SS_StellarSprite.OutlineColor);

            // Texturize and shade
            if (!DebugDrawing)
            {
                Texturize(tmpTexture, SS_StellarSprite.FillColor, baseColor, highlights, true);
                SS_StellarSprite.ShadeEdge(tmpTexture);
            }
            SS_Drawing.MergeColors(targetTexture, tmpTexture, 0, 0);
        }
Exemple #9
0
        private void CreateBody(SS_Texture targetTexture, SS_ShipBody body, int length, int smoothCount, bool highlights)
        {
            // Temporary texture
            SS_Texture tmpTexture = new SS_Texture(Size, Size, Color.clear);

            // Determine type of body to generate
            if (body == SS_ShipBody.Human)
            {
                // Data points for body edge
                List <SS_Point> topPoints    = new List <SS_Point>();
                List <SS_Point> bottomPoints = new List <SS_Point>();

                // Noise generator
                Perlin perlin = new Perlin(BodyDetail, 2, 0.5, 8, Seed, QualityMode.Medium);

                // Calculated step points
                int step = length / GetRandomBodyStep(length);

                for (int xCnt = 0; xCnt <= length; xCnt += step)
                {
                    // Get some funky noise value
                    float noise = (float)perlin.GetValue(xCnt, 0, 0);
                    noise = (noise + 3.0f) * 0.25f; // Convert to 0 to 1
                    noise = Mathf.Clamp(noise, 0.05f, 1f);

                    int x = Sprite.Center.x - (length / 2) + xCnt;
                    if (x > Size - 1)
                    {
                        x = Size - 1;
                    }
                    int y = (int)(noise * (Size / 4));

                    topPoints.Add(new SS_Point(x, Sprite.Center.y + y));
                }

                // Fix first and last points so they are less ugly than a random tip and butt.
                topPoints[0] = new SS_Point(topPoints[0].x, Sprite.Center.y + 4);
                topPoints[topPoints.Count - 1] = new SS_Point(topPoints[topPoints.Count - 1].x, Sprite.Center.y + 2);

                // Loop through all the points and smooth them out a bit
                for (int j = 0; j < smoothCount; j++)
                {
                    for (int i = 0; i < topPoints.Count - 1; i++)
                    {
                        float y = (topPoints[i].y + topPoints[i + 1].y) / 2f;
                        y            = Mathf.Ceil(y);
                        topPoints[i] = new SS_Point(topPoints[i].x, (int)y);
                    }
                }

                // Duplicate top points to bottom points but inverse the Y position
                for (int i = 0; i < topPoints.Count; i++)
                {
                    SS_Point p = topPoints[i];
                    p.y = Size - p.y - 1;
                    bottomPoints.Add(p);
                }

                // Draw the body outline - use lines since they seem to be more symmetric (pixel placement) than my polygon drawing... not sure why.
                SS_Drawing.LineStrip(tmpTexture, topPoints.ToArray(), SS_StellarSprite.OutlineColor);
                SS_Drawing.LineStrip(tmpTexture, bottomPoints.ToArray(), SS_StellarSprite.OutlineColor);

                // Connect both sizes of lines
                SS_Drawing.Line(tmpTexture, topPoints[0].x, topPoints[0].y, topPoints[0].x, (Size - topPoints[0].y), SS_StellarSprite.OutlineColor);
                SS_Drawing.Line(tmpTexture, topPoints[topPoints.Count - 1].x, topPoints[topPoints.Count - 1].y, topPoints[topPoints.Count - 1].x, (Size - topPoints[topPoints.Count - 1].y), SS_StellarSprite.OutlineColor);

                // Fill with magenta
                SS_Drawing.FloodFillArea(tmpTexture, Sprite.Center, SS_StellarSprite.FillColor);

                // Inner detail (same shape as body, but slightly smaller)
                for (int i = 0; i < topPoints.Count; i++)
                {
                    topPoints[i] = SS_Point.Scale(topPoints[i], Sprite.Center, 0.5f, 0.25f);
                }

                for (int i = 0; i < bottomPoints.Count; i++)
                {
                    bottomPoints[i] = SS_Point.Scale(bottomPoints[i], Sprite.Center, 0.5f, 0.25f);
                }

                // Draw the body outline - use lines since they seem to be more symmetric (pixel placement) than my polygon drawing... not sure why.
                SS_Drawing.LineStrip(tmpTexture, topPoints.ToArray(), SS_StellarSprite.OutlineColor);
                SS_Drawing.LineStrip(tmpTexture, bottomPoints.ToArray(), SS_StellarSprite.OutlineColor);

                // Connect both sizes of lines
                SS_Drawing.Line(tmpTexture, topPoints[0].x, topPoints[0].y, topPoints[0].x, (Size - topPoints[0].y), SS_StellarSprite.OutlineColor);
                SS_Drawing.Line(tmpTexture, topPoints[topPoints.Count - 1].x, topPoints[topPoints.Count - 1].y, topPoints[topPoints.Count - 1].x, (Size - topPoints[topPoints.Count - 1].y), SS_StellarSprite.OutlineColor);

                // Texturize and shade
                if (!DebugDrawing)
                {
                    Texturize(tmpTexture, SS_StellarSprite.FillColor, ColorBase, highlights, true);
                    SS_StellarSprite.ShadeEdge(tmpTexture);
                }
                SS_Drawing.MergeColors(targetTexture, tmpTexture, 0, 0);
            }
            else if (body == SS_ShipBody.Alien)
            {
                float bodyAngleSteps = 360.0f / 32;

                List <SS_Point> bodyPoints = new List <SS_Point>();
                for (float angle = 0; angle < 360f; angle += bodyAngleSteps)
                {
                    int px = (int)((Size / 2) + (Mathf.Cos(angle * Mathf.Deg2Rad) * (BodyLength * 0.5)));
                    int py = (int)((Size / 2) + (Mathf.Sin(angle * Mathf.Deg2Rad) * (BodyLength * 0.5)));

                    bodyPoints.Add(new SS_Point(px, py));
                }

                SS_Drawing.PolygonFill(tmpTexture, bodyPoints.ToArray(), SS_StellarSprite.OutlineColor, SS_StellarSprite.FillColor);

                if (!DebugDrawing)
                {
                    Texturize(tmpTexture, SS_StellarSprite.FillColor, ColorBase, false, true);
                }

                Color ringColor = random.NextColor();
                int   ringMin   = random.RangeEven(12, 18);
                int   ringMax   = random.RangeEven(18, 24);

                for (int y = 0; y < Size; y++)
                {
                    for (int x = 0; x < Size; x++)
                    {
                        int dist = SS_Point.Distance(new SS_Point(x, y), Sprite.Center);

                        if (dist >= ringMin && dist <= ringMax)
                        {
                            tmpTexture.SetPixel(x, y, tmpTexture.GetPixel(x, y) * ringColor);
                        }
                    }
                }

                if (random.NextBool())
                {
                    CreateFlare(tmpTexture, Sprite.Center, 48, true, random.NextColor());
                }
                if (random.NextBool())
                {
                    CreateFlare(tmpTexture, Sprite.Center, 24, true, Color.white);
                }

                if (!DebugDrawing)
                {
                    SS_StellarSprite.ShadeEdge(tmpTexture);
                }
                SS_Drawing.MergeColors(targetTexture, tmpTexture, 0, 0);
            }
        }