Eclipse – How to simulate nature with code

In my last post, I shared how something as simple as a crack in a sidewalk can be the inspiration for a variety of artistic interpretations. One of those was using code to generate cracks and then having that evolve into what began to look like an eclipse. That idea continued to evolve to the point that it is now available for you to explore on your own here. What’s great about code generated art is that you can create a variety of unexpected results simply by changing a few parameters. See some of the examples below. Keep reading to learn more about how to use Eclipse and how I created it.

How to Use it

Eclipse works by generating random cracks around a circle. By changing any or all of the sliders, you can alter all aspects of how the cracks are generated. You can change everything from the number and size of the cracks to the color and transparency. See below for an explanation of each slider. Click here to try it out (works best on a PC/Mac).

  • Max Life: Ultimately determines the length of each crack. The longer the life, the longer the crack and the greater chance for additional branching.
  • Seg Size: While life is about how long the crack grows, segment size has the biggest impact on the length. The bigger the size of the segment, the faster the crack grows.
  • Num Points: This determines how many crack origination points will be generated on the circle. Setting it low gives the impression of a random solar flare.
  • Num Cracks: Each “crack”  can actually be composed of 1 or more cracks. Increasing this and/or Branch Factor will generate more complex cracks.
  • Branch Factor: Determines how often a crack will branch during its lifetime.
  • Thickness: Determines the starting thickness of a crack. The crack naturally gets thinner as it dies out. 
  • Alpha: Lower = more transparent, Higher = less transparent. 100 = Opaque. Using lower values combined with toggling Clearscreen (C key) can generate interesting artistic effects.
  • Framerate: Higher numbers generates a new image more often.
  • Hue: Changes the color of the cracks
  • Saturation: Changes the intensity of the color
  • Radius: Changes the size of the circle (sun or moon)
  • Jagginess: Higher numbers result in more complex cracks (jaggier lines)

.There are also 4 “hot keys” 

  • N: Toggles between eclipse mode and sun mode. In eclipse mode, the circle is filled with black to simulate an eclipse. In sun mode, the circle is filled with white or the chosen color.
  • C: “Clearscreen” – toggles between clearing the screen after each frame is drawn or continuing to add to the existing drawing. 
  • P: “Pause” – pauses the creation. This is useful if you want to save the image.
  • S: “Save” – click to save and download an image to your PC/Mac.

How it Works

As mentioned in my previous post, the core of this program is based on a p5.js Crack class suggested by ChatGPT after a few iterations. It generates cracks by “growing” line segments over time by calling the update() method within the class. Additional branches are created occasionally using a simple random function. I modified this core class to parameterize several of the elements. 

				
					// Crack class to handle growth and branching
class Crack {
constructor(x, y, angle, thickness, lifetime, segsize) {
    this.x = x;
    this.y = y;
    this.angle = angle;
    this.lifetime = lifetime; // Limit how long the crack grows
    this.maxlife = lifetime;
    this.thickness = thickness;
    this.segsize = segsize;
  }

grow() {
    if (this.lifetime <= 0) return true;

    // Move in the current direction
    let newX = this.x + cos(this.angle) * this.segsize;
    let newY = this.y + sin(this.angle) * this.segsize;

    // Draw the crack
    stroke(drawHue, drawSat,255,alpha);
    let crackThickness = map(this.lifetime, this.maxlife, 0, this.thickness, 0.5);
    strokeWeight(crackThickness); // Tapering effect
    line(this.x, this.y, newX, newY);

    // Update position
    this.x = newX;
    this.y = newY;

    // Occasionally branch
    if (random() < branchfactor) {
    cracks.push(new Crack(this.x, this.y, this.angle + random(-PI / 4, PI / 4),crackThickness, this.maxlife*.4,this.segsize));
    }

    // Occasionally change direction slightly
    this.angle += random(-PI / jagginess, PI / jagginess);

    // Stop growing if out of bounds or too short-lived
    if (this.x < 0 || this.x > width || this.y < 0 || this.y > height) {
    this.lifetime = 0;
    }

    this.lifetime--;
    return false;
  }
}
				
			

One of the limitations of the ChatGpt code was that the Crack update() method was called forever, even when lifetime had elapsed. To make things more flexible and allow me to generate cracks wherever and whenever I wanted, I created a “crackPoint” function which would generate a crack from a given point and return once the lifetime was over.

				
					//creates and grows cracks from a point until all growth has stopped
function crackPoint (xpos,ypos,thickness,lifetime, segsize) {
    for (let i = 0; i < numCracks; i++) {
      cracks.push(new Crack(xpos,ypos, random(TWO_PI), thickness, lifetime,segsize));
    }
    while (cracks.length > 0) {
      // Iterate from the end towards the beginning to allow removal of dead cracks
      for (let i = cracks.length - 1; i >= 0; i--) {
        dead = cracks[i].grow();
        if (dead) {
          cracks.splice(i, 1); // Safely remove inactive objects
        }
      }
    }
  }
				
			

One of the enhancements I mentioned in the previous post was to start the cracks from points on a circle instead of randomly on the screen. I tend to use circles in my generative art and thought this would be interesting to see what it would create. Since I now had the abillity to generate cracks whenever and wherever I wanted, I simply created a routine to draw points on a circle and then, instead of creating a point, I call the crackPoint function.

				
					
function drawCircle() {
  
    // Circle parameters
    let centerX = width / 2;
    let centerY = height / 2;
    
    // Draw points on the circle
    for (let i = 0; i < numPoints; i++) {
        //let angle = TWO_PI / numPoints * i; // Calculate the angle for each point
        let angle = TWO_PI * random(); // Calculate the angle for each point
        let x = centerX + circleRadius * cos(angle); // Calculate x position
        let y = centerY + circleRadius * sin(angle); // Calculate y position
        crackPoint(x,y,thickness,maxlife,segsize);
    }
    if (sun) {
      fill('White');
    } else {
      fill('Black');
    }
    stroke('White');
    strokeWeight(1);
    ellipse(centerX, centerY,circleRadius*2);
}
				
			

And that’s pretty much it. The rest of the code includes functions to create and update sliders and to handle the hot keys. 

As you can see, you can generate all types of images, so feel free to play around and save your own images. Let me know your thoughts iand share you favorite images in the comments!

To see more of my code generated art, check out my portfolio page

Share This Post

1 thought on “Eclipse – How to simulate nature with code”

Leave a Comment

Your email address will not be published. Required fields are marked *

More To Explore