Meter mNoiseSpeed, mGrowthSpeed, mPoints, mNoiseRadius, mAnimRadius, mAnimSpeed;
ColorChooser chInnerHue, chOuterHue;
boolean showText = false;
colorMode(HSB, 360, 100, 100, 100);
background(0, 0, 0, 100);
bg = loadImage("bg1.png");
meters = new ArrayList<Meter>();
float meterY = meterRadius;
float meterX = meterRadius;
float mSpace = meterRadius * 0.5;
mNoiseSpeed = new Meter(meterX, meterY, meterRadius);
mNoiseSpeed.name = "NOISE\nSPEED";
mNoiseSpeed.value = b.noiseSpeed;
meterY += meterRadius + mSpace;
mNoiseRadius = new Meter(meterX, meterY, meterRadius);
mNoiseRadius.name = "NOISE\nRADIUS";
mNoiseRadius.value = b.noiseSpeed;
meters.add(mNoiseRadius);
meterY += meterRadius + mSpace;
mGrowthSpeed = new Meter(meterX, meterY, meterRadius);
mGrowthSpeed.name = "GROWTH\nSPEED";
mGrowthSpeed.value = b.growthSpeed;
meters.add(mGrowthSpeed);
meterY += meterRadius + mSpace;
mPoints = new Meter(meterX, meterY, meterRadius);
mPoints.value = b.points;
meterY += meterRadius + mSpace;
mAnimRadius = new Meter(meterX, meterY, meterRadius);
mAnimRadius.name = "ANIM\nRADIUS";
mAnimRadius.value = b.animSpeed;
meterY += meterRadius + mSpace;
mAnimSpeed = new Meter(meterX, meterY, meterRadius);
mAnimSpeed.name = "ANIM\nSPEED";
mAnimSpeed.value = b.animSpeed;
meterY += meterRadius + mSpace;
meterY += meterRadius + mSpace;
chInnerHue = new ColorChooser(meterX, meterY, meterRadius);
chInnerHue.name = "INNER\nHUE";
chInnerHue.value = b.innerHue;
meterY += meterRadius + mSpace;
chOuterHue = new ColorChooser(meterX, meterY, meterRadius);
chOuterHue.name = "OUTER\nHUE";
chOuterHue.value = b.outerHue;
meterY += meterRadius + mSpace;
image(bg, 0, 0, width, height);
if (showText) printBlobInfo(b);
if (showViz) visualizeAppearance(b);
if (showHUD) displayMeters();
rect(-5, -5, 155, height + 5);
if (mNoiseSpeed.changed) b.noiseSpeed = mNoiseSpeed.value;
if (mGrowthSpeed.changed) b.growthSpeed = mGrowthSpeed.value;
if (mPoints.changed) b.points = int(mPoints.value);
if (mNoiseRadius.changed) b.noiseRadius = int(mNoiseRadius.value);
if (mAnimRadius.changed) b.animRadius = int(mAnimRadius.value);
if (mAnimSpeed.changed) b.animSpeed = int(mAnimSpeed.value);
if (chInnerHue.changed) b.innerHue = chInnerHue.value;
if (chOuterHue.changed) b.outerHue = chOuterHue.value;
background(0, 0, 100, 100);
void visualizeAppearance(Blob b) {
float hWidth = vizWidth / 2;
translate(width - (hWidth + 30), hWidth + 30);
ellipse(0,0, vizWidth * 0.05, vizWidth * 0.05);
PVector animPos = new PVector();
float animR = map(b.animRadius, 0, 255, 0, hWidth);
animPos.x = cos(radians(b.animDegree)) * animR;
animPos.y = sin(radians(b.animDegree)) * animR;
float nrr = vizWidth * map(b.noiseRadius, 0, 255, 0.01, 0.06);
ellipse(0, 0, animR * 2, animR * 2);
ellipse(animPos.x, animPos.y, nrr, nrr);
line(0,0, animPos.x, animPos.y);
return String.format("%.4f", val);
PVector centerNoisePos, frameNoisePos;
float animRadius, animDegree;
float noiseRadius, noiseSpeed;
float growthSpeed, growthValue, growthCounter, blobRadius;
pos = new PVector(random(width), random(height));
blobRadius = height * 0.65;
centerNoisePos = new PVector(500, 400);
frameNoisePos = new PVector(0, 0);
frameNoisePos.x = centerNoisePos.x + cos(radians(animDegree)) * map(animRadius, 0, 255, 0, 4);
frameNoisePos.y = centerNoisePos.y + sin(radians(animDegree)) * map(animRadius, 0, 255, 0, 4);
while (growthCounter < PI) {
growthCounter += map(growthSpeed, 0, 255, 0.004, 0.05);
animDegree += map(animSpeed, 0, 255, 0, 2);
frameNoisePos.x += map(noiseSpeed, 0, 255, 0.001, 0.01);
growthValue = sin(growthCounter);
float shapeRadius = growthValue * blobRadius;
float arcR = TWO_PI / points;
PVector pointPos = new PVector();
stroke(lerpColor(innerColor, outerColor, growthValue));
for (int i = 0; i < points; i++) {
float noiseX = frameNoisePos.x + cos(i * arcR) * map(noiseRadius, 0, 255, 0.1, 1);
float noiseY = frameNoisePos.y + sin(i * arcR) * map(noiseRadius, 0, 255, 0.1, 1);
float noiseVal = noise(noiseX, noiseY);
float r = noiseVal * shapeRadius;
pointPos.x = cos(rad) * r;
pointPos.y = sin(rad) * r;
vertex(pointPos.x, pointPos.y);
void randomizeAppearance() {
points = int(random(32, 255));
growthSpeed = round(random(5, 100));
noiseSpeed = round(random(255));
noiseRadius = round(random(255));
centerNoisePos = new PVector(random(10000), random(10000));
frameNoisePos = new PVector(0, 0);
animRadius = round(random(255));
animSpeed = round(random(30, 150));
innerColor = color(innerHue, 100, 100, 5);
outerColor = color(outerHue, 50, 50, 10);
String blobName = "x" + fd(b.centerNoisePos.x) + "y" + fd(b.centerNoisePos.y);
blobName += "gs" + fd(b.growthSpeed) + "ns" + fd(b.noiseSpeed) + "nr" + fd(b.noiseRadius);
blobName += "ar" + fd(b.animRadius);
blobName = blobName.replace('.', '-');
blobName = blobName.replace(',', '-');
PVector size= new PVector(width / 2, height /2);
fill(buttonHue, 50, 50, 100);
class ColorChooser extends Meter {
ColorChooser(float _x, float _y, float _r) {
PVector mousePos = new PVector(mouseX, mouseY);
if (mousePos.dist(pos) < radius / 2 && mousePressed) {
if (!active && activeMeter == null) activate();
value += (mouseX - pmouseX) + (pmouseY - mouseY);
value = constrain(value, 0, maxVal);
color fColor = color(value, 70, 100, 100);
ellipse(0, 0, radius, radius);
float end = start + (value / maxVal) * 360;
arc(0, 0, radius - 1, radius - 1, radians(start), radians(end));
for (int i = 0; i < seg; i++) {
degree = start + (360 / seg) * i;
float endX = cos(radians(degree)) * (radius - 1) / 2;
float endY = sin(radians(degree)) * (radius - 1) / 2;
ellipse(0, 0, radius * (1 - thickness), radius * (1 - thickness));
PVector pos = new PVector();
color bgColor = color(0, 0, 70, 100);
color mColor = color(200, 50, 100, 100);
color aColor = color(100, 100, 100, 100);
Meter(float _x, float _y, float _r) {
PVector mousePos = new PVector(mouseX, mouseY);
if (mousePos.dist(pos) < radius / 2 && mousePressed) {
if (!active && activeMeter == null) activate();
value += (mouseX - pmouseX) + (pmouseY - mouseY);
value = constrain(value, 0, maxVal);
ellipse(0, 0, radius, radius);
fill(map(value, 0, 255, 220, 200), 30, 100, 100);
float end = start + (value / maxVal) * 360;
arc(0, 0, radius - 1, radius - 1, radians(start), radians(end));
ellipse(0, 0, radius * (1 - thickness), radius * (1 - thickness));
for (int i = 0; i < seg; i++) {
degree = start + (360 / seg) * i;
float endX = cos(radians(degree)) * (radius - 1) / 2;
float endY = sin(radians(degree)) * (radius - 1) / 2;
text(name, radius * 0.8, 0);