Skip to content

Instantly share code, notes, and snippets.

@dribnet
Forked from prestojack/.block
Last active November 2, 2016 01:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dribnet/1dbdb24efef11d660fd9e98abfa56c61 to your computer and use it in GitHub Desktop.
Save dribnet/1dbdb24efef11d660fd9e98abfa56c61 to your computer and use it in GitHub Desktop.
PS1 MDDN 342 2016
license: mit

PS1 MDDN 342 2016 - Goblins

The goal of this project was to create a program that generated a series of distinct faces. 'Goblins' achieves this by creating sketchy goblin-like faces that have a wide variation in facial expression, giving each face a unique personality. The final arrangement depicts a slumber party of 'sleeping' goblins, with some king goblins amongst them. While the majority of the goblins are resting, some are awake and exhibiting a wide variety of emotions.

// note: this file is poorly named - it can generally be ignored.
// helper functions below for supporting blocks/purview
function saveBlocksImages(doZoom) {
if(doZoom == null) {
doZoom = false;
}
// generate 960x500 preview.jpg of entire canvas
// TODO: should this be recycled?
var offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 1550*3;
offscreenCanvas.height = 1140*3;
var context = offscreenCanvas.getContext('2d');
// background is flat white
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 1550*3, 1140*3);
context.drawImage(this.canvas, 0, 0, 1550*3, 1140*3);
// save to browser
var downloadMime = 'image/octet-stream';
var imageData = offscreenCanvas.toDataURL('image/png');
imageData = imageData.replace('image/png', downloadMime);
p5.prototype.downloadFile(imageData, 'canvas.png', 'png');
/*
// generate 230x120 thumbnail.png centered on mouse
offscreenCanvas.width = 230;
offscreenCanvas.height = 120;
// background is flat white
context = offscreenCanvas.getContext('2d');
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 230, 120);
if(doZoom) {
// pixelDensity does the right thing on retina displays
var pd = this._pixelDensity;
var sx = pd * mouseX - pd * 230/2;
var sy = pd * mouseY - pd * 120/2;
var sw = pd * 230;
var sh = pd * 120;
// bounds checking - just displace if necessary
if (sx < 0) {
sx = 0;
}
if (sx > this.canvas.width - sw) {
sx = this.canvas.width - sw;
}
if (sy < 0) {
sy = 0;
}
if (sy > this.canvas.height - sh) {
sy = this.canvas.height - sh;
}
// save to browser
context.drawImage(this.canvas, sx, sy, sw, sh, 0, 0, 230, 120);
}
else {
// now scaledown
var full_width = this.canvas.width;
var full_height = this.canvas.height;
context.drawImage(this.canvas, 0, 0, full_width, full_height, 0, 0, 230, 120);
}
imageData = offscreenCanvas.toDataURL('image/png');
imageData = imageData.replace('image/png', downloadMime);
p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png');
*/
}
function resetFocusedRandom() {
return Math.seedrandom(arguments);
}
function focusedRandom(min, max, focus, mean) {
if(max === undefined) {
max = min;
min = 0;
}
if(focus === undefined) {
focus = 1.0;
}
if(mean === undefined) {
mean = (min + max) / 2.0;
}
if(focus == 0) {
return d3.randomUniform(min, max)();
}
else if(focus < 0) {
focus = -1 / focus;
}
sigma = (max - mean) / focus;
val = d3.randomNormal(mean, sigma)();
if (val > min && val < max) {
return val;
}
return d3.randomUniform(min, max)();
}
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.2/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.2/addons/p5.dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.0/seedrandom.min.js"></script>
<script src="https://d3js.org/d3-random.v1.min.js"></script>
<script language="javascript" type="text/javascript" src="focusedRandom.js"></script>
<script language="javascript" type="text/javascript" src="readme.purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<style> body {padding: 0; margin: 0;} </style>
</head>
<body style="background-color:white">
<div id="canvasContainer"></div>
</body>
var main_canvas;
var eyebrow_slider;
var pupil_slider;
var jaw_slider;
var faces = [];
var randVal = 0.18;
var faceScale = 100;
var rows = 8*3;
var cols = 5*3;
function setup () {
main_canvas = createCanvas(1550*3, 1140*3);
rectMode(CENTER);
angleMode(DEGREES);
for (i = 0; i < rows; i++){
faces[i] = []
for (j = 0; j < cols; j++){
var face = drawHead(int(random(3*faceScale/4.0, faceScale)));
faces[i].push(face);
}
}
}
function draw () {
background(87, 82, 97);
fill(255);
stroke(0);
strokeWeight(1);
for (i = 0; i < rows; i++){
for (j = 0; j < cols; j++){
push();
if (i % 2 == 0) {
translate(25 + faceScale + (2*(faceScale-10)) * i, 45 + faceScale + ((2*faceScale) * j));
} else {
translate(25 + faceScale + (2*(faceScale-10)) * i, 45 + (1.5*faceScale) + ((2*faceScale) * j));
}
faces[i][j]();
pop();
}
}
noLoop();
}
function recreateFaces () {
faces = [];
for (i = 0; i < rows; i++){
faces[i] = []
for (j = 0; j < cols; j++){
var face = drawHead(int(random(3*faceScale/4.0, faceScale)));
faces[i].push(face);
}
}
}
function drawHead (scalar) {
var coords = [(-0.1 + random(-randVal, randVal)) * scalar,
(-1.0 + random(-randVal, randVal)) * scalar,
(-0.6 + random(-randVal, randVal)) * scalar,
(-0.6 + random(-randVal, randVal)) * scalar,
(-0.8 + random(-randVal, randVal)) * scalar,
(-0.7 + random(-randVal, randVal)) * scalar,
(0.5 + random(-randVal, randVal)) * scalar,
(1.0 + random(-randVal, randVal)) * scalar,
(0.7 + random(-randVal, randVal)) * scalar,
(0.5 + random(-randVal, randVal)) * scalar,
(0.6 + random(-randVal, randVal)) * scalar,
(0.4 + random(-randVal, randVal)) * scalar,
(-0.7 + random(-randVal, randVal)) * scalar];
var eyelid = focusedRandom(-10, 60, 50, -10);
var mouthval = int(random(3));
var pupil = focusedRandom(1,6, 5, 2);
var crownState = random(1);
var beardState = random(1);
var col = color(random(160, 220), 180, random(210, 245));
//var col = color(random(210, 235), random(160, 210), 140);
var pupilOffset = random(-4, 4);
var eye1 = drawEye(coords[5] + scalar/6.0, coords[6] - 2*scalar/15.0, scalar/3.0, 2*scalar/5.0, pupilOffset, 1);
var eyelid1 = drawEyelids(coords[5] + scalar/6.0, coords[6] - 2*scalar/15.0, scalar/3.0, 2*scalar/5.0, random(-25, 25), col);
var eye2 = drawEye(coords[8] - 4*scalar/15.0, coords[9] - 2*scalar/15.0, scalar/2.0, 3*scalar/5.0, pupilOffset, 0);
var eyelid2 = drawEyelids(coords[8] - 4*scalar/15.0, coords[9] - 2*scalar/15.0, scalar/2.0, 3*scalar/5.0, random(-25, 25), col);
var mouth = drawMouth(coords[5] + scalar/6.0 + (coords[8] - coords[5] - 2*scalar/5.0)/2.0, coords[7] - scalar/5.0, 2 * abs(coords[8] - coords[5] - 13*scalar/15.0)/3.0, 2*scalar/15.0);
var beard = drawBeard(coords[5] + scalar/6.0 + (coords[8] - coords[5] - 2*scalar/5.0)/2.0, coords[7] - scalar/5.0);
var nose = drawNose(coords[5] + scalar/12.0 + (coords[8] - coords[5] - 2*scalar/5.0)/2.0, coords[7] - 2*scalar/5.0, abs(coords[8] - coords[5] - 13*scalar/15.0)/2.0, 2*scalar/15.0);
var ears = drawEars(coords, scalar/5.0, 2*scalar/5.0);
var head = drawHeadShape(coords);
var crown = drawCrown(coords);
var rotAngle = random(-18,18);
return function() {
push();
rotate(rotAngle);
push();
fill(col);
sketchyStyle(ears);
//head
sketchyStyle(head);
pop();
//crown
if (crownState > 0.95) {
crown(1);
push();
noFill();
strokeWeight(1);
translate(0, 1);
crown(0);
translate(0, -2);
crown(0);
pop();
}
eye1(pupil, 1);
push();
noFill();
strokeWeight(1);
rotate(1);
eye1(pupil, 0);
rotate(-2);
eye1(pupil, 0);
pop();
eyelid1(eyelid, 1);
push();
noFill();
strokeWeight(1);
rotate(1);
eyelid1(eyelid, 0);
rotate(-2);
eyelid1(eyelid, 0);
pop();
eye2(pupil, 1);
push();
noFill();
strokeWeight(1);
rotate(1);
eye2(pupil, 0);
rotate(-2);
eye2(pupil, 0);
pop();
eyelid2(eyelid, 1);
push();
noFill();
strokeWeight(1);
rotate(1);
eyelid2(eyelid, 0);
rotate(-2);
eyelid2(eyelid, 0);
pop();
mouth(mouthval, 1);
push();
strokeWeight(1);
translate(0, 2);
mouth(mouthval, 0);
translate(0, -4);
mouth(mouthval, 0);
pop();
if (beardState > 0.4) {
beard();
push();
strokeWeight(1);
translate(0, 2);
beard();
translate(0, -4);
beard();
pop();
}
nose();
push();
strokeWeight(1);
translate(0, 1);
nose();
translate(0, -2);
nose();
pop();
pop();
}
}
function sketchyStyle (object) {
object();
push();
noFill();
strokeWeight(1);
rotate(1);
object();
rotate(-2);
object();
rotate(2)
translate(0, -3);
stroke(50);
object();
pop();
}
function drawCrown (coords) {
var ht = random(20, 70);
var wd = random(20, 60);
var baseHt = 30;
return function(fillState) {
push();
if (fillState == 1) {
fill(255,255,100);
}
beginShape();
vertex(coords[0] - wd/2, coords[1] + baseHt);
vertex(coords[0] - wd/2, coords[1] - (ht-baseHt));
vertex(coords[0] - wd/4, coords[1] - (ht/2-baseHt));
vertex(coords[0], coords[1] - (ht-baseHt));
vertex(coords[0] + wd/4, coords[1] - (ht/2-baseHt));
vertex(coords[0] + wd/2, coords[1] - (ht-baseHt));
vertex(coords[0] + wd/2, coords[1] + baseHt);
vertex(coords[0] - wd/2, coords[1] + baseHt);
endShape();
pop();
}
}
function drawHeadShape (coords) {
return function() {
beginShape();
curveVertex(coords[11], coords[12]);
curveVertex(coords[0], coords[1]);
curveVertex(coords[2], coords[3]);
curveVertex(coords[4], 0);
curveVertex(coords[5], coords[6]);
curveVertex(0, coords[7]);
curveVertex(coords[8], coords[9]);
curveVertex(coords[10], 0);
curveVertex(coords[11], coords[12]);
curveVertex(coords[0], coords[1]);
curveVertex(coords[2], coords[3]);
endShape();
}
}
function drawEars (coords, wd, ht) {
return function() {
ellipse(coords[5], coords[6], wd, ht);
ellipse(coords[8], coords[9], wd, ht);
}
}
function drawNose (x, y, wd, ht) {
return function() {
push();
noFill();
arc(x, y, wd, ht, 0, 180);
arc(x - abs(wd/2.0), y + 6, wd/4.0, ht/2.0, 10, 190);
arc(x + abs(wd/2.0), y + 6, wd/4.0, ht/2.0, -10, 180);
pop();
}
}
function drawEye (x, y, wd, ht, offset, lefteye) {
return function(pupil, fillState) {
push();
noFill();
if (fillState == 1) {
if (lefteye == 1) {
arc(x, y, wd, ht*1.5, 0, 68);
arc(x, y, wd, ht*1.2, 0, 68);
} else {
arc(x, y, wd, ht*1.5, 112, 180);
arc(x, y, wd, ht*1.2, 112, 180);
}
}
if (fillState == 1) {
fill(255);
}
ellipse(x, y, wd, ht);
if (fillState == 1) {
fill(0);
}
var mult = offset/(abs(offset));
ellipse(x + (wd/10.0*offset) - ((offset/8.0) * pupil * wd/20.0), y, pupil * wd/10.0, pupil * ht/10.0);
pop();
}
}
function drawEyelids (x, y, wd, ht, angle, lidCol) {
return function(eyelid, fillState) {
push();
if (fillState == 1) {
fill(red(lidCol) - 40, green(lidCol) - 40, blue(lidCol) - 40);
}
arc(x, y, wd, ht, 190 + eyelid, 350 - eyelid, CHORD);
arc(x, y, wd, ht, 10 + eyelid, 170 - eyelid, CHORD);
translate(x, y-(ht/2.0));
rotate(angle);
fill(0);
rect(0, 0, wd, 5);
pop();
}
}
function drawMouth (x, y, wd, ht) {
return function(expression, strokeState) {
push();
noFill();
stroke(0);
if (strokeState == 1) {
strokeWeight(3);
}
if (expression == 0) {
arc(x, y, wd, ht, 0, 180);
} else if (expression == 1) {
arc(x, y, wd, ht, 180, 360);
} else {
push();
fill(0);
strokeWeight(1);
ellipse(x, y, wd, ht)
pop();
}
pop();
}
}
function drawBeard (x, y) {
return function() {
push();
fill(0);
stroke(30);
rect(x, y + 18, 2, 6);
rotate(-4);
rect(x, y + 16, 1, 4);
rotate(-4);
rect(x, y + 16, 1, 2);
rotate(12);
rect(x, y + 16, 1, 4);
rotate(4);
rect(x, y + 16, 1, 2);
pop();
}
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
}
function mousePressed() {
if (mouseButton == LEFT) {
recreateFaces();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment