Necromancer

128 unique pieces, created with with Javascript and p5.js, and minted on Arbitrum, an Ethereum L2. Presented by Prohibition and deployed on Art Blocks Engine. Towering trees, imbued with magical power, reach high into the sky, guarding the secret hidden within.

Secondary market on Opensea.

The code, which is 22,208 characters long, is stored on an Arbitrum smart contract here. Querying "projectScriptByIndex" with 2 as the "_projectId" and 0 as the "index" will return the script.

Necromancer Contract Details

Necromancer Sketch

This project began as a simple sketch of some parallel lines. It began to look as though I was standing in a forest looking uphill at the trees.
The code for this initial sketch is below:

function setup() { createCanvas(1000, 400); noFill(); pixelDensity(4); background("#fdfff5"); stroke("#252321"); curveTightness(-2); } function draw() { background("#fdfff5"); let x = 100; let y2 = 50; let y = 266; let w = 4; let h = 20; let t = -10; let segments = (500-y2)/h; let s = w+10; for(let x = s/2; x < width; x+=s*2) { for(let i = 0; i > -h*segments; i-=h+h/10){ push(); translate(x,y+i); scale((y/height),1); translate(-x,-y-i); stroke("#363330"); drawTreeTrunk(x,y+i,w,h,t,3*(y/height),10); stroke("#fdfff5"); drawTreeTrunk(x,y+i,w,h,t,2*(y/height),10); stroke("#363330"); drawTreeTrunk(x,y+i,w,h,t,1*(y/height),10); pop(); } } y += 45; for(let x = s+s/1.25; x < width; x+=s*2) { let yInit = y; y += (Math.random() < .5 ? -1 : 1) * Math.random()*50; for(let i = 0; i > -h*segments; i-=h+h/10){ push(); translate(x,y+i); scale((y/height),1); translate(-x,-y-i); stroke("#201F1D") drawTreeTrunk(x,y+i,w,h,t,4*(y/height),15); stroke("#fdfff5"); drawTreeTrunk(x,y+i,w,h,t,2*(y/height),15); stroke("#201F1D") drawTreeTrunk(x,y+i,w,h,t,1*(y/height),15); pop(); } y = yInit; } y += 30; for(let x = s; x < width; x+=s*2) { let yInit = y; y += (Math.random() < .5 ? -1 : 1) * Math.random()*50; for(let i = 0; i > -h*segments; i-=h+h/10){ let iInit = i; i += Math.random()*3; push(); translate(x,y+i); scale((y/height),1); translate(-x,-y-i); stroke("#151513") drawTreeTrunk(x,y+i,w,h,t,5*(y/height),20); stroke("#fdfff5"); drawTreeTrunk(x,y+i,w,h,t,2*(y/height),20); stroke("#151513") drawTreeTrunk(x,y+i,w,h,t,1*(y/height),20); pop(); i = iInit; } y = yInit; } noLoop(); } function drawTreeTrunk(x,y,w,h,t,weight,steps) { let x1 = x; let x2 = x+(w/3); let x3 = x+(2*(w/3)); let x4 = x+w; let y1 = y; let y2 = y-sin(PI/4)*t; let y3 = y-sin(PI/4)*t; let y4 = y; if(Math.random()>.5) { strokeWeight(noise(x1,y2)); bezier(x1,y1,x2,y2,x3,y3,x4,y4); bezier(x1,y1-h,x2,y2-h,x3,y3-h,x4,y4-h); } beginShape(); for(let i = 0; i <= steps; i++) { push(); let m = i/steps; let bX = bezierPoint(x1,x2,x3,x4,m); let bY = bezierPoint(y1,y2,y3,y4,m); let bTX = bezierTangent(x1,x2,x3,x4,m); let bTY = bezierTangent(y1,y2,y3,y4,m); if(i === 0 || i === steps){ strokeWeight(weight); } else { translate(bX,bY); shearX(radians((noise(x,y) < .3 ? -1 : 1)*(noise(i))*5)); translate(-bX,-bY); strokeWeight(noise(bX,bY)*weight); } curveVertex(bX,bY) curveVertex(bX,bY-h); pop(); } endShape(); }