public SS_Cloud(int seed, int size, double frequency, double lacunarity, int octaves, Color tint, float brightness) { // Create sprite texture Sprite = new SS_Texture(size, size, Color.white); // Initialize noise with parameters RidgedMultifractal noise = new RidgedMultifractal(frequency, lacunarity, octaves, seed, QualityMode.Medium); // Create cloud for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { float distance = SS_Point.Distance(new SS_Point(x, y), Sprite.Center); float n = (float)noise.GetValue(x, y, 0); Color pixelColor = tint * n * brightness; float blackness = ((pixelColor.r + pixelColor.g + pixelColor.b) / 3.0f); float fade = distance / (size / 2); pixelColor.a = (1f - fade) * blackness; if (distance > (size / 2)) { pixelColor.a = 0f; } Sprite.SetPixel(x, y, pixelColor); } } }
public static void Blur(ref SS_Texture texture) { SS_Texture tmp = new SS_Texture(texture.Width, texture.Height, Color.clear); float v = 1.0f / 9.0f; float[,] kernel = { { v, v, v }, { v, v, v }, { v, v, v } }; // Loop through every pixel in the image for (int y = 1; y < texture.Height - 1; y++) { for (int x = 1; x < texture.Width - 1; x++) { float alpha = texture.GetPixel(x, y).a; Color sum = Color.clear; // Kernel sum for this pixel for (int ky = -1; ky <= 1; ky++) { for (int kx = -1; kx <= 1; kx++) { sum += kernel[ky + 1, kx + 1] * texture.GetPixel(x + kx, y + ky); } } sum.a = alpha; tmp.SetPixel(x, y, sum); } } // Apply changes texture = tmp; }
public static void Swirl(SS_Texture texture, int aX, int aY, int radius, float twists) { SS_Texture tmpTexture = new SS_Texture(texture.Width, texture.Height, Color.clear); for (int y = 0; y < texture.Height; y++) { for (int x = 0; x < texture.Width; x++) { // compute the distance and angle from the swirl center: int pixelX = x - aX; int pixelY = y - aY; float pixelDistance = Mathf.Sqrt((pixelX * pixelX) + (pixelY * pixelY)); float pixelAngle = Mathf.Atan2(pixelY, pixelX); // work out how much of a swirl to apply (1.0 in the center fading out to 0.0 at the radius): float swirlAmount = 1.0f - (pixelDistance / radius); if (swirlAmount > 0.0f) { float twistAngle = twists * swirlAmount * Mathf.PI * 2.0f; // adjust the pixel angle and compute the adjusted pixel co-ordinates: pixelAngle += twistAngle; pixelX = (int)(Mathf.Cos(pixelAngle) * pixelDistance); pixelY = (int)(Mathf.Sin(pixelAngle) * pixelDistance); } // read and write the pixel tmpTexture.SetPixel(x, y, texture.GetPixel(aX + pixelX, aY + pixelY)); } } texture.SetPixels(tmpTexture.GetPixels()); }
public static void Polygon(SS_Texture texture, SS_Point[] points, bool fill, Color outlineColor, Color fillColor) { SS_Point p, p2; // Loop through all SS_Points and draw lines between them except for the last one for (int i = 0; i < points.Length - 1; i++) { p = new SS_Point((short)points[i].x, (short)points[i].y); p2 = new SS_Point((short)points[i + 1].x, (short)points[i + 1].y); Line(texture, p.x, p.y, p2.x, p2.y, outlineColor); } // Last SS_Point connects to first SS_Point (order is important) p = new SS_Point((short)points[0].x, (short)points[0].y); p2 = new SS_Point((short)points[points.Length - 1].x, (short)points[points.Length - 1].y); Line(texture, p.x, p.y, p2.x, p2.y, outlineColor); if (fill) { SS_Point centroid = SS_Utilities.Centroid(points); FloodFillArea(texture, centroid, fillColor); } }
// Generate a generally boring metallic-like texture (ships and stations use this) public static SS_Texture GenerateBaseTexture(int seed, int textureWidth, int textureHeight, int detail) { SS_Texture tmpTexture = new SS_Texture(textureWidth, textureHeight, Color.clear); Perlin noise = new Perlin(0.005, 2, 0.5, 6, seed, QualityMode.Low); int offsetX = tmpTexture.Width / detail; int offsetY = tmpTexture.Height / detail; for (int y = 0; y < tmpTexture.Height; y += offsetY) { for (int x = 0; x < tmpTexture.Width; x += offsetX) { float n1 = (float)noise.GetValue(x, y, 0); n1 = (n1 + 3.0f) * 0.25f; n1 = Mathf.Clamp(n1, 0.5f, 1f); float n2 = (float)noise.GetValue(x, y, 0); n2 = (n2 + 3.0f) * 0.25f; n2 = Mathf.Clamp(n2, 0.95f, 1f); Color c = new Color(n1, n1, n1, 1f); SS_Drawing.RectangleFill(tmpTexture, x, y, offsetX, offsetY, c, c); Color current = tmpTexture.GetPixel(x, y); Color c3 = new Color(current.r * n2, current.g * n2, current.b * n2); SS_Drawing.Line(tmpTexture, x, y, x, y + detail, c3); SS_Drawing.Line(tmpTexture, x, y, x + detail, y, c3); } } return(tmpTexture); }
void CreateFlare(SS_Texture texture, SS_Point lightPoint, int radius, bool customTint, Color tint) { Color flareColor = tint; if (!customTint) { flareColor = new Color(random.Range(0f, 1f), random.Range(0f, 1f), random.Range(0f, 1f)); } int hRad = radius / 2; int xMin = lightPoint.x - hRad; int yMin = lightPoint.y - hRad; int xMax = lightPoint.x + hRad; int yMax = lightPoint.y + hRad; for (int y = yMin; y < yMax; y++) { for (int x = xMin; x < xMax; x++) { float distance = SS_Point.Distance(lightPoint, new SS_Point(x, y)); if (distance < hRad) { Color c = SS_Utilities.Blend(flareColor, texture.GetPixel(x, y), 1.0f - ((distance - 0) / (hRad - 0))); if (texture.GetPixel(x, y).a == 0f) { c.a = 1f; } texture.SetPixel(x, y, c); } } } }
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); } } } }
public static void LineThick(SS_Texture texture, SS_Point start, SS_Point end, int width, Color outlineColor, Color fillColor) { SS_Texture tmpTexture = new SS_Texture(texture.Width, texture.Height, Color.clear); SS_Point[] points = new SS_Point[4]; float angle = Mathf.Atan2(end.y - start.y, end.x - start.x) * Mathf.Rad2Deg; points[0] = new SS_Point( (int)(start.x + Mathf.Cos((angle - 90f) * Mathf.Deg2Rad) * (width / 2)), (int)(start.y + Mathf.Sin((angle - 90f) * Mathf.Deg2Rad) * (width / 2))); points[1] = new SS_Point( (int)(start.x + Mathf.Cos((angle + 90f) * Mathf.Deg2Rad) * (width / 2)), (int)(start.y + Mathf.Sin((angle + 90f) * Mathf.Deg2Rad) * (width / 2))); points[2] = new SS_Point( (int)(end.x + Mathf.Cos((angle + 90f) * Mathf.Deg2Rad) * (width / 2)), (int)(end.y + Mathf.Sin((angle + 90f) * Mathf.Deg2Rad) * (width / 2))); points[3] = new SS_Point( (int)(end.x + Mathf.Cos((angle - 90f) * Mathf.Deg2Rad) * (width / 2)), (int)(end.y + Mathf.Sin((angle - 90f) * Mathf.Deg2Rad) * (width / 2))); LineStripClosed(tmpTexture, points, outlineColor); FloodFillArea(tmpTexture, SS_Utilities.Centroid(points), fillColor); MergeColors(texture, tmpTexture, 0, 0); }
private void CreateWeapon(SS_Texture targetTexture, SS_Point offset, Color baseColor) { // Temporary texture SS_Texture tmpTexture = new SS_Texture(Size, Size, Color.clear); // Keeping the weapons very simple for now // Just draw 4 layers of lines to create the weapon shape (rectangle) for (int y = offset.y - 2; y < offset.y + 2; y++) { int xEnd = offset.x + 8; if (xEnd > Size - 1) { xEnd = Size - 1; } SS_Drawing.Line(tmpTexture, offset.x, y, xEnd, y, baseColor); } // Create Weapon Points WeaponPoint.Add(new SS_Point(offset.x + 8, offset.y)); SS_Drawing.Outline(tmpTexture, SS_StellarSprite.OutlineColor); //Texturize but dont shade (more vibrant) if (!DebugDrawing) { Texturize(tmpTexture, SS_StellarSprite.FillColor, baseColor, false, false); } SS_Drawing.MergeColors(targetTexture, tmpTexture, 0, 0); }
// Darken any pixels next the black borders public static void ShadeEdge(SS_Texture texture) { Color[] tmpColors = new Color[texture.Width * texture.Height]; for (int y = 0; y < texture.Height; y++) { for (int x = 0; x < texture.Width; x++) { tmpColors[x + y * texture.Width] = texture.GetPixel(x, y); } } for (int y = 1; y < texture.Height - 1; y++) { for (int x = 1; x < texture.Width - 1; x++) { Color c = texture.GetPixel(x, y); if (c != Color.clear && c != Color.black) { Color tL = texture.GetPixel(x - 1, y - 1); Color tM = texture.GetPixel(x, y - 1); Color tR = texture.GetPixel(x + 1, y - 1); Color mL = texture.GetPixel(x - 1, y); Color mR = texture.GetPixel(x + 1, y); Color bL = texture.GetPixel(x - 1, y + 1); Color bM = texture.GetPixel(x, y + 1); Color bR = texture.GetPixel(x + 1, y + 1); if ((tL == Color.black || tM == Color.black || tR == Color.black || mL == Color.black || mR == Color.black || bL == Color.black || bM == Color.black || bR == Color.black)) { c.r *= 0.5f; c.g *= 0.5f; c.b *= 0.5f; tmpColors[x + y * texture.Width] = c; } } } } for (int x = 0; x < texture.Width; x++) { if (texture.GetPixel(x, 0) != Color.clear) { texture.SetPixel(x, 0, Color.black); } if (texture.GetPixel(x, texture.Height - 1) != Color.clear) { texture.SetPixel(x, texture.Height - 1, Color.black); } } texture.SetPixels(tmpColors); }
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); }
public SS_Moon(int seed, int size, float frequency, float lacunarity, int octaves, float roughness, Color[] colors, float lightAngle) { Seed = seed; Size = size; Sprite = new SS_Texture(size, size, Color.clear); gradientColors = SS_Utilities.CreateGradient(colors, 16, 32); Perlin shapeNoise = new Perlin(0.01, 2, 0.5, 8, seed, QualityMode.High); RidgedMultifractal noise = new RidgedMultifractal(frequency, lacunarity, octaves, seed, QualityMode.Low); Vector2 lightPosition = new Vector2( Sprite.Center.x + (Mathf.Cos(lightAngle * Mathf.Deg2Rad) * (Size / 4)), Sprite.Center.y + (Mathf.Sin(lightAngle * Mathf.Deg2Rad) * (Size / 4))); for (int y = 0; y < Size; y++) { for (int x = 0; x < Size; x++) { float dist = Vector2.Distance(new Vector2(x, y), new Vector2(Sprite.Center.x, Sprite.Center.y)); float edgeNoise = (float)shapeNoise.GetValue(x, y, 0); edgeNoise = (edgeNoise + 1.0f) * 0.5f; edgeNoise = Mathf.Clamp(edgeNoise, 0f, 1f); edgeNoise *= (8 * roughness); if (dist < (Size / 2) - edgeNoise) { float pixelNoise = (float)noise.GetValue(x, y, 0); pixelNoise = (pixelNoise + 1.0f) * 0.5f; pixelNoise = Mathf.Clamp(pixelNoise, 0f, 1f); float n = pixelNoise * (gradientColors.Length - 1); // Generate color and noise so land doesn't look to smooth Color pixelColor = gradientColors[(int)n]; pixelColor.a = 1.0f; Sprite.SetPixel(x, y, pixelColor); // Shadow float lightDistance = Vector2.Distance(new Vector2(x, y), lightPosition); lightDistance = 1.25f - (lightDistance / (Size / 2)); if (lightDistance < 0.025f) { lightDistance = 0.025f; } pixelColor.r *= lightDistance; pixelColor.g *= lightDistance; pixelColor.b *= lightDistance; Sprite.SetPixel(x, y, pixelColor); } } } }
public SS_Ship(int seed, SS_ShipType shipType, float bodyDetail, int bodyLength, float wingDetail, Color[] colors, float colorDetail) { Seed = seed; ColorBase = colors[0]; ColorHighlight = colors[1]; ColorEngine = colors[2]; BodyDetail = bodyDetail; BodyLength = bodyLength; WingDetail = wingDetail; ColorDetail = colorDetail; Sprite = new SS_Texture(Size, Size, Color.clear); random = new SS_Random(Seed); // generate ship based on type if (shipType == SS_ShipType.Fighter) { CreateWing(Sprite, Color.grey, random.NextBool()); CreateBody(Sprite, SS_ShipBody.Human, bodyLength, random.Range(0, 4), random.NextBool()); CreateEngine(Sprite, random.Range(1, 6)); CreateTank(Sprite, random.Range(1, 6), Color.grey, random.NextBool()); CreateWing(Sprite, Color.grey, random.NextBool()); CreateCockpit(Sprite, Color.cyan); } else if (shipType == SS_ShipType.Fighter2) { CreateWing(Sprite, Color.grey, random.NextBool()); CreateWing(Sprite, Color.grey, random.NextBool()); CreateBody(Sprite, SS_ShipBody.Human, bodyLength, random.Range(0, 4), random.NextBool()); CreateEngine(Sprite, random.Range(1, 4)); CreateTank(Sprite, random.Range(1, 4), Color.grey, random.NextBool()); CreateWing(Sprite, Color.grey, random.NextBool()); CreateWing(Sprite, Color.grey, random.NextBool()); CreateCockpit(Sprite, Color.cyan); } else if (shipType == SS_ShipType.Hauler) { CreateBody(Sprite, SS_ShipBody.Human, bodyLength, random.Range(0, 4), random.NextBool()); CreateEngine(Sprite, random.Range(1, 4)); CreateTank(Sprite, 2, Color.grey, random.NextBool()); CreateCockpit(Sprite, Color.cyan); } else if (shipType == SS_ShipType.Saucer) { BodyLength = 48; //CreateWing(Sprite, Color.grey, random.NextBool()); CreateBody(Sprite, SS_ShipBody.Alien, bodyLength, random.Range(0, 4), random.NextBool()); //CreateTank(Sprite, 1, Color.grey, random.NextBool()); //CreateWing(Sprite, Color.grey, random.NextBool()); } }
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); }
private static void Rectangle(SS_Texture texture, int aX, int aY, int aW, int aH, bool fill, Color color, Color fillColor) { Line(texture, aX, aY, aX + aW, aY, color); Line(texture, aX + aW, aY, aX + aW, aY + aH, color); Line(texture, aX, aY + aH, aX + aW, aY + aH, color); Line(texture, aX, aY, aX, aY + aH, color); if (fill) { FloodFillArea(texture, new SS_Point(aX + (aW / 2), aY + (aH / 2)), fillColor); } }
public static void LineStrip(SS_Texture texture, SS_Point[] SS_Points, Color color) { SS_Point p, p2; // Loop through all SS_Points and draw lines between them except for the last one for (int i = 0; i < SS_Points.Length - 1; i++) { p = new SS_Point((short)SS_Points[i].x, (short)SS_Points[i].y); p2 = new SS_Point((short)SS_Points[i + 1].x, (short)SS_Points[i + 1].y); Line(texture, p.x, p.y, p2.x, p2.y, color); } }
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 static void Mirror(SS_Texture texture, SS_Mirror location) { // Mirror top right horizontally and vertically if (location == SS_Mirror.TopRight) { // Vertical for (int y = (texture.Height / 2); y < texture.Height; y++) { for (int x = texture.Width / 2; x < texture.Width; x++) { Color target = texture.GetPixel(x, y); if (target != Color.clear) { int y1 = texture.Height - y - 1; texture.SetPixel(x, y1, texture.GetPixel(x, y)); } } } // Horizontal for (int y = 0; y < texture.Height; y++) { for (int x = (texture.Width / 2); x < texture.Width; x++) { Color target = texture.GetPixel(x, y); if (target != Color.clear) { int x1 = texture.Width - x - 1; texture.SetPixel(x1, y, texture.GetPixel(x, y)); } } } } else if (location == SS_Mirror.Vertical) { // Vertical for (int y = (texture.Height / 2); y < texture.Height; y++) { for (int x = 0; x < texture.Width; x++) { Color target = texture.GetPixel(x, y); if (target != Color.clear) { int y1 = texture.Height - y - 1; texture.SetPixel(x, y1, texture.GetPixel(x, y)); } } } } }
public static void FloodFill(SS_Texture texture, SS_Point pt, Color targetColor, Color replacementColor) { targetColor = texture.GetPixel(pt.x, pt.y); if (targetColor == replacementColor) { return; } Stack <SS_Point> pixels = new Stack <SS_Point>(); pixels.Push(pt); while (pixels.Count != 0) { SS_Point temp = pixels.Pop(); int y1 = temp.y; while (y1 >= 0 && texture.GetPixel(temp.x, y1) == targetColor) { y1--; } y1++; bool spanLeft = false; bool spanRight = false; while (y1 < texture.Height && texture.GetPixel(temp.x, y1) == targetColor) { texture.SetPixel(temp.x, y1, replacementColor); if (!spanLeft && temp.x > 0 && texture.GetPixel(temp.x - 1, y1) == targetColor) { pixels.Push(new SS_Point(temp.x - 1, y1)); spanLeft = true; } else if (spanLeft && temp.x - 1 == 0 && texture.GetPixel(temp.x - 1, y1) != targetColor) { spanLeft = false; } if (!spanRight && temp.x < texture.Width - 1 && texture.GetPixel(temp.x + 1, y1) == targetColor) { pixels.Push(new SS_Point(temp.x + 1, y1)); spanRight = true; } else if (spanRight && temp.x < texture.Width - 1 && texture.GetPixel(temp.x + 1, y1) != targetColor) { spanRight = false; } y1++; } } }
public static SS_Texture ColorWheel() { int padding = 0; int inner_radius = 0; int outer_radius = inner_radius + 128; int bmp_width = (2 * outer_radius) + (2 * padding); int bmp_height = bmp_width; SS_Texture spriteTexture = new SS_Texture(bmp_width, bmp_height, Color.black); var center = new Vector2(bmp_width / 2, bmp_height / 2); var c = Color.red; for (int y = 0; y < bmp_width; y++) { int dy = ((int)center.y - y); for (int x = 0; x < bmp_width; x++) { int dx = ((int)center.x - x); double dist = Mathf.Sqrt(dx * dx + dy * dy); if (dist >= inner_radius && dist <= outer_radius) { double theta = Mathf.Atan2(dy, dx); // theta can go from -pi to pi double hue = (theta + Mathf.PI) / (2 * Mathf.PI); double dr, dg, db; const double sat = 1.0; const double val = 1.0; HSVToRGB(hue, sat, val, out dr, out dg, out db); dr *= 0.75; dg *= 0.75; db *= 0.75; c = new Color((float)dr, (float)dg, (float)db); // Set spriteTexture.SetPixel(x, y, c); } } } return(spriteTexture); }
public static void Outline(SS_Texture spriteTexture, Color outlineColor) { for (int y = 1; y < spriteTexture.Height - 1; y++) { for (int x = 1; x < spriteTexture.Width - 1; x++) { Color c = spriteTexture.GetPixel(x, y); if (c != Color.clear) { Color tL = spriteTexture.GetPixel(x - 1, y - 1); Color tM = spriteTexture.GetPixel(x, y - 1); Color tR = spriteTexture.GetPixel(x + 1, y - 1); Color mL = spriteTexture.GetPixel(x - 1, y); Color mR = spriteTexture.GetPixel(x + 1, y); Color bL = spriteTexture.GetPixel(x - 1, y + 1); Color bM = spriteTexture.GetPixel(x, y + 1); Color bR = spriteTexture.GetPixel(x + 1, y + 1); if (tL == Color.clear || tM == Color.clear || tR == Color.clear || mL == Color.clear || mR == Color.clear || bL == Color.clear || bM == Color.clear || bR == Color.clear) { spriteTexture.SetPixel(x, y, outlineColor); } } } } for (int y = 0; y < spriteTexture.Height; y++) { for (int x = 0; x < spriteTexture.Width; x++) { Color c = spriteTexture.GetPixel(x, y); if (c != Color.clear) { if (x == 0 || x == spriteTexture.Width - 1 || y == 0 || y == spriteTexture.Height - 1) { spriteTexture.SetPixel(x, y, outlineColor); } } } } }
private static void Ellipse(SS_Texture texture, int x, int y, int rW, int rH, int resolution, bool fill, Color colorOutline, Color colorFill) { SS_Point[] positions = new SS_Point[resolution + 1]; for (int i = 0; i <= resolution; i++) { float angle = (float)i / (float)resolution * 2.0f * Mathf.PI; positions[i] = new SS_Point(x + ((short)(rW * Mathf.Cos(angle))), y + ((short)(rH * Mathf.Sin(angle)))); } Polygon(texture, positions, colorOutline); if (fill) { FloodFillArea(texture, new SS_Point(x, y), colorFill); } }
public SS_Starfield(int seed, int size, int starCount) { // Create sprite texture Sprite = new SS_Texture(size, size, Color.clear); // Random generator SS_Random random = new SS_Random(seed); // Create point stars for (int i = 0; i < starCount; i++) { int x = random.Range(0, size - 1); int y = random.Range(0, size - 1); Sprite.SetPixel(x, y, new Color(1f, 1f, 1f, random.Range(0.5f, 1.0f))); } }
public SS_Background(int seed, int size, SS_NoiseGenerator backgroundNoise, double frequency, double lacunarity, double persistence, int octaves, Color tint, float brightness) { // Create sprite texture Sprite = new SS_Texture(size, size, Color.white); // Initialize noise with parameters ModuleBase myModule; if (backgroundNoise == SS_NoiseGenerator.Perlin) { Perlin perlin = new Perlin(frequency, lacunarity, persistence, octaves, seed, QualityMode.Low); myModule = perlin; } else { RidgedMultifractal ridgedMultifractal = new RidgedMultifractal(frequency, lacunarity, octaves, seed, QualityMode.Low); myModule = ridgedMultifractal; } // Create seemless tiling noise Noise2D noise = new Noise2D(size, size, myModule); noise.GeneratePlanar(0, size, 0, size, false); // Get noise data float[,] noiseData = noise.GetNormalizedData(false, 0, 0); // Create cloud for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { float n = noiseData[y, x];; Color pixelColor = tint * n * brightness; pixelColor.a = ((pixelColor.r + pixelColor.g + pixelColor.b) / 3.0f); Sprite.SetPixel(x, y, pixelColor); } } }
public static Color[] GenerateColorWheelColors(int seed, int count) { SS_Texture colorWheel = ColorWheel(); Color[] colors = new Color[count]; SS_Random random = new SS_Random(seed); float angle = random.Range(0f, 360f); for (int i = 0; i < count; i++) { float xPos = (colorWheel.Width / 2) + Mathf.Cos(angle) * 32; float yPos = (colorWheel.Height / 2) + Mathf.Sin(angle) * 32; colors[i] = colorWheel.GetPixel((int)xPos, (int)yPos); angle += 360 / count; } return(colors); }
public static void MergeColors(SS_Texture target, SS_Texture source, int xOffset, int yOffset) { int x1 = xOffset; int y1 = yOffset; int x2 = 0; int y2 = 0; for (int y = y1; y < y1 + source.Height; y++) { x2 = 0; for (int x = x1; x < x1 + source.Width; x++) { Color c = source.GetPixel(x2, y2); if (c != Color.clear) { target.SetPixel(x, y, c); } x2++; } y2++; } }
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); }
public SS_Blackhole(int seed, int size) { Seed = seed; Size = size; Sprite = new SS_Texture(Size, Size, Color.clear); SS_Random random = new SS_Random(Seed); float radius = Size * 0.75f; float atmosphereThickness = Size * 0.125f; for (int y = 0; y < Size; y++) { for (int x = 0; x < Size; x++) { //float dist = Vector2.Distance(new Vector2(x, y), new Vector2(sprite.Center.x, sprite.Center.y)); int dist = SS_Point.Distance(new SS_Point(x, y), Sprite.Center); if (dist <= (radius / 2)) { Sprite.SetPixel(x, y, Color.black); } // Create "glow" Color currentPixel = Sprite.GetPixel(x, y); Color atmosphereColor = Color.black; if (currentPixel == Color.clear) { atmosphereColor.a = 1; //float distToEdge = Vector2.Distance(new Vector2(x, y), new Vector2(sprite.Center.x, sprite.Center.y)); int distToEdge = SS_Point.Distance(new SS_Point(x, y), Sprite.Center); if (distToEdge < (radius / 2) + atmosphereThickness && distToEdge > (radius / 2)) { float dist2 = dist - (radius / 2); atmosphereColor.a = (atmosphereThickness - dist2) / atmosphereThickness;; Sprite.SetPixel(x, y, atmosphereColor); } } } } // Calculate the number of light points around the even horizon based on the square root of the size halfed. int lightSpecCount = (int)(Mathf.Sqrt(Size) / 2) * Size; // Create specs of light around event horizon for (int i = 0; i < lightSpecCount; i++) { int a = random.Range(0, 359); int dist = (short)random.Range(radius * 0.25f, radius * 0.65f); int x = Sprite.Center.x + (int)(Mathf.Cos(a * Mathf.Deg2Rad) * dist); int y = Sprite.Center.y + (int)(Mathf.Sin(a * Mathf.Deg2Rad) * dist); SS_Point p = new SS_Point(x, y); int distToCenter = SS_Point.Distance(p, Sprite.Center); float v = 1 - (distToCenter / radius); Color c = new Color(v, v, v); Sprite.SetPixel(x, y, c); } SS_Drawing.Swirl(Sprite, Sprite.Width / 2, Sprite.Height / 2, Sprite.Width / 2, 5f); for (int y = 0; y < Size; y++) { for (int x = 0; x < Size; x++) { float dist = Vector2.Distance(new Vector2(x, y), new Vector2(Sprite.Center.x, Sprite.Center.y)); if (dist > (radius * 0.25f)) { Color c = Sprite.GetPixel(x, y); c.a = 1 - (dist / (Size / 2)); Sprite.SetPixel(x, y, c); } } } SS_Drawing.Ellipse(Sprite, Sprite.Center.x, Sprite.Center.y, (int)(radius * 0.25), (int)(radius * 0.25), 32, Color.white); }
// Light pixels as they approach black borders public static void PixelLighting(SS_Texture texture, int x, int y, ref Color hullShade) { int Width = texture.Width; int Height = texture.Height; float eastShading = 1.5f; float westShading = 1.5f; float northShading = 1.5f; float southShading = 1.5f; int shadingThickness = 4; bool hasEastBorder = false; int cntr = 0; while (!hasEastBorder) { int currentX = x + cntr; if (currentX < 0) { currentX = 0; } if (currentX > Width - 1) { currentX = Width - 1; } Color shadingPixel = texture.GetPixel(currentX, y); if (shadingPixel == Color.black) { hasEastBorder = true; } cntr++; if (cntr > shadingThickness) { break; } } if (hasEastBorder) { hullShade *= eastShading; } bool hasWestBorder = false; cntr = 0; while (!hasWestBorder) { int currentX = x - cntr; if (currentX < 0) { currentX = 0; } if (currentX > Width - 1) { currentX = Width - 1; } Color shadingPixel = texture.GetPixel(currentX, y); if (shadingPixel == Color.black) { hasWestBorder = true; } cntr++; if (cntr > shadingThickness) { break; } } if (hasWestBorder) { hullShade *= westShading; } bool hasNorthBorder = false; cntr = 0; while (!hasNorthBorder) { int currentY = y - cntr; if (currentY < 0) { currentY = 0; } if (currentY > Height - 1) { currentY = Height - 1; } Color shadingPixel = texture.GetPixel(x, currentY); if (shadingPixel == Color.black) { hasNorthBorder = true; } cntr++; if (cntr > shadingThickness) { break; } } if (hasNorthBorder) { hullShade *= northShading; } bool hasSouthBorder = false; cntr = 0; while (!hasSouthBorder) { int currentY = y + cntr; if (currentY < 0) { currentY = 0; } if (currentY > Height - 1) { currentY = Height - 1; } Color shadingPixel = texture.GetPixel(x, currentY); if (shadingPixel == Color.black) { hasSouthBorder = true; } cntr++; if (cntr > shadingThickness) { break; } } if (hasSouthBorder) { hullShade *= southShading; } }