using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using SDL2; namespace SDL2Demo.Screenhacks.Complexification { [ScreenHackId(2)] internal class Substrate : Processing { int dimx = 250; int dimy = 250; int num = 0; int maxnum = 100; // grid of cracks int[] cgrid; Crack[] cracks; // color parameters int maxpal = 512; int numpal = 0; private Color[] goodcolor; // sand painters SandPainter[] sands; protected override void Init() { goodcolor = new Color[maxpal]; //Background(Color.FromArgb(255, 255, 255, 255)); TakeColor(); dimx = windowRectangle.Width; dimy = windowRectangle.Height; cgrid = new int[dimx * dimy]; cracks = new Crack[maxnum]; Begin(); } private void Begin() { // erase crack grid for (int y = 0; y < dimy; y++) { for (int x = 0; x < dimx; x++) { cgrid[y * dimx + x] = 10001; } } // make random crack seeds for (int k = 0; k < 16; k++) { int i = (Random(dimx * dimy - 1)); cgrid[i] = (Random(360)); } // make just three cracks num = 0; for (int k = 0; k < 3; k++) { MakeCrack(); } //Background(Color.FromArgb(255, 255, 255, 255)); } private void MakeCrack() { if (num < maxnum) { // make a new crack instance cracks[num] = new Crack(this); num++; } } private void TakeColor() { uint[] srcArrays = { 0x201F21, 0x262C2E, 0x352626, 0x372B27, 0x302C2E, 0x392B2D, 0x323229, 0x3F3229, 0x38322E, 0x2E333D, 0x333A3D, 0x473329, 0x40392C, 0x40392E, 0x47402C, 0x47402E, 0x4E402C, 0x4F402E, 0x4E4738, 0x584037, 0x65472D, 0x6D5D3D, 0x745530, 0x755532, 0x745D32, 0x746433, 0x7C6C36, 0x523152, 0x444842, 0x4C5647, 0x655D45, 0x6D5D44, 0x6C5D4E, 0x746C43, 0x7C6C42, 0x7C6C4B, 0x6B734B, 0x73734B, 0x7B7B4A, 0x6B6C55, 0x696D5E, 0x7B6C5D, 0x6B7353, 0x6A745D, 0x727B52, 0x7B7B52, 0x57746E, 0x687466, 0x9C542B, 0x9D5432, 0x9D5B35, 0x936B36, 0xAA7330, 0xC45A27, 0xD95223, 0xD85A20, 0xDB5A23, 0xE57037, 0x836C4B, 0x8C6B4B, 0x82735C, 0x937352, 0x817B63, 0x817B6D, 0x927B63, 0xD9893B, 0xE49832, 0xDFA133, 0xE5A037, 0xF0AB3B, 0x8A8A59, 0xB29A58, 0x89826B, 0x9A8262, 0x888B7C, 0x909A7A, 0xA28262, 0xA18A69, 0xA99968, 0x99A160, 0x99A168, 0xCA8148, 0xEB8D43, 0xC29160, 0xC29168, 0xD1A977, 0xC9B97F, 0xF0E27B, 0x9F928B, 0xC0B999, 0xE6B88F, 0xC8C187, 0xE0C886, 0xF2CC85, 0xF5DA83, 0xECDE9D, 0xF5D294, 0xF5DA94, 0xF4E784, 0xF4E18A, 0xF4E193, 0xE7D8A7, 0xF1D4A5, 0xF1DCA5, 0xF4DBAD, 0xF1DCAE, 0xF4DBB5, 0xF5DBBD, 0xF4E2AD, 0xF5E9AD, 0xF4E3BE, 0xF5EABE, 0xF7F0B6, 0xD9D1C1, 0xE0D0C0, 0xE7D8C0, 0xF1DDC6, 0xE8E1C0, 0xF3EDC7, 0xF6ECCE, 0xF8F2C7, 0xEFEFD0, 0 }; for (int i = 0; i < srcArrays.Length; i++) { srcArrays[i] |= 0xff000000; goodcolor[i] = Color.FromArgb((int)srcArrays[i]); } numpal = srcArrays.Length; } public override void MousePressed() { throw new NotImplementedException(); } public override void Dispose() { throw new NotImplementedException(); } public override void Render() { for (int n = 0; n < num; n++) { cracks[n].Move(); } SDL.SDL_Rect a = new SDL.SDL_Rect(); a.h = 16; a.w = 16; SDL.SDL_Rect b = new SDL.SDL_Rect(); b.h = 720; b.w = 1280; renderer.Copy(whiteBackground, ref a, ref b); renderer.Copy(_texture, topLeft); } class Crack { private readonly Substrate _parent; private float x, y, t; private SandPainter sp; public Crack(Substrate parent) { _parent = parent; FindStart(); sp = new SandPainter(_parent); } private void FindStart() { // pick random point int px = 0; int py = 0; // shift until crack is found bool found = false; int timeout = 0; while ((!found) || (timeout++ > 1000)) { px = (_parent.Random(_parent.dimx)); py = (_parent.Random(_parent.dimy)); if (_parent.cgrid[py * _parent.dimx + px] < 10000) { found = true; } } if (found) { // start crack int a = _parent.cgrid[py * _parent.dimx + px]; if (_parent.Random(100) < 50) { a -= 90 + (int)(_parent.Random(-2.0f, 2.1f)); } else { a += 90 + (int)(_parent.Random(-2.0f, 2.1f)); } StartCrack(px, py, a); } else { //println("timeout: "+timeout); } } private void StartCrack(int X, int Y, int T) { x = X; y = Y; t = T;//%360; x += 0.61f * (float)Math.Cos(t * Math.PI / 180.0); y += 0.61f * (float)Math.Sin(t * Math.PI / 180.0); } public void Move() { // continue cracking x += 0.42f * (float)Math.Cos(t * Math.PI / 180); y += 0.42f * (float)Math.Sin(t * Math.PI / 180); // bound check float z = 0.33f; int cx = (int)(x + _parent.Random(-z, z)); // add fuzz int cy = (int)(y + _parent.Random(-z, z)); // draw sand painter RegionColor(); // draw black crack _parent.Stroke(0.0f, 85.0f); _parent.Point(x + _parent.Random(-z, z), y + _parent.Random(-z, z)); if ((cx >= 0) && (cx < _parent.dimx) && (cy >= 0) && (cy < _parent.dimy)) { // safe to check if ((_parent.cgrid[cy * _parent.dimx + cx] > 10000) || (Math.Abs(_parent.cgrid[cy * _parent.dimx + cx] - t) < 5)) { // continue cracking _parent.cgrid[cy * _parent.dimx + cx] = (int)(t); } else if (Math.Abs(_parent.cgrid[cy * _parent.dimx + cx] - t) > 2) { // crack encountered (not self), stop cracking FindStart(); _parent.MakeCrack(); } } else { // out of bounds, stop cracking FindStart(); _parent.MakeCrack(); } } private void RegionColor() { // start checking one step away float rx = x; float ry = y; bool openspace = true; // find extents of open space while (openspace) { // move perpendicular to crack rx += 0.81f * (float)Math.Sin(t * Math.PI / 180.0); ry -= 0.81f * (float)Math.Cos(t * Math.PI / 180.0); int cx = (int)(rx); int cy = (int)(ry); if ((cx >= 0) && (cx < _parent.dimx) && (cy >= 0) && (cy < _parent.dimy)) { // safe to check if (_parent.cgrid[cy * _parent.dimx + cx] > 10000) { // space is open } else { openspace = false; } } else { openspace = false; } } // draw sand painter sp.Render(rx, ry, x, y); } } class SandPainter { private readonly Substrate _parent; public SandPainter(Substrate _parent) { this._parent = _parent; c = _parent.SomeColor(); g = _parent.Random(0.01f, 0.1f); } private Color c; private float g; public void Render(float x, float y, float ox, float oy) { // modulate gain g += _parent.Random(-0.050f, 0.050f); float maxg = 1.0f; if (g < 0) g = 0; if (g > maxg) g = maxg; // calculate grains by distance //int grains = (int)(Math.Sqrt((ox-x)*(ox-x)+(oy-y)*(oy-y))); int grains = 64; // lay down grains of sand (transparent pixels) float w = g / (grains - 1); for (int i = 0; i < grains; i++) { float a = 0.1f - i / (grains * 10.0f); _parent.Stroke(c.R, c.G, c.B, a * 256); _parent.Point(ox + (x - ox) * (float)Math.Sin(Math.Sin(i * w)), oy + (y - oy) * (float)Math.Sin(Math.Sin(i * w))); } } } private Color SomeColor() { return goodcolor[rng.Next(numpal)]; } } }