0x57ca1267…d46csent to0xf28f163e…abec·#23,914,722·view on Etherscan
ipfs://bafkreichumfgiuu75fwlpp6lj2n23dodhpa6a75vl42rhigjt2t2ankxculet dots = [];
let cycleStartTime = 0;
let cycleDuration = 5000;
let isWhitePhase = true;
let totalDotsNeeded = 50000;
let canvasSize = 0;
let centerX = 0;
let centerY = 0;
let petals = [];
let dotsInCurrentPhase = 0;
let dotsInsidePetals = 0;
let dotsRemovedOutside = 0;
let dotsRemovedInside = 0;
let initialWhiteDotsInside = 0;
let initialWhiteDotsOutside = 0;
let initialFillComplete = false;
let cycleCount = 0;
let isBlackout = false;
let blackoutStartDots = 0;
let blackoutRemoved = 0;
let dotSize = 2;
function generatePetals() {
petals = [];
let numLayers = floor(random(2, 5));
let innerRadius = canvasSize / 25;
let baseSpan = canvasSize * 0.05;
let maxOuterRadius = canvasSize * 0.475;
let basePetalWidth = canvasSize / 15;
let totalAvailableRadius = maxOuterRadius - innerRadius;
let currentRadius = innerRadius;
for (let layer = 0; layer < numLayers; layer++) {
let isOuterLayer = (layer === numLayers - 1);
let layerProgress = layer / (numLayers - 1);
let layerSpan = baseSpan * (1 + layerProgress * 2);
let layerInnerRadius = currentRadius;
let layerOuterRadius = layerInnerRadius + layerSpan;
if (isOuterLayer) {
layerOuterRadius = maxOuterRadius;
} else if (layerOuterRadius > maxOuterRadius) {
layerOuterRadius = maxOuterRadius;
}
let numPetals = floor(random(7, 14));
let angleStep = TWO_PI / numPetals;
let petalWidth = basePetalWidth * (1 + layer * 0.8);
for (let i = 0; i < numPetals; i++) {
let angle = i * angleStep + random(-angleStep * 0.1, angleStep * 0.1);
let offsetFactor = layer === 0 ? 0.2 : (layer === 1 ? 0.1 : 0.05);
let petalInnerRadius = layerInnerRadius + random(0, layerSpan * offsetFactor);
let petalOuterRadius;
if (isOuterLayer) {
let minOuter = maxOuterRadius * 0.85;
let maxOuter = maxOuterRadius;
petalOuterRadius = random(minOuter, maxOuter);
} else {
petalOuterRadius = layerOuterRadius - random(0, layerSpan * (offsetFactor * 0.75));
}
let width = petalWidth * random(0.8, 1.4);
let maxWidthRadius = 0.4 + random(-0.1, 0.1);
petals.push({
angle: angle,
innerRadius: petalInnerRadius,
outerRadius: petalOuterRadius,
width: width,
maxWidthRadius: maxWidthRadius
});
}
if (!isOuterLayer) {
let overlap = layerSpan * 0.3;
currentRadius = layerOuterRadius - overlap;
}
}
}
function getPetalWidthAtRadius(petal, radius) {
let normalizedRadius = (radius - petal.innerRadius) / (petal.outerRadius - petal.innerRadius);
if (normalizedRadius < 0 || normalizedRadius > 1) return 0;
let distanceFromMax = abs(normalizedRadius - petal.maxWidthRadius);
let widthFactor = 1 - (distanceFromMax / max(0.4, 1 - petal.maxWidthRadius));
widthFactor = pow(max(0, widthFactor), 1.5);
let taperFactor = 1 - pow(normalizedRadius, 1.8);
return petal.width * widthFactor * taperFactor;
}
function isPointInPetals(x, y) {
let dx = x - centerX;
let dy = y - centerY;
let distFromCenter = sqrt(dx * dx + dy * dy);
let angle = atan2(dy, dx);
if (angle < 0) angle += TWO_PI;
for (let petal of petals) {
if (distFromCenter < petal.innerRadius || distFromCenter > petal.outerRadius) {
continue;
}
let petalWidthAtRadius = getPetalWidthAtRadius(petal, distFromCenter);
if (petalWidthAtRadius <= 0) continue;
let angleDiff = abs(angle - petal.angle);
if (angleDiff > PI) angleDiff = TWO_PI - angleDiff;
let petalAngleWidth = petalWidthAtRadius / distFromCenter;
if (angleDiff <= petalAngleWidth * 0.5) {
return true;
}
}
return false;
}
function getRandomPositionInPetals() {
if (petals.length === 0) return null;
let petal = random(petals);
let attempts = 0;
while (attempts < 50) {
let radius = random(petal.innerRadius, petal.outerRadius);
let petalWidthAtRadius = getPetalWidthAtRadius(petal, radius);
if (petalWidthAtRadius <= 0) {
attempts++;
continue;
}
let angleOffset = random(-petalWidthAtRadius / (radius * 2), petalWidthAtRadius / (radius * 2));
let angle = petal.angle + angleOffset;
let testX = centerX + cos(angle) * radius;
let testY = centerY + sin(angle) * radius;
if (isPointInPetals(testX, testY)) {
return {
x: testX,
y: testY
};
}
attempts++;
}
return null;
}
function setup() {
canvasSize = min(windowWidth, windowHeight);
createCanvas(canvasSize, canvasSize);
centerX = width / 2;
centerY = height / 2;
dotSize = max(1, canvasSize / 500);
generatePetals();
background(0);
cycleStartTime = millis();
cycleCount = 0;
isBlackout = false;
blackoutStartDots = 0;
blackoutRemoved = 0;
dotsInCurrentPhase = 0;
dotsInsidePetals = 0;
dotsRemovedOutside = 0;
dotsRemovedInside = 0;
initialWhiteDotsInside = 0;
initialWhiteDotsOutside = 0;
initialFillComplete = false;
if (isWhitePhase) {
initialWhiteDotsInside = dots.filter(d => d.isInsidePetals && d.color === 255).length;
} else {
initialWhiteDotsOutside = dots.filter(d => !d.isInsidePetals && d.color === 255).length;
}
}
function draw() {
background(0);
let elapsed = millis() - cycleStartTime;
let progress = elapsed / cycleDuration;
if (progress >= 1.0) {
if (isBlackout) {
dots = [];
generatePetals();
cycleCount = 0;
isBlackout = false;
blackoutStartDots = 0;
blackoutRemoved = 0;
isWhitePhase = true;
dotsInCurrentPhase = 0;
dotsInsidePetals = 0;
dotsRemovedOutside = 0;
dotsRemovedInside = 0;
initialWhiteDotsInside = 0;
initialWhiteDotsOutside = 0;
initialFillComplete = false;
cycleStartTime = millis();
progress = 0;
} else {
cycleCount++;
if (cycleCount >= 2) {
isBlackout = true;
blackoutStartDots = dots.length;
blackoutRemoved = 0;
cycleStartTime = millis();
progress = 0;
} else {
if (isWhitePhase) {
for (let j = dots.length - 1; j >= 0; j--) {
if (dots[j].isInsidePetals && dots[j].color === 255) {
dots.splice(j, 1);
}
}
initialWhiteDotsOutside = dots.filter(d => !d.isInsidePetals && d.color === 255).length;
} else {
for (let j = dots.length - 1; j >= 0; j--) {
if (!dots[j].isInsidePetals && dots[j].color === 255) {
dots.splice(j, 1);
}
}
initialWhiteDotsInside = dots.filter(d => d.isInsidePetals && d.color === 255).length;
}
cycleStartTime = millis();
isWhitePhase = !isWhitePhase;
dotsInCurrentPhase = 0;
dotsInsidePetals = 0;
dotsRemovedOutside = 0;
dotsRemovedInside = 0;
progress = 0;
}
}
}
if (isBlackout) {
let targetProgress = progress * progress;
let targetRemoved = Math.round(blackoutStartDots * targetProgress);
let dotsToRemove = targetRemoved - blackoutRemoved;
let removed = 0;
let maxRemovals = Math.max(100, Math.min(400, dotsToRemove));
for (let i = 0; i < dotsToRemove && i < maxRemovals && removed < dots.length; i++) {
if (dots.length > 0) {
dots.splice(floor(random(dots.length)), 1);
blackoutRemoved++;
removed++;
}
}
} else {
if (dots.length >= totalDotsNeeded && !initialFillComplete) {
initialFillComplete = true;
}
let targetProgress = progress * progress;
let targetDots = Math.floor(totalDotsNeeded * targetProgress);
if (isWhitePhase) {
let dotsToAddOutside = 0;
let dotsToRemoveInside = 0;
if (!initialFillComplete) {
dotsToAddOutside = targetDots - dotsInCurrentPhase;
} else {
let targetRemoved = Math.round(initialWhiteDotsInside * targetProgress);
dotsToRemoveInside = targetRemoved - dotsRemovedInside;
dotsToAddOutside = dotsToRemoveInside;
}
if (initialFillComplete && dotsToRemoveInside > 0) {
let removedInside = 0;
let currentWhiteDotsInside = dots.filter(d => d.isInsidePetals && d.color === 255).length;
let maxRemovals = Math.max(100, Math.min(400, dotsToRemoveInside));
for (let i = 0; i < dotsToRemoveInside && i < maxRemovals && removedInside < currentWhiteDotsInside; i++) {
for (let j = dots.length - 1; j >= 0; j--) {
if (dots[j].isInsidePetals && dots[j].color === 255) {
dots.splice(j, 1);
dotsRemovedInside++;
removedInside++;
break;
}
}
}
} else if (!initialFillComplete) {
let targetRemoved = Math.round(initialWhiteDotsInside * targetProgress);
dotsToRemoveInside = targetRemoved - dotsRemovedInside;
let removedInside = 0;
let currentWhiteDotsInside = dots.filter(d => d.isInsidePetals && d.color === 255).length;
let maxRemovals = Math.max(100, Math.min(400, dotsToRemoveInside));
for (let i = 0; i < dotsToRemoveInside && i < maxRemovals && removedInside < currentWhiteDotsInside; i++) {
for (let j = dots.length - 1; j >= 0; j--) {
if (dots[j].isInsidePetals && dots[j].color === 255) {
dots.splice(j, 1);
dotsRemovedInside++;
removedInside++;
break;
}
}
}
}
for (let i = 0; i < dotsToAddOutside && i < 100 && dots.length < totalDotsNeeded; i++) {
let x, y;
let attempts = 0;
do {
x = random(width);
y = random(height);
attempts++;
} while (isPointInPetals(x, y) && attempts < 50);
if (!isPointInPetals(x, y)) {
dots.push({
x: x,
y: y,
color: 255,
size: dotSize,
isInsidePetals: false
});
dotsInCurrentPhase++;
}
}
} else {
let dotsToAddInside = 0;
let dotsToRemoveOutside = 0;
if (!initialFillComplete) {
dotsToAddInside = targetDots - dotsInsidePetals;
} else {
let targetRemoved = Math.round(initialWhiteDotsOutside * targetProgress);
dotsToRemoveOutside = targetRemoved - dotsRemovedOutside;
dotsToAddInside = dotsToRemoveOutside;
}
if (initialFillComplete && dotsToRemoveOutside > 0) {
let removedOutside = 0;
let currentWhiteDotsOutside = dots.filter(d => !d.isInsidePetals && d.color === 255).length;
let maxRemovals = Math.max(100, Math.min(400, dotsToRemoveOutside));
for (let i = 0; i < dotsToRemoveOutside && i < maxRemovals && removedOutside < currentWhiteDotsOutside; i++) {
for (let j = dots.length - 1; j >= 0; j--) {
if (!dots[j].isInsidePetals && dots[j].color === 255) {
dots.splice(j, 1);
dotsRemovedOutside++;
removedOutside++;
break;
}
}
}
} else if (!initialFillComplete) {
let targetRemoved = Math.round(initialWhiteDotsOutside * targetProgress);
dotsToRemoveOutside = targetRemoved - dotsRemovedOutside;
let removedOutside = 0;
let currentWhiteDotsOutside = dots.filter(d => !d.isInsidePetals && d.color === 255).length;
let maxRemovals = Math.max(100, Math.min(400, dotsToRemoveOutside));
for (let i = 0; i < dotsToRemoveOutside && i < maxRemovals && removedOutside < currentWhiteDotsOutside; i++) {
for (let j = dots.length - 1; j >= 0; j--) {
if (!dots[j].isInsidePetals && dots[j].color === 255) {
dots.splice(j, 1);
dotsRemovedOutside++;
removedOutside++;
break;
}
}
}
}
for (let i = 0; i < dotsToAddInside && i < 100 && dots.length < totalDotsNeeded; i++) {
let pos = getRandomPositionInPetals();
if (pos) {
dots.push({
x: pos.x,
y: pos.y,
color: 255,
size: dotSize,
isInsidePetals: true
});
dotsInsidePetals++;
}
}
}
}
noStroke();
for (let dot of dots) {
fill(dot.color);
ellipse(dot.x, dot.y, dot.size, dot.size);
}
}
function windowResized() {
canvasSize = min(windowWidth, windowHeight);
resizeCanvas(canvasSize, canvasSize);
centerX = width / 2;
centerY = height / 2;
dotSize = max(1, canvasSize / 500);
generatePetals();
dots = [];
cycleCount = 0;
isBlackout = false;
blackoutStartDots = 0;
blackoutRemoved = 0;
dotsInCurrentPhase = 0;
dotsInsidePetals = 0;
dotsRemovedOutside = 0;
dotsRemovedInside = 0;
initialWhiteDotsInside = 0;
initialWhiteDotsOutside = 0;
initialFillComplete = false;
cycleStartTime = millis();
background(0);
}