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); } }
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); }
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); }
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); } }