Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.
Let’s do it!
21) Persian carpet
Wikipedia: Persian carpet
Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.
Let’s do it!
Wikipedia: Persian carpet
Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.
Let’s do it!
Wikipedia: Art Deco
Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.
Let’s do it!
Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.
Let’s do it!
Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.
Let’s do it!
Wikipedia: Asemic writing
Use the same Wikipedia code as yesterday to get a random page, render each word as a line that meanders based on the letters of the word. Shiny. 😄
Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.
Let’s do it!
META! LEARN EVERYTHING!
Fetch a random page from Wikipedia and scroll it by super quick, see how fast you can speed read it. And heck, you might just learn something. I know I did!
let url;
let titleToRender;
let wordsToRender;
let wordIndex;
let nextButton;
let wikiButton;
const CHAR_SIZE = 60;
function setup() {
createCanvas(400, 400);
frameRate(10);
nextButton = createButton("next");
nextButton.mousePressed(renderRandomPage);
wikiButton = createButton("open");
wikiButton.mousePressed(() => {
window.open(url, '_blank');
});
wordsToRender = [];
wordIndex = 0;
renderRandomPage();
}
function draw() {
if (wordIndex > wordsToRender.length) {
noLoop();
}
clear();
textSize(CHAR_SIZE);
for (let i = 0; i < height / CHAR_SIZE; i++) {
if (i == 3) {
fill("black");
} else {
fill("lightgray");
}
text(
wordsToRender[wordIndex + i],
10,
CHAR_SIZE * (i + 1)
);
}
stroke("black");
line(
width - 10,
10,
width - 10,
height - 10
);
circle(
width - 10,
1.0 * wordIndex / wordsToRender.length * (height - 20),
20
);
wordIndex++;
}
function renderRandomPage() {
wikiButton.attribute('disabled', '');
// https://stackoverflow.com/a/70225116
async function go() {
let title;
{
let json = await httpGet(`https://en.wikipedia.org/w/api.php?action=query&format=json&generator=random&grnlimit=1&grnnamespace=0&prop=info&origin=*`, 'json');
let pages = json.query.pages;
let id = Object.keys(pages)[0];
title = pages[id].title;
url = `https://en.wikipedia.org/wiki/${title}`;
}
let body;
{
let json = await httpGet(`https://en.wikipedia.org/w/api.php?action=query&format=json&titles=${title}&prop=extracts&explaintext&origin=*`, 'json');
let pages = json.query.pages;
let id = Object.keys(pages)[0];
body = pages[id].extract;
}
return [title, body];
}
background(255);
text("Loading...", 10, 20);
go().then(([title, body]) => {
titleToRender = title;
wordsToRender = body.trim().split(/\s+/);
wordIndex = 0;
wikiButton.removeAttribute('disabled');
loop();
});
}
Spend a month making one beautiful thing per day, given a bunch of prompts. A month late, but as they say, ’the second best time is now'.
Let’s do it!
Wikipedia: Tessellation (List)
This was not at all the direction I ended to go, but it got really interesting, so I decided to keep it.
What I remember doing years and years ago, I think roughly around the time of Windows 95 (I feel old) or perhaps even pre-Windows was using a tesselation program that would give you a basic shape and then allow you to pull the edges in a way it would propagate to automatically keep the tesselation valid. It was pretty awesome… but I have no idea what it was called any more.
It might have been Shodor on Tessellations.org, or perhaps TesselMania!. Been a while.
In any case, enjoy!
const SIZE = 40;
let gui;
let params = {
scale: 1.0, scaleMin: 0.25, scaleMax: 3.0, scaleStep: 0.01,
drawBorders: true,
applyRotation: true,
fastFlux: true,
varyRotations: true,
}
let g;
let buffer;
let bufferMask;
let lastRedrawBuffer;
function setup() {
createCanvas(400, 400);
g = createGraphics(width, height);
buffer = createGraphics(2 * SIZE, 2 * SIZE);
for (let i = 0; i < 100; i++) {
buffer.fill(
255 * random(),
255 * random(),
255 * random(),
255 * random()
);
buffer.rect(
random(4 * SIZE) - 2 * SIZE,
random(4 * SIZE) - 2 * SIZE,
random(2 * SIZE),
random(2 * SIZE)
)
}
redrawBuffer();
bufferMask = createGraphics(2 * SIZE, 2 * SIZE);
bufferMask.push();
{
bufferMask.translate(SIZE, SIZE);
bufferMask.scale(params.scale);
bufferMask.stroke("black");
bufferMask.fill("black");
ngon(bufferMask, 6, SIZE);
}
bufferMask.pop();
gui = createGuiPanel('params');
gui.addObject(params);
gui.setPosition(420, 0);
}
function draw() {
g.background(255);
if (params.fastFlux) {
drawOneToBuffer();
} else {
if (millis() - lastRedrawBuffer > 1000) {
redrawBuffer();
}
}
let masked = buffer.get();
masked.mask(bufferMask);
g.push();
{
g.stroke("black");
g.fill("green");
g.translate(200, 200);
g.scale(params.scale);
g.stroke("black");
g.noFill();
if (params.drawBorders) {
g.stroke("black");
g.strokeWeight(2);
ngon(g, 6, SIZE);
}
g.push();
{
g.translate(-SIZE, -SIZE);
g.image(masked, 0, 0);
}
g.pop();
for (let xd = -10; xd < 10; xd++) {
for (let yd = -50; yd < 50; yd++) {
if (xd == 0 && yd == 0) continue;
g.push();
{
let rowOffset = abs(yd) % 2 == 1 ? 1.5 * SIZE : 0;
// Major thanks to:
// https://www.redblobgames.com/grids/hexagons/
g.translate(
rowOffset + 3.0 * xd * SIZE,
sqrt(3) / 2 * yd * SIZE
);
if (params.applyRotation) {
let n = noise(
xd,
yd,
params.varyRotations ? frameCount / 500.0 : 0
);
g.rotate(TWO_PI / 6.0 * parseInt(n * 6));
}
g.push();
{
g.translate(-SIZE, -SIZE);
g.image(masked, 0, 0);
}
g.pop();
if (params.drawBorders) {
g.stroke("black");
g.strokeWeight(2);
ngon(g, 6, SIZE);
}
}
g.pop();
}
}
}
g.pop();
image(g, 0, 0);
}
function ngon(g, n, size) {
g.beginShape();
for (let i = 0; i < n; i++) {
let x = size * cos(TWO_PI * i / n);
let y = size * sin(TWO_PI * i / n);
g.vertex(x, y);
}
g.endShape(CLOSE);
}
function redrawBuffer() {
buffer.background(255);
for (let i = 0; i < 100; i++) {
drawOneToBuffer();
}
lastRedrawBuffer = millis();
}
function drawOneToBuffer() {
buffer.fill(
255 * random(),
255 * random(),
255 * random(),
255 * random()
);
buffer.rect(
random(4 * SIZE) - 2 * SIZE,
random(4 * SIZE) - 2 * SIZE,
random(2 * SIZE),
random(2 * SIZE)
);
}