rgroves – Final – Section B

sketch

//vertices and edge sets of the individual graphs
var V = [];
var E = [];

//total set of vertices
var vertices = [];
var spacing = 48;

//buttons for coloring vertices
var redbutton;
var bluebutton;
var greenbutton;
var pinkbutton;
var orangebutton
var buttons = [];

var levelnumber = 1;
var mousehasentbeenclicked;

function setup() {
    createCanvas(480, 400);
    background(255);
    resetLevel();
}

function resetLevel() {
	mousehasentbeenclicked = true;
	 background(255);
    //create buttons
    redbutton = makeButton(width/6, color(209, 90, 90));
	bluebutton = makeButton(2 * width/6, color(93, 137, 196));
	greenbutton = makeButton(3 * width/6, color(199, 197, 71));
	pinkbutton = makeButton(4 * width/6, 'lightpink');
	orangebutton = makeButton(5 * width/6, 'orange');
	buttons = [redbutton, bluebutton, greenbutton, pinkbutton, orangebutton];
	for (i = 0; i < buttons.length; i++) {
		buttons[i].isoutlined = false;
		buttons[i].draw();
	}

	//draw grid of small vertices and label them from 0 to 53 in an array
    for (i = 0; i < width/spacing - 1; i++) {
    	for (j = 0; j < 300/spacing - 1; j++) {
	   		vertices[i + ((width/spacing - 1) * j)] = 
	   		makeVertex(spacing + i * spacing, spacing + j * spacing);
    	}
    }
}

//OBJECTS: VERTICES, EDGES, BUTTONS////////////////////////////////////////////

//vertices
function vertexboldDraw() {
	noStroke();
	if (this.isred == true) {
		fill(209, 90, 90);
		ellipse(this.x, this.y, 16, 16);	
	} else if (this.isblue == true) {
		fill(93, 137, 196);
		ellipse(this.x, this.y, 16, 16);	
	} else if (this.isgreen == true) {
		fill(199, 197, 71);
		ellipse(this.x, this.y, 16, 16);	
	} else if (this.ispink == true) {
		fill('lightpink');
		ellipse(this.x, this.y, 16, 16);
	} else if (this.isorange == true) {
		fill('orange');
		ellipse(this.x, this.y, 16, 16);
	} else {
		stroke(150);
		strokeWeight(1);
		fill(255);	
		ellipse(this.x, this.y, 15, 15);	
	}
}

function vertexDraw() {
	noStroke();
	fill(180);
	ellipse(this.x, this.y, 1.5, 1.5);
}

function makeVertex(px, py) {
	v = {x: px, y: py, draw: vertexDraw, bolddraw: vertexboldDraw,
		isred: false, isgreen: false, isblue: false, ispink: false,
		isorange: false};
	return v;
}

//edges
function edgeDraw(m, n) {
	if (this.iscolored == true & this.iscorrect == true) {
		strokeWeight(3);
		stroke('limegreen');
	} else if (this.iscolored == true & this.iscorrect == false) {
		strokeWeight(3);
		stroke('tomato');
	} else if (this.iscolored == false) {
		strokeWeight(.5);
		stroke(200);
	}
    line(vertices[this.m].x, vertices[this.m].y,
    vertices[this.n].x, vertices[this.n].y);
}

function makeEdge(pm, pn) {
	e = {m: pm, n: pn, iscolored: false, iscorrect: true, draw: edgeDraw};
	return e
}

//buttons
function buttonDraw() {
	rectMode(CENTER);
	if (this.isoutlined == true) {
		strokeWeight(3);
		stroke(255);
		fill(this.buttoncolor);
		rect(this.x, height - 50, 60, 20);
	} else {
		noStroke();
		fill(this.buttoncolor);
		rect(this.x, height - 50, 61.5, 21.5);
	}	
	
}

function makeButton(px, color) {
	b = {x: px, buttoncolor: color, isoutlined: false, draw: buttonDraw};
	return b;
}

//FUNCTIONS TO BE CALLED IN MOUSEPRESSED///////////////////////////////////////
function testEdge() {
	//edges are green if the vertices are different color and red if they are 
	//the same colors
	for (i = 0; i < E.length; i++) {
		if (vertices[E[i].m].isred == true & vertices[E[i].n].isred == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if (vertices[E[i].m].isblue == true & vertices[E[i].n].isblue == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if (vertices[E[i].m].isgreen == true & vertices[E[i].n].isgreen == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if (vertices[E[i].m].ispink == true & vertices[E[i].n].ispink == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if (vertices[E[i].m].isorange == true & vertices[E[i].n].isorange == true) {
			E[i].iscolored = true;
			E[i].iscorrect = false;
		}
		if ((vertices[E[i].m].isred == true || vertices[E[i].m].isblue == true ||
			vertices[E[i].m].isgreen == true || vertices[E[i].m].ispink == true
			|| vertices[E[i].m].isorange == true) & (vertices[E[i].n].isred == true 
			|| vertices[E[i].n].isblue == true || vertices[E[i].n].isgreen == true
			|| vertices[E[i].n].ispink == true || vertices[E[i].n].isorange == true)) {
			E[i].iscolored = true;
		}
		if (E[i].iscolored == true & (vertices[E[i].m].isred !== vertices[E[i].n].isred
			|| vertices[E[i].m].isblue !== vertices[E[i].n].isblue
		    || vertices[E[i].m].isgreen !== vertices[E[i].n].isgreen 
		    || vertices[E[i].m].ispink !== vertices[E[i].n].ispink
		    || vertices[E[i].m].isorange !== vertices[E[i].n].isorange)) {
			E[i].iscolored = true;
			E[i].iscorrect = true;
		}
		E[i].draw();
	}
}

function colorVertices() {
	//change colors of vertices when clicked, depending on which button has 
	//most recently been clicked
	for (i = 0; i < V.length; i++) {
		if (dist(mouseX, mouseY, vertices[V[i]].x, vertices[V[i]].y) < 10) {
			if (buttons[0].isoutlined == true & buttons[1].isoutlined == false &&
				buttons[2].isoutlined == false && buttons[3].isoutlined == false &&
				buttons[4].isoutlined == false) {
				vertices[V[i]].isred = true;
				vertices[V[i]].isblue = false;
				vertices[V[i]].isgreen = false;
				vertices[V[i]].ispink = false;
				vertices[V[i]].isorange = false;
			}
			if (buttons[0].isoutlined == false & buttons[1].isoutlined == true &&
				buttons[2].isoutlined == false && buttons[3].isoutlined == false &&
				buttons[4].isoutlined == false) {
				vertices[V[i]].isred = false;
				vertices[V[i]].isblue = true;
				vertices[V[i]].isgreen = false;
				vertices[V[i]].ispink = false;
				vertices[V[i]].isorange = false;
			}
			if (buttons[0].isoutlined == false & buttons[1].isoutlined == false &&
				buttons[2].isoutlined == true && buttons[3].isoutlined == false &&
				buttons[4].isoutlined == false) {
				vertices[V[i]].isred = false;
				vertices[V[i]].isblue = false;
				vertices[V[i]].isgreen = true;
				vertices[V[i]].ispink = false;
				vertices[V[i]].isorange = false;
			}
			if (buttons[0].isoutlined == false & buttons[1].isoutlined == false &&
				buttons[2].isoutlined == false && buttons[3].isoutlined == true &&
				buttons[4].isoutlined == false) {
				vertices[V[i]].isred = false;
				vertices[V[i]].isblue = false;
				vertices[V[i]].isgreen = false;
				vertices[V[i]].ispink = true;
				vertices[V[i]].isorange = false;
			}
			if (buttons[0].isoutlined == false & buttons[1].isoutlined == false &&
				buttons[2].isoutlined == false && buttons[3].isoutlined == false &&
				buttons[4].isoutlined == true) {
				vertices[V[i]].isred = false;
				vertices[V[i]].isblue = false;
				vertices[V[i]].isgreen = false;
				vertices[V[i]].ispink = false;
				vertices[V[i]].isorange = true;
			}
		}
	}
}

function pressButton() {
	//select color for vertex coloring
	if (mouseX >= buttons[0].x - 30 & mouseX <= buttons[0].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = true;
			buttons[1].isoutlined = false;
			buttons[2].isoutlined = false;
			buttons[3].isoutlined = false;
			buttons[4].isoutlined = false;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
	if (mouseX >= buttons[1].x - 30 & mouseX <= buttons[1].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = false;
			buttons[1].isoutlined = true;
			buttons[2].isoutlined = false;
			buttons[3].isoutlined = false;
			buttons[4].isoutlined = false;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
	if (mouseX >= buttons[2].x - 30 & mouseX <= buttons[2].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = false;
			buttons[1].isoutlined = false;
			buttons[2].isoutlined = true;
			buttons[3].isoutlined = false;
			buttons[4].isoutlined = false;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
	if (mouseX >= buttons[3].x - 30 & mouseX <= buttons[3].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = false;
			buttons[1].isoutlined = false;
			buttons[2].isoutlined = false;
			buttons[3].isoutlined = true;
			buttons[4].isoutlined = false;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
	if (mouseX >= buttons[4].x - 30 & mouseX <= buttons[4].x + 30 
		&& mouseY <= height - 40 && mouseY >= height - 60) {
			buttons[0].isoutlined = false;
			buttons[1].isoutlined = false;
			buttons[2].isoutlined = false;
			buttons[3].isoutlined = false;
			buttons[4].isoutlined = true;
			for (i = 0; i < buttons.length; i++) {
				buttons[i].draw();
			}
	}
}

//DESIGN LEVELS AND CALL THEM IN DRAW//////////////////////////////////////////
function levelOne() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level One: Practice', 30, 10);
	E = [[25, 4], [19, 4], [25, 51], [51, 47], [47, 19], [4, 13], [25, 24], 
	[51, 41], [47, 39], [19, 20], [13, 41], [41, 20], [20, 24], [24, 39], 
	[39, 13]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 13, 19, 20, 24, 25, 39, 41, 47, 51];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 	
}

function levelTwo() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level Two', 30, 10);
	E = [[25, 4], [19, 4], [25, 51], [51, 47], [47, 19], [38, 47], [47, 51], 
	[51, 42], [42, 38], [38, 51], [42, 47], [42, 19], [25, 38], [4, 38], 
	[4, 42], [19, 38], [25, 42]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 19, 25, 38, 42, 47, 51];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 	
}

function levelThree() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level Three', 30, 10);
	E = [[4, 31], [31, 17], [31, 53], [31, 45], [31, 9], [12, 14], [14, 33], 
	[33, 40], [40, 29], [29, 12], [4, 29], [4, 14], [17, 12], [17, 33], [53, 14], 
	[53, 40], [45, 33], [45, 29], [9, 40], [9, 12]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 9, 12, 14, 17, 29, 33, 40, 45, 53, 31];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 
		
}

function levelFour() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level Four', 30, 10);
	E = [[4, 18], [18, 45], [45, 21], [21, 4], [4, 23], [23, 53], [53, 26], 
	[26, 4], [4, 28], [4, 34], [28, 34], [18, 28], [26, 34], [18, 21], 
	[23, 26], [28, 21], [34, 23], [21, 23], [28, 34], [23, 45], [21, 53]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 18, 21, 23, 26, 28, 34, 45, 53];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 
}

function levelFive() {
	textSize(10);
	strokeWeight(.4);
	fill('grey');
	text('Level Five', 30, 10);
	E = [[25, 4], [19, 4], [25, 51], [51, 47], [47, 19], [4, 13], [19, 13], 
	[25, 13], [29, 13], [33, 13], [47, 13], [51, 13], [4, 29], [4, 33], 
	[19, 29], [25, 33], [29, 51], [33, 47], [29, 47], [33, 51], [25, 29], [19, 33]];
	for (i = 0; i < E.length; i++) {
		E[i] = makeEdge(E[i][0], E[i][1]);
		if (mousehasentbeenclicked) {
			E[i].draw();
		}
	}
	V = [4, 19, 25, 47, 51, 13, 33, 29];
	for (i = 0; i < V.length; i++) {
		vertices[V[i]].bolddraw();
	} 
}



function draw() {
	for (k = 0; k < vertices.length; k++) {
    	vertices[k].draw();
    }
    if (levelnumber == 1) {
    	levelOne();
    } else if (levelnumber == 2) {
    	levelTwo();
    } else if (levelnumber == 3) {
    	levelThree();
    } else if (levelnumber == 4) {
    	levelFour();
    } else if (levelnumber == 5) {
    	levelFive();
    }
}


function mousePressed() { 
	mousehasentbeenclicked = false;
	pressButton();
	colorVertices();
	testEdge();	

	var is5colored = true;
	for (i = 0; i < E.length; i ++) {
		if (E[i].iscolored == false || E[i].iscorrect == false) {
			is5colored = false;
		}
	}
	if (is5colored == true) {
		resetLevel();
		levelnumber++;
	}
	if (levelnumber == 6) {
		textSize(90);
		fill('lightpink');
		noStroke();
		text('YOU WIN', 40, height/2);
	}			
}

My final project is a simple game based on graph coloring. Click on any of the colored boxes to select a color and then click in the vertices to color them with that color. The goal is to color in the graph so that there is no edge between vertices of the same color. When you succeed it will automatically move on to the next level. There are a total of 5 levels and when you complete them all you win!

rgroves – Looking Outwards – 12

Seven Sets by Santiago Ortiz is related to my projects because it is a visualization of a mathematical concept using color. It is basically the answer to the question “how many subsets are there of a set of size 7” (the answer is 2^7) but instead it’s a set of colors and he visualizes a subset as a combination of those colors. The way the information is displayed is very simple, beautiful, and easy to understand.

While this isn’t exactly an art project, sodoku puzzles can be directly analyzed as graph coloring problems as shown here. They are an example of many simple games that can be analyzed as mathematical concepts, which also include the Japanese game Hashiwokakero and even tic-tac-toe.

rgroves – Proposal

For my final project I am going to create a game based on graph coloring which I learned about in my discrete math class. At the time I thought it seemed more like a game than a math problem. The objective of the game will be to color in the vertices of a graph such that no adjacent vertices have the same color. The game will consist of a graph and at the bottom of the screen will be a certain number colored squares determined by the chromatic number of the graph (the minimum number of colors necessary to complete the objective). The player will select a color by clicking on the box, and then click on a vertex to color it in. When the two vertices of an edge are different colors, the edge will turn green and when they are the same the edge will turn red. You will know you have completed the level when all the edges are green. The player can then click to move onto the next level.

I’m not sure if I will be able to make the levels automatically generate as I can’t remember if there’s an algorithm for determining the chromatic number and it also may generate levels that are too easy. If I can’t make them automatically generate, I will simply manually design 25 or so levels.

Here is a sketch of what the beginning of a level, a completed level, and an incorrect coloring would look like.

 

rgroves – Composition – Section B

sketch

var cabin;
var turtle;
var spacing = 5;

function preload() {
	cabin = loadImage("https://i.imgur.com/vd2MDbC.jpg");
}

function setup() {
    createCanvas(437, 480);
    background(140, 90, 100);
    cabin.loadPixels();
    turtle = makeTurtle(0, 0);
    turtle.setColor(255);
    for (j = 0; j <= height; j += spacing) {
		for (i = 0; i <= width; i++) {
			var b = brightness(color(cabin.get(i, j)));
			var lineweight = map(b, 0, 255, 0, 5);
			turtle.setWeight(lineweight);
			turtle.forward(1);
		}
		turtle.goto(0, j);
	}
	noLoop();
}

function draw() {

}

function turtleLeft(d){this.angle-=d;}function turtleRight(d){this.angle+=d;}
function turtleForward(p){var rad=radians(this.angle);var newx=this.x+cos(rad)*p;
var newy=this.y+sin(rad)*p;this.goto(newx,newy);}function turtleBack(p){
this.forward(-p);}function turtlePenDown(){this.penIsDown=true;}
function turtlePenUp(){this.penIsDown = false;}function turtleGoTo(x,y){
if(this.penIsDown){stroke(this.color);strokeWeight(this.weight);
line(this.x,this.y,x,y);}this.x = x;this.y = y;}function turtleDistTo(x,y){
return sqrt(sq(this.x-x)+sq(this.y-y));}function turtleAngleTo(x,y){
var absAngle=degrees(atan2(y-this.y,x-this.x));
var angle=((absAngle-this.angle)+360)%360.0;return angle;}
function turtleTurnToward(x,y,d){var angle = this.angleTo(x,y);if(angle< 180){
this.angle+=d;}else{this.angle-=d;}}function turtleSetColor(c){this.color=c;}
function turtleSetWeight(w){this.weight=w;}function turtleFace(angle){
this.angle = angle;}function makeTurtle(tx,ty){var turtle={x:tx,y:ty,
angle:0.0,penIsDown:true,color:color(128),weight:1,left:turtleLeft,
right:turtleRight,forward:turtleForward, back:turtleBack,penDown:turtlePenDown,
penUp:turtlePenUp,goto:turtleGoTo, angleto:turtleAngleTo,
turnToward:turtleTurnToward,distanceTo:turtleDistTo, angleTo:turtleAngleTo,
setColor:turtleSetColor, setWeight:turtleSetWeight,face:turtleFace};
return turtle;}

I made an image filter using a turtle that goes horizontally across the screen, its width varying based on the brightness of the pixel underneath. The result is a stripy monochrome picture. It takes a really long time to load because the turtle goes forward only one pixel at a time. Here’s a screenshot of what it looks like once it’s loaded:

rgroves – LookingOutwards – 11

I found a sound art project to write about because my submission for Looking Outwards 04 was really about music.

Deep Listening Room is a sound installation by Pauline Oliveros at the 2014 Whitney Biennial. Live feed from the main lobby was broadcast onto three walls in a small gallery. The audio from the footage was heavily manipulated and distorted. In addition, Oliveros sat and played a improvised accordion part, matching the doom-like tone of the processed noise from the crowd; the soundtrack became a mixture of low drones, screeches, and vibrating wails. The installation was a commentary on the ubiquity of surveillance. The evil nature of the sound forces the viewer to confront the voyeurism of filming and watching this type of footage.

rgroves – Landscape – Section B

sketch

//Rebecca Groves
//Section B
//rgroves@andrew.cmu.edu
//Landscape

var middlecacti = [];
var foregroundcacti = [];
var shrubs = [];
var buttes = [];

var MiddlegroundSpeed = .0003;
var MiddlegroundDetail = .004;
var ForegroundSpeed = .0005;
var ForegroundDetail = .005;

var middleTerrain = [];
var foregroundTerrain = [];

function setup() {
    createCanvas(480, 250);
    //pregenerated vegetation
    for (var i = 0; i < 4; i++) {
		buttes[i] = makeButte(random(width));
	}
	for (var i = 0; i < 5; i++) {
		middlecacti[i] = makeCactus(floor(random(width))); 
	}
	for (var i = 0; i < 3; i++) {
		foregroundcacti[i] = makeCactus(floor(random(width))); 
	}
	for (var i = 0; i < 100; i++) {
		shrubs[i] = makeShrub(random(width));
	}

}

//LANDSCAPES

function drawForeground() {
	noStroke();
	fill(223, 194, 140);
	beginShape();
	for (var x = 0; x <= width; x++) {
		var t = (x * ForegroundDetail) + (millis() * ForegroundSpeed);
		var y = map(noise(t), 0, 1, 2 * height/3, height);
		vertex(x,y);
		foregroundTerrain[x] = y;

	} 
	vertex(width, height);
	vertex(0, height);
	endShape();
	if (random(0, 1) < .003) {
		foregroundcacti.push(makeCactus(width))
	}
	for (var i = 0; i < foregroundcacti.length; i++) {
		foregroundcacti[i].move();
		foregroundcacti[i].foregrounddraw();
	}
}

function drawMiddleground() {
	noStroke();
	fill(210, 170, 100);
	beginShape();
	for (var x = 0; x <= width; x++) {
		var t = (x * MiddlegroundDetail) + (millis() * MiddlegroundSpeed);
		var y = map(noise(t), 0, 1, height/2, height);
		vertex(x,y);
		middleTerrain[x] = y;
	} 
	vertex(width, height);
	vertex(0, height);
	endShape();
	if (random(0, 1) < .005) {
		middlecacti.push(makeCactus(width))
	}
	for (var i = 0; i < middlecacti.length; i++) {
		middlecacti[i].move();
		middlecacti[i].middledraw();
	}
}

function drawBackground() {
	fill(230, 190, 90);
	noStroke();
	rect(0, 2 * height/3, width, height/3);

	if (random(0, 1) < .01) {
		buttes.push(makeButte(width))
	}
	for (var i = 0; i < buttes.length; i++) {
		buttes[i].move();
		buttes[i].draw();
	}
	if (random(0, 1) < .5) {
		shrubs.push(makeShrub(width))
	}
	for (var i = 0; i < shrubs.length; i++) {
		shrubs[i].move();
		shrubs[i].draw();
	}
}

//REMOVE UNUSED OBJECTS

function removeButtes() {
	var buttesToKeep = [];
	for (var i = 0; i < buttes.length; i++) {
		if (buttes[i].x + buttes[i].breadth > 0)
			buttesToKeep.push(buildings[i]);

	}
	buttes = buttesToKeep;
}

function removemiddleCacti() {
	var middlecactiToKeep = [];
	for (var i = 0; i < middlecacti.length; i++) {
		if (middlecacti[i].x > 0)
			middlecactiToKeep.push(middlecacti[i]);

	}
	middlecacti = middlecactiToKeep;
}

function removeforegroundCacti() {
	var foregroundcactiToKeep = [];
	for (var i = 0; i < foregroundcacti.length; i++) {
		if (foregroundcacti[i].x > 0)
			foregroundcactiToKeep.push(foregroundcacti[i]);

	}
	foregroundcacti = foregroundcactiToKeep;

}

//BUTTES

function butteMove() {
	this.x += this.speed;
}

function drawButte() {
	beginShape();
	vertex(this.x + this.breadth, 2 * height/3);
	vertex(this.x + this.breadth, 2 * height/3);
	vertex(this.x + this.breadth - 10, (2 * height/3) - this.tall);
	vertex(this.x + 10, (2 * height/3) - this.tall);
	vertex(this.x, 2 * height/3);
	endShape();
	
}

function makeButte(birthlocationX) {
	var butte = {x: birthlocationX,
				breadth: random(40, 150),
				tall: random(10, 30),
				speed: -1,
				move: butteMove,
				draw: drawButte}
	return butte;
}

//VEGETATION

function cactusMove() {
	this.x -= 1;
}

function drawmiddleCactus() {
	strokeWeight(10);
	stroke('green');
	line(this.x, middleTerrain[this.x], this.x, middleTerrain[this.x] - this.height);
	for (i = 0; i < this.limbs; i++) {
		if (i%2 == 0) {	
			line(this.x - 10, middleTerrain[this.x] - this.height/(1.25 * i) - 15, this.x, middleTerrain[this.x] - this.height/(1.25 * i));
		} else {
			line(this.x + 10, middleTerrain[this.x] - this.height/(1.25 * i) - 15, this.x, middleTerrain[this.x] - this.height/(1.25 * i));

		}
	}
	noStroke();
	if (this.flowercolor < .3) {
		fill(236, 96, 160);
	} else if (this.flowercolor > .3 & this.flowercolor < .6) {
		fill(255, 255, 0);
	} else {
		noFill();
	}
	push();
	translate(this.x, middleTerrain[this.x] - this.height);
	rotate(-90);
	for (i = 0; i < 3; i++) {
		angleMode(DEGREES);
		var angle = 45;
		rotate(angle);
		angle += 45 * i;
		ellipse(0, -5, -7, 15);
	}
	pop();
	

}

function drawforegroundCactus() {
	strokeWeight(10);
	stroke('green');
	line(this.x, foregroundTerrain[this.x], this.x, foregroundTerrain[this.x] - this.height);
	for (i = 0; i < this.limbs; i++) {
		if (i%2 == 0) {	
			line(this.x - 10, foregroundTerrain[this.x] - this.height/(1.25 * i) - 15, this.x, foregroundTerrain[this.x] - this.height/(1.25 * i));
		} else {
			line(this.x + 10, foregroundTerrain[this.x] - this.height/(1.25 * i) - 15, this.x, foregroundTerrain[this.x] - this.height/(1.25 * i));
		}
	}
	noStroke();
	if (this.flowercolor < .3) {
		fill(236, 96, 160);
	} else if (this.flowercolor > .3 & this.flowercolor < .6) {
		fill(255, 255, 0);
	} else {
		noFill();
	}
	push();
	translate(this.x, foregroundTerrain[this.x] - this.height);
	rotate(-90);
	for (i = 0; i < 3; i++) {
		angleMode(DEGREES);
		var angle = 45;
		rotate(angle);
		angle += 45 * i;
		ellipse(0, -5, -7, 15);
	}
	pop();
}

function makeCactus(locationX) {
	var cactus = {x: locationX,
				height: random(20, 70),
				limbs: floor(random(1, 4)),
				middledraw: drawmiddleCactus,
				foregrounddraw: drawforegroundCactus,
				move: cactusMove,
				flowercolor: random(0, 1)}
	return cactus;
}

function shrubMove() {
	this.x += this.speed
}

function drawShrub() {
	fill(50, 100, 100);
	ellipse(this.x, this.y, 3, 3);
}

function makeShrub(locationX) {
	var shrub = {x: locationX, y: random(2 * height/3, height),
				speed: -1,
				draw: drawShrub,
				move: shrubMove}
	return shrub;
}

function draw() {
    background("skyblue");
    drawBackground();
    drawMiddleground();
	drawForeground();

}

For my landscape I was inspired by driving through New Mexico this summer. Unfortunately I could not figure out how make the cacti move at the same speed as the landscape. I borrowed the code for the landscape from the class website and I think maybe if I understood how that worked a little better I might have been able to make the speeds match. I will keep thinking about it. Other than that, I thought this project went pretty well. I’m glad I was finally able to figure out objects, even at a pretty basic level. I still find them confusing but I can use them!

rgroves – Looking Outwards – 10


Digital Death by Claudia Heart is an animated installation reflecting on the lifespan of computer art. As soon as such a work is created, it starts to become outdated and is threatened by bugs and glitches. In her animation, she uses a biological growth algorithm to imagine a tree growing and ungrowing at the same time. Throughout the animation, certain clumps of leaves on the tree twitch rapidly, evoking the idea of glitches. When the tree is fully grown, the trunk starts to disappear from the bottom, then the inner leaves, then finally all that’s left is a thin layer of outer light pink leaves in a sphere like a dandelion. Then they too vanish.

I like how simple the execution of this idea was. She simply used one growth algorithm but had time be both increasing and decreasing. I also think it represents the the artist’s concept very well. It’s a simple metaphor, but the contrast of representing a condition of tech art using an organic form is very striking.


http://www.claudiahart.com/portfolio/digitaldeath/

rgroves – Project09 – Portrait

sketch

var Will;

function preload() {
	var URL = "https://i.imgur.com/sdnZ6UU.jpg"
	Will = loadImage(URL);
}

function setup() {
    createCanvas(360, 480);
    background(120, 212, 204);
    Will.loadPixels();
    frameRate(3000);
}

function draw() {
	var px = random(0, width);
    var py = random(0, height);
    var ix = floor(px);
    var iy = floor(py);
    var color = Will.get(ix, iy);
    stroke(color);
    if (dist(px, py, 190, 320) < 10) { //centered at nose
    	line(px + 15, py + 15, 190, 320);
    } else {
    	line(lerp(190, px, .9), lerp(320, py, .9), px, py);
    }
}

For this project I used a picture of my friend Will. Because it’s a funny picture, I wanted to create a funny way to generate it. I decided to use lines that radiate out from his nose, which looks really big at this angle. I changed the background color after I took this screenshot, but this is what it looks like after you let it run for a while. I like how not only do the lines point to his nose, but they get longer as they get father away. It gives the picture a cool exploding effect.

This is photograph I used.

 

rgroves – Looking Outwards 09

For this Looking Outwards I read Isadora Krsek’s post about Giorgia Lupi and Stephanie Posavec’s eyeo talk, which focused on their year long project Dear Data. She did a great job going into detail about the two artist’s backgrounds and careers, which helped explain why the two would be so attracted to collaborating with each other. They are both extremely successful and knowledgable in the fields of design and data representation, and all that combined experience allowed this project to become something really beautiful. The only thing I would change from Isadora’s post would be to include some pictures of the postcards, which are incredibly beautiful, intricate, and painstaking. It’s also fascinating how the two of them come up with methods of representing the same kinds of data. Sometimes they come up with very similar methods, like in drawing that represents times they loved their SOs versus times they were annoyed by them:

Other times, like in these drawings which track all the times the two artists complained, it’s impossible to tell that the two drawings represent the same kind of data.

Considering they made 52 postcards, this project is an absolute goldmine of inspiration for anyone interested in data or data art.

I should also mention that I love the double meaning of the title, which both references the medium of postcards and the love the artists have for data itself.

https://courses.ideate.cmu.edu/15-104/f2017/author/ikrsekandrew-cmu-edu/

rgroves – Looking Outward – 08

I watched Darius Kazemi’s talk on harnessing the power of infinity when making art with code. Kazemi is what he calls an “internet artist,” making a huge quantity of simple projects, mostly bots, parodying pop culture, the news, and internet memes. He begins his lecture by demonstrating that by writing only a couple lines of code, he can generate an infinite list of random numbers – more content than a human can consume in a lifetime. He then presents a formula for translating this power into meaningful art: “Templated Authorship + Random Input + Context.” He goes on to explain how his popular twitter bot Two Headlines uses this formula to create effective content. It takes current headlines and swaps the most important phrase in the headline with a different news topic. The new headlines are funny because they satirize stories that are already being talked about a lot and often the words that are switched out create a new meaning that is unexpectedly pertinent. Using the same template on Shakespeare titles or very old headlines would not be as funny because they would not be relevant – that’s where the “context” part of the formula comes in.
He has made an absolutely vast quantity of twitter bots and even though they are all quite simple, they are still effective and funny because of this formula.

 

http://tinysubversions.com/