xxxxxxxxxx
149
// Shadows (Genuary 22)
// Isometric projection of Suprematism (Genuary 11 prompt)
// https://editor.p5js.org/N-Lebrun/sketches/3S13Je7bK
// Nicolas Lebrun @nclslbrn https://nicolas-lebrun.fr
let ctr = { x: window.innerWidth / 2, y: window.innerHeight / 2 }
let minD = Math.min(window.innerWidth, window.innerHeight) / 2
function iso (pt) {
return {
x: ctr.x + pt.x - pt.y,
y: ctr.y*1.2 + (pt.x + pt.y) / 2
}
}
function setup () {
canvas = createCanvas(windowWidth, windowHeight);
noLoop();
stroke(50);
composition();
fill(255, 200);
rect(width*0.2, height*0.4, width*0.6, height*0.2);
fill("#333")
textSize(24);
textAlign(CENTER);
text("Click to regenerate a composition", width/2, height/2);
}
function composition () {
const compAngle = PI * 0.5 * random();
background(255, 235, 235);
noFill();
const innerCanvas = [
{x: 20, y: 20}, {x: width-20, y: 20}, {x: width-20, y: height-20}, {x: 20, y: height-20}
]
drawParallelLines([255, 236, 236],innerCanvas);
drawParallelLines([0, 0, 0, 0], innerCanvas);
const shapes = []
for (let i = 0; i < 6 + random() * 18; i++) {
const shpRot = PI / Math.ceil(random() * 3)
const shpCenter = {
x: (random() - 0.5) * minD * 0.5,
y: (random() - 0.5) * minD * 0.5
}
const shapeSize = createVector(
Math.max(ctr.x * 0.1, minD * random() * 0.75),
Math.max(ctr.y * 0.05, minD * random() * 0.2)
);
// Create two points to define an edge
const shpStart = {
x: shpCenter.x - shapeSize.x / 2 * Math.cos(shpRot + compAngle),
y: shpCenter.y - shapeSize.x / 2 * Math.sin(shpRot + compAngle),
}
const shpEnd = {
x: shpCenter.x + shapeSize.x / 2 * Math.cos(shpRot + compAngle),
y: shpCenter.y + shapeSize.x / 2 * Math.sin(shpRot + compAngle),
}
// Then create a path around it
const shapePts = [{
x: shpStart.x + Math.cos(shpRot + compAngle - HALF_PI) * shapeSize.y,
y: shpStart.y + Math.sin(shpRot + compAngle - HALF_PI) * shapeSize.y
}, {
x: shpEnd.x + Math.cos(shpRot + compAngle - HALF_PI) * shapeSize.y,
y: shpEnd.y + Math.sin(shpRot + compAngle - HALF_PI) * shapeSize.y
}, {
x: shpEnd.x + Math.cos(shpRot + compAngle + HALF_PI) * shapeSize.y,
y: shpEnd.y + Math.sin(shpRot + compAngle + HALF_PI) * shapeSize.y
}, {
x: shpStart.x + Math.cos(shpRot + compAngle + HALF_PI) * shapeSize.y,
y: shpStart.y + Math.sin(shpRot + compAngle + HALF_PI) * shapeSize.y
}];
shapes.push({
center: shpCenter,
pts: shapePts,
rot: shpRot
})
}
// Order shapes from top left to bottom right
shapes.sort((a, b) => a.center.x < b.center.x || a.center.y < b.center.y)
// Build visible side of these shapes
const isoShapes = []
shapes.forEach((shp, i) => {
const shpHeight = minD * random(0.15, 0.5)
// Project these points into an isometric grid
const base = shp.pts.map((pt) => iso(pt))
// Find the highest point of the shape
const highestPt = [base].sort((a, b) => a.y - b.y)[0]
const highestPtId = base.indexOf(highestPt)
// And build sides from it
const bottom = []
for (let i = 0; i < 4; i++) {
const pt = base[(highestPtId + i) % base.length]
bottom.push({ x: pt.x, y: pt.y })
}
const top = bottom.map((pt) => { return { x: pt.x, y: pt.y - shpHeight } })
isoShapes.push({
bottom: bottom,
left: [top[3], top[2], bottom[2], bottom[3]],
right: [top[2], top[1], bottom[1], bottom[2]],
top: top,
height: shpHeight
})
})
// Then draw side
isoShapes.forEach((iso, i) => {
drawParallelLines([255, 255, 255, 200], iso.bottom);
drawParallelLines([0, 0, 0, 0], iso.bottom);
drawParallelLines([255, 255, 255, 200], iso.left);
drawParallelLines([0, 0, 0, 0], iso.left);
drawParallelLines([255, 255, 255, 200], iso.right);
drawParallelLines([0, 0, 0, 0], iso.right);
drawParallelLines([255, 255, 255, 200], iso.top);
drawParallelLines([0, 0, 0, 0], iso.top);
})
}
function drawParallelLines (fillColor, mask = false) {
drawingContext.save();
if (mask) {
noStroke();
fill(fillColor);
beginShape();
mask.forEach((pt) => vertex(pt.x, pt.y));
endShape(CLOSE);
drawingContext.clip();
}
const dy = random(0.25, 0.75) * height * 0.5;
const step = random(0.5, 12);
stroke(50);
noFill();
for (let y = -dy; y <= height + dy; y += step) {
line(0, y, width, y + dy * random(0.95, 1));
}
drawingContext.restore();
}
function mouseClicked () {
composition();
}
function keyPressed(e) {
if (e && e.key && (e.key === 'd' || e.key === 'D')) {
save('More-moiré-genuary-23');
}
}