I take references from this animation/rendering competition and made this robot pushing a sphere in an alien planet:
I have trees generation in the background
boulders in front
and hills in the back
/*
* Andrew J Wang
* ajw2@andrew.cmu.edu
* Section A
*
* This Program is walking
*/
//sets of links
//location of feets of the walking person
var pointXG = 0;
var pointYG = 0;
//steps (frame) locations of the feets
var stepsX = [0,1,2,3,4,5,6,7,8,9,10,10,10,10,10,10,9,8,7,6,5,4,3,2,1,0];
var stepsY = [0,0.5,1,1.5,2,2.5,3,3.5,4,4.5,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0];
//counters for multiple frames (feet + mountains)
var counter = 0;
//location of the person on the drawing
var locationX = 120;
var locationY = 200;
//arrays for trees for clusters of boulders
var trees = [];
var clusters = [];
//set a array for land heights (FROM PREVIOUS ASSIGNMENT)
var landHeight = [];
var landHeight2 = [];
//create noice parameter and steps
var noiseParam = 0;
var noiseParam2 = 0;
var noiseStep = 0.005;
var noiseStep2 = 0.01;
function setup() {
createCanvas(480,300);
// create an initial collection of trees
for (var i = 0; i < 5; i++){
var rx = random(width);
trees[i] = makeTrees(rx);
}
// create an initial collection of boulders
for (var i = 0; i < 10; i++)
{
var rx2 = random(width);
clusters[i] = makeClusters(rx2);
}
//hill #1
for (var k=0; k<=480; k++)
{
//get noise through noise param
var n = noise(noiseParam);
//remapping based on height
var value = map(n,0,1,0,height/4)+130;
//add to array
landHeight.push(value);
//plus steps
noiseParam += noiseStep;
}
//hill #2
for (var k=0; k<=480; k++)
{
//get noise through noise param
var n2 = noise(noiseParam2);
//remapping based on height
var value2 = map(n2,0,1,0,height/3)+80;
//add to array
landHeight2.push(value2);
//plus steps
noiseParam2 += noiseStep2;
}
}
function draw() {
background(100);
//MOON
push();
noStroke();
fill(255,255,220);
ellipse(380,0,250,250);
pop();
//draw first sets of hill
push();
noStroke();
fill(240);
beginShape();
//fist vertex
vertex(0,(locationY+70+60)*0.8-80);
//for loop to grab all the vertex
for (var k=0; k<=480; k++)
{
vertex(k,landHeight2[k]);
}
//last vertex
vertex(width,(locationY+70+60)*0.8-80);
endShape(CLOSE);
//adding another point by shifting
var n2=noise(noiseParam2);
var value2 = map(n2,0,1,0,height/3)+80;
noiseParam2 += 0.01/20;
//slowing the speed of refreshing by using a counter
if (counter%40==0)
{
landHeight2.shift();
landHeight2.push(value2);
}
pop();
//draw second sets of hill
push();
noStroke();
fill(220);
beginShape();
//fist vertex
vertex(0,(locationY+70+60)*0.8-80);
//for loop to grab all the vertex
for (var k=0; k<=480; k++)
{
vertex(k,landHeight[k]);
}
//last vertex
vertex(width,(locationY+70+60)*0.8-80);
endShape(CLOSE);
//adding another point by shifting
var n=noise(noiseParam);
var value = map(n,0,1,0,height/4)+130;
noiseParam += 0.005/5;
//slowing the speed of refreshing by using a counter
if (counter%10==0)
{
landHeight.shift();
landHeight.push(value);
}
pop();
//ground plane
push();
noStroke();
fill(200);
rect(0,(locationY+70+60)*0.8-80,width, height-((locationY+70+60)*0.8-80));
pop();
//set trees and clusters by refreshing the removed objects and clusters
updateDisplay();
removeTrees();
addTrees();
removeClusters();
addClusters();
//walking person
strokeWeight(3);
push();
//scaling it
scale(0.6);
translate(0,150);
walking(locationX,locationY);
walking2(locationX,locationY);
body(locationX,locationY);
//butt
push();
strokeWeight(2);
ellipse(locationX,locationY,15,15);
pop();
pop();
//display clusters in the end
updateDisplay2();
}
//refreashing trees and display them
function updateDisplay(){
for (var i = 0; i < trees.length; i++){
trees[i].move();
trees[i].display();
}
}
//refreshing boulders and display them
function updateDisplay2(){
for (var i = 0; i < clusters.length; i++){
clusters[i].move();
clusters[i].display();
}
}
//removing trees if it is too far away from the screen
function removeTrees(){
var treesToKeep = [];
for (var i = 0; i < trees.length; i++){
if (trees[i].x + trees[i].breadth > 0) {
treesToKeep.push(trees[i]);
}
}
}
//removing boulders if it is too far away from the screen
function removeClusters(){
var clustersToKeep = [];
for (var i = 0; i < clusters.length; i++){
if (clusters[i].x + clusters[i].breadth > 0) {
clustersToKeep.push(clusters[i]);
}
}
}
//add trees 100 units away from border
function addTrees() {
var Likelihood = 0.01;
if (random(0,1) < Likelihood) {
trees.push(makeTrees(width+100));
}
}
//add boulders 500 units away from border
function addClusters() {
var Likelihood = 0.01;
if (random(0,1) < Likelihood) {
clusters.push(makeClusters(width+500));
}
}
//set trees values and function
function makeTrees(birthLocationX) {
var tree = {x: birthLocationX,
breadth: 100,
speed: -0.4,
y: 160+round(random(20)),
treeHeight: round(random(40,50)),
size: round(random(30,50)),
move: objectMove,
display: treeDisplay}
return tree;
}
//set boulders values and functions
function makeClusters(birthLocationX) {
var tree = {x: birthLocationX,
breadth: 100,
speed: -2.0,
treeHeight: round(random(40,50)),
size: round(random(200,350)),
move: object2Move,
display: clusterDisplay}
return tree;
}
//move objects
function objectMove() {
this.x += this.speed;
}
function object2Move() {
this.x += this.speed;
}
//draw trees
function treeDisplay() {
line(this.x, this.y , this.x, this.y+this.treeHeight);
push();
translate(this.x,this.y);
rectMode(CENTER);
noFill();
strokeWeight(1);
push();
rotate(-counter/180*Math.PI);
rect(0,0,this.size,this.size);
pop();
push();
rotate(counter/180*Math.PI);
rect(0,0,this.size-10,this.size-10);
pop();
pop();
}
//draw bolders
function clusterDisplay() {
push();
fill(0);
ellipse(this.x,height+30,this.size,this.size/2);
strokeWeight(1.5);
noFill();
ellipse(this.x,height+30,this.size+20,this.size/2+10);
pop();
}
//leg #1
function walking(xL,yL)
{
//counter/10 get frame number
var counterK = Math.floor(counter/10)%(stepsX.length);
//Feet locations
pointXG = xL-70+stepsX[counterK]*6;
pointYG = yL+70-stepsY[counterK]*4;
//Pathegorean theorm to get the knee and legs
var dis = Math.sqrt((xL-pointXG)*(xL-pointXG)+(yL-pointYG)*(yL-pointYG));
var num = (10000)-(dis*dis);
var sid = sqrt(num);
var midX = xL-(xL-pointXG)/2;
var midY = yL-(yL-pointYG)/2;
var tan = atan2(pointXG-xL,pointYG-yL);
ellipse ((pointXG-xL)/2+xL+cos(tan)*sid/2, (pointYG-yL)/2+yL-sin(tan)*sid/2, 5,5);
line(xL,yL,(pointXG-xL)/2+xL+cos(tan)*sid/2, (pointYG-yL)/2+yL-sin(tan)*sid/2);
line(pointXG,pointYG,(pointXG-xL)/2+xL+cos(tan)*sid/2, (pointYG-yL)/2+yL-sin(tan)*sid/2);
//feet bending
if (stepsY[counterK]==0)
{
line(pointXG,pointYG,pointXG+20,pointYG);
}
else
{
var tanF = atan2(Math.sqrt(400-stepsY[counterK]*2),stepsY[counterK]*4);
line(pointXG,pointYG,pointXG+20*sin(tanF),pointYG+20*cos(tanF));
}
counter++;
}
//repeat for the second leg
function walking2(xL,yL)
{
var counterK = (Math.floor(counter/10)+stepsX.length/2)%(stepsX.length);
pointXG = xL-70+stepsX[counterK]*6;
pointYG = yL+70-stepsY[counterK]*4;
var dis = Math.sqrt((xL-pointXG)*(xL-pointXG)+(yL-pointYG)*(yL-pointYG));
var num = (10000)-(dis*dis);
var sid = sqrt(num);
var midX = xL-(xL-pointXG)/2;
var midY = yL-(yL-pointYG)/2;
var tan = atan2(pointXG-xL,pointYG-yL);
ellipse ((pointXG-xL)/2+xL+cos(tan)*sid/2, (pointYG-yL)/2+yL-sin(tan)*sid/2, 5,5);
line(xL,yL,(pointXG-xL)/2+xL+cos(tan)*sid/2, (pointYG-yL)/2+yL-sin(tan)*sid/2);
line(pointXG,pointYG,(pointXG-xL)/2+xL+cos(tan)*sid/2, (pointYG-yL)/2+yL-sin(tan)*sid/2);
if (stepsY[counterK]==0)
{
line(pointXG,pointYG,pointXG+20,pointYG);
}
else
{
var tanF = atan2(Math.sqrt(400-stepsY[counterK]*2),stepsY[counterK]*4);
line(pointXG,pointYG,pointXG+20*sin(tanF),pointYG+20*cos(tanF));
}
counter++;
}
//body parts and other stuff
function body(xL,yL)
{
var counterK = (Math.floor(counter/10)+stepsX.length/2)%(stepsX.length);
var counterK2 = (Math.floor(counter/10)+10)%(stepsX.length);
var counterK3 = (Math.floor(counter/10)+25)%(stepsX.length);
push();
strokeWeight(2);
fill("grey")
//shoulder 1
ellipse(xL+35+stepsY[counterK2],yL-45-stepsX[counterK2],30,30);
//hand
ellipse(xL+35+60,yL-45-stepsX[counterK]+10,10,10);
pop();
//arms
line(xL+35+stepsY[counterK],yL-45-stepsX[counterK],xL+35+30,yL-45-stepsX[counterK]+20);
line(xL+35+30,yL-45-stepsX[counterK]+20,xL+35+60,yL-45-stepsX[counterK]+10);
//body
line(xL,yL,xL+35+stepsY[counterK],yL-45-stepsX[counterK]);
push();
fill("black");
ellipse(xL+35+30,yL-45-stepsX[counterK]+20,5,5);
pop();
//Round thingy
push();
noFill();
strokeWeight(2);
ellipse(xL+35+175,yL-45,230,230);
fill(255);
ellipse(xL+35+175,yL-45,220,220);
stroke(255);
pop();
//shoulder 2
push();
noStroke();
ellipse(xL+35+stepsY[counterK2],yL-45-stepsX[counterK2],15,15);
pop();
//head
push();
strokeWeight(1);
noFill();
translate(xL+55+stepsY[counterK3],yL-85-stepsX[counterK3]);
rectMode(CENTER);
rotate(-counter/180*Math.PI);
rect(0,0,40,40);
rect(0,0,30,30);
pop();
push();
strokeWeight(1);
noFill();
translate(xL+65+stepsY[counterK2]*2,yL-95-stepsX[counterK2]);
rectMode(CENTER);
rotate(counter/180*Math.PI);
rect(0,0,25,25);
rect(0,0,30,30);
pop();
push();
strokeWeight(1);
noFill();
translate(xL+45+stepsY[counterK]*2,yL-75-stepsX[counterK]);
rectMode(CENTER);
rotate(counter/180*Math.PI);
rect(0,0,25,25);
rect(0,0,15,15);
pop();
}
]]>Link: https://www.plagiarismtoday.com/2021/03/16/nfts-and-copyright/
By reading this article, I understand how NFTs really work. So, according to this article owning an NFT doesn’t necessarily mean someone actually owns the copyright of this art piece. However, it isn’t completely useless, as NFTs can also be considered as an internet-signed copy of the work. Because of the fact that the NFTs function as a signed copy of the original art piece, they can help the producers financially. On the other hand, some people who didn’t create those works can also tokenize those works can really damage the career of the artists who actually created those works. In other words, NFT platforms not only provide an easier way to allow society to donate and help digital artists but also create an opportunity for those who are even involved in any art creation process to drain money from those creators. However, in a few years, courts will eventually be involved in such cases to protect those artists eventually.
CITATION:
Bailey, J. (2021, March 16). NFTs and copyright. Plagiarism Today. Retrieved November 19, 2022, from https://www.plagiarismtoday.com/2021/03/16/nfts-and-copyright/
]]>Sanic make “dash” noises every now and then
Eggman has “intro” and “escape” lines
Rings make sounds when grabbed by sanic
Knuckle makes sounds in the end
/*
* Andrew J Wang
* ajw2@andrew.cmu.edu
* Section A
*
* This Program is Sanic
*/
//rotation variables for limb movements for sanic and the coins
var rot = 0;
//controls whether the limbs are moving forwards or backwards
var forward = true;
//sanic locations
var x=0;
//eggman image
var egg;
//eggman Ylocation
var eggY = -150;
//uganda knuckle's Ylocation
var ugandaY = 450;
//Green Hill Zone notes (BACKGROUND MUSIC)
var pitch = [72,69,72,71,72,71,67, 0, 69,76,74,72,71,72,71,67, 0, 72,69,72,71,72,71,67, 0, 69,69,65,69,67,69,67,60, 0];
var duration = [3,9,3,9,3,9,12, 15, 3,3,9,3,9,3,9,12, 15, 3,9,3,9,3,9,12, 15, 3,3,9,3,9,3,9,12, 15];
//counter for durations
var counter = 0;
//which note on the pitch list to play
var note = 0;
//rings' existance
var coin = [true,true,true,true,true];
//sound variables
var eggmanIntro;
var ringSound;
var dawae;
var spinDash;
var eggmanDefeat
//https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/name-eggman.wav
//https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/Sonic_Ring_Sound_Effect.wav
//https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/do-you-know-the-way.wav
//https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/Spin.wav
//https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/no.wav
//loading the images and sounds
function preload() {
egg = loadImage("https://i.imgur.com/Wy46mQF.png");
uganda = loadImage ("https://i.imgur.com/HRB5kdy.png");
eggmanIntro = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/name-eggman.wav");
ringSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/Sonic_Ring_Sound_Effect.wav");
dawae = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/do-you-know-the-way.wav");
spinDash = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/Spin.wav");
eggmanDefeat = loadSound ('https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/no.wav');
}
//setups Don't think I need to elaborate
function setup() {
createCanvas(600,300);
useSound();
frameRate(20);
}
function soundSetup() {
osc = new p5.Oscillator();
osc.amp(0.25);
eggmanIntro.setVolume(1.0);
ringSound.setVolume(0.5);
dawae.setVolume(0.5);
spinDash.setVolume(0.5);
eggmanDefeat.setVolume(1.0);
osc.setType('square');
osc.start();
}
function draw() {
background(255);
//rotation till 1 then change directions
if (rot>=1 || rot <=-1)
{
forward = !forward;
}
if (forward)
{
rot+=0.1;
}
else
{
rot-=0.1;
}
//move sanic by 1 per frame
x+=1;
//check whether sanic ran pass through those rings or not
for (var k=0; k<5; k++)
{
if (x>(100+k*100))
{
coin[k] = false;
}
}
//if sanic is on the ring play ring sound
if (x%100==0 & x<600 && x>0)
{
ringSound.play();
}
//sanic spins every now and then if he's on the screen
if (x%100==50 & x<=600 && x>=0)
{
spinDash.play();
}
//rings
ring(100,170,rot,coin[0]);
ring(200,170,rot,coin[1]);
ring(300,170,rot,coin[2]);
ring(400,170,rot,coin[3]);
ring(500,170,rot,coin[4]);
//eggman shows up
if (eggY<50)
{eggY+=2;}
//eggman "escapes"
if (x>300 & eggY<1000)
{
eggY = 50 + (x-300) * (x-300);
}
//eggman intro right before he stops
if (eggY==48)
{
eggmanIntro.play();
}
//eggman says no moment after he's defeated
if (eggY==54)
{
eggmanDefeat.play();
}
//eggman image
eggman(300,eggY);
//sanic
sanicLimbs(x,100,rot);
sanic(x,100);
//uganda knuckle shows up
if (x>700 & ugandaY > 200)
{
ugandaY -=2;
}
//"DO YOU KNOW DA WAE" before stoping
if (ugandaY==202)
{
dawae.play();
}
//kunckle
knuckle(300,ugandaY);
//if pitch is 0 stop playing
if (pitch[note] == 0)
{
osc.stop();
}
//if pitch before is 0 but this note isn't restart
else if (pitch[note-1] == 0 & pitch[note] != 0)
{
osc.start();
}
//play notes
osc.freq(midiToFreq(pitch[note]));
//duration counter ++
if (counter < duration[note] & note < pitch.length)
{
counter++
}
//if reach max duration change note and reset
else if (counter >= duration[note] && note < pitch.length)
{
counter = 0;
note++;
}
//if reach the end restart from the beginning to loop
else
{
note=0;
}
}
//drawing sanic
function sanic(xL,yL)
{
push();
translate(xL,yL);
noStroke();
stroke(0);
fill("blue");
curve(-10,100,-7,-10,-50,-30,-50,50);
curve(-10,100,-7,10,-50,10,-50,50);
curve(-10,100,-7,30,-65,20,-50,100);
curve(-10,100,-7,40,-50,30,-50,50);
curve(-10,100,-7,90,-75,70,-50,200);
strokeWeight(1);
ellipse(0,25,10,20);
ellipse(0,0,50,45);
ellipse(0,70,70,75);
fill(255,255,170);
ellipse(0,70,40,45);
ellipse(3,15,25,10);
fill(255);
ellipse(10,0,15,13);
ellipse(-8,0,15,10);
fill(0);
ellipse(12,0,3,3);
ellipse(-6,0,3,3);
ellipse(0,8,4,4);
stroke(5);
curve(-7,5,-7,15,16,15,16,5);
pop();
}
//drawing sanic's llimbs
function sanicLimbs (xL,yL,r)
{
push();
translate(xL,yL);
push();
translate(15,50);
rotate(r);
fill("blue");
beginShape();
vertex(0, 0);
bezierVertex(0,0,30,-50,60,0);
bezierVertex(60,0,30,-25,0,0);
endShape();
fill(255);
ellipse(60,0,20,20);
pop();
push();
translate(-15,60);
rotate(r);
fill("blue");
beginShape();
vertex(0, 0);
bezierVertex(0,0,-30,-55,-60,0);
bezierVertex(-60,0,-30,-15,0,0);
endShape();
fill(255);
ellipse(-60,0,30,25);
pop();
push();
translate(0,100);
rotate(r);
fill("blue");
beginShape();
vertex(0, 0);
bezierVertex(0,0,-60,0,-60,60);
bezierVertex(-60,60,-60,40,0,0);
endShape();
fill("red");
ellipse(-70,60,40,20);
pop();
push();
translate(20,100);
rotate(r);
fill("blue");
beginShape();
vertex(0, 0);
bezierVertex(0,0,0,40,60,60);
bezierVertex(60,60,0,80,0,0);
endShape();
fill("red");
ellipse(70,60,40,20);
pop();
pop();
}
//ring spins through scalling
function ring (xR,yR,sc,sh)
{
if (sh==true)
{
push();
translate(xR,yR);
scale(sc,1.0);
fill("gold");
ellipse(0,0,50,50);
fill(255);
ellipse(0,0,30,30);
pop();
}
}
function eggman (xE,yE)
{
image(egg,xE,yE,150,150);
}
function knuckle (xU, yU)
{
push();
imageMode(CENTER);
image(uganda,xU, yU, 250,250);
pop();
}
]]>The Image is based on how Octopus uses their camouflage:
So Basically I created a bunch of particles that ages and disappear eventually:
when those particles first appear they growth rapidly then they slowly shrink and fade away
Base Image:
/*
* Andrew J Wang
* ajw2@andrew.cmu.edu
* Section A
*
* This Program is Face
*/
//face image for preload the data
let faceImage;
//array of global particles
var particles = [];
//preload image
function preload(){
faceImage = loadImage("https://i.imgur.com/i3WmsKd.jpeg");
}
function particleStep() {
//age of the particles
this.age++;
//shrine slowly after 45 age
if (this.age % 2 == 0 & this.age >= 45)
{
this.sz = this.sz * 0.98;
}
//grow rapidly before 45 age
else if (this.age % 2 == 0 & this.age < 45)
{
this.sz = this.sz * 1.1;
}
}
function particleDraw() {
push();
//grab color based on the location on the image
var kolor = faceImage.get(this.x*2, 220+this.y*2);
fill(kolor);
noStroke();
rectMode(CENTER);
//create rectangle based on location size and color
rect(this.x, this.y, this.sz, this.sz);
pop();
}
//create color particles
function makeParticle(px, py, size) {
p = {x: px, y: py,
age: 0,
sz: size,
stepFunction: particleStep,
drawFunction: particleDraw
}
return p;
}
function setup() {
createCanvas(480,480);
frameRate(120);
}
function draw() {
background(220);
stroke(0);
//create 30 particles per fram just to fill the whole image with particles
for (var n=0; n<30; n++)
{
//create particles at random location on the canvas, origin size = 1
var p = makeParticle(random(480), random(480),1);
particles.push(p);
}
//new particles to refresh
newParticles = [];
for (var i = 0; i < particles.length; i++){ // for each particle
var k = particles[i];
//draw and refresh particles
k.stepFunction();
k.drawFunction();
if (k.age < 250) {
//if younger than 250 keep them if not they are gone
newParticles.push(k);
}
}
// particles refreshed by the new particles
particles = newParticles;
}
]]>I really admire Camille Utterback’s project Text Rain not because of the complexity of the program itself, but when the project is produced. First, I need to introduce who Camille is. She is an American Interactive Installation artist who graduated from William College and gained her master’s degree from the Interactive Telecommunications Program at New York University’s Tisch School of the Arts. Why I prefer her Text Rain installation is because her work is groundbreaking or one of the first of such type (Interactive Installation). Her work might not look impressive at our time, since her program is basically about capturing the silhouette of pedestrians and making random letters float on them. However, because of this “simple” (compared to nowadays interactive projects) installation, which was created during 1999, more and more interactive public installations that we might see on streets were created, making Camille Utterback a pioneer of such computational forms of art.
Text Rain – by Camille Utterback and Romy Achituv:
This week I watched the lecture of Jennifer Daniel, who is an American designer, editor, and illustrator, and she also leads the Emoji Subcommittee for the Unicode Consortium, while working for The New York Times and The New Yorker. What people might not know is that Jennifer initiated the gender-inclusive representation movement for the emoji creation group around the globe that shares the same sets of Unicodes for emojis. Among the new gender-inclusive emojis that she created, Mrs. Claus, Woman in Tuxedo, and Man in Veil are the most famous ones. I admire the movement because I think as we develop, we should make all aspects of our modern technology more inclusive for more and more people, to further facilitate our advances. To do this, she believes that we need more and more emojis that can better represent individuals, thus she and her team developed several emoji-related apps such as Emoji Kitchen. While introducing those emoji-related apps during her lecture, she started with the very core and basic definition and evolutions of emoji, then explained every issue of the emojis that we are using and why we should improve them, eventually demonstrating how her works can solve those problems. I enjoy watching her lecture because of how direct her approach to the topic is and how simple she made her works look to non-programmers.
Eyeo 2017 – Jennifer Daniel from Eyeo Festival on Vimeo.
Emoji Kitchen Examples:
Jennifer Daniel’s Website/Blogs: https://httpcolonforwardslashforwardslashwwwdotjenniferdanieldotcom.com/category/blog/
]]>It slowly draws a butterfly if u move your mouse from left to right!
/*
* Andrew J Wang
* ajw2@andrew.cmu.edu
* Section A
*
* This Program is ButterFly and Flower Curves
*/
function setup() {
createCanvas(480,480);
}
function draw() {
background(220);
//create constrain for the rest of the codes' mouse X and Y
var conY = constrain(mouseY,0,height);
var conX = constrain(mouseX,0,width);
//create two array sets for Flower's X and Y
var pointX2 = [];
var pointY2 = [];
//remapping A and B with mouse X and Y
//A => inner circle, B => outer circle
var a = map(conY,0,width,50,150);
var b = map(conX,0,width,5,15);
var h = 20;
//using for loop to get points
for (var k=0; k<=2000; k+=1)
{
//2 PI but 2000 points
var t=k/1000*Math.PI;
//epitrochoid formulas for X and Y
var xP2= width/2+((a+b)*Math.cos(t)-h*cos(((a+b)/b)*t));
var yP2= height/2+((a+b)*Math.sin(t)-h*sin(((a+b)/b)*t));
//push values to lists
pointX2.push(xP2);
pointY2.push(yP2);
}
//connect vertexes and close them
push();
noFill();
//stroke
stroke(0);
strokeWeight(5);
beginShape();
for (var k=0; k<=2000; k+=1)
{
vertex(pointX2[k],pointY2[k]);
}
endShape(CLOSE);
pop();
//connect vertexes and close them
push();
//no stroke only fill
fill(255,200,200);
strokeWeight(0);
beginShape();
for (var k=0; k<=2000; k+=1)
{
vertex(pointX2[k],pointY2[k]);
}
endShape(CLOSE);
pop();
//same logics but this time it is the butterfly curves
var pointX = [];
var pointY = [];
for (var k=0; k<=2400; k+=1)
{
//Mouse Y dictate how big the butterfly will be
var xP= width/2-map(conY,0,width,0,100)*Math.sin(k/100*Math.PI)*((Math.exp(Math.cos(k/100*Math.PI))) - (2*Math.cos(4*(k/100*Math.PI))) - (Math.pow(Math.sin((k/100*Math.PI)/12), 5)));
var yP= height/2-map(conY,0,width,0,100)*Math.cos(k/100*Math.PI)*((Math.exp(Math.cos(k/100*Math.PI))) - (2*Math.cos(4*(k/100*Math.PI))) - (Math.pow(Math.sin((k/100*Math.PI)/12), 5)));
pointX.push(xP);
pointY.push(yP);
}
//this time I use smaller circles to represent the curves
fill (90,map(conY,0,width,0,255),100);
stroke (90,map(conY,0,width,0,255),100);
//mouse X dictates how many circles
for (var k=0; k<=conX*4; k+=1)
{
circle (pointX[k],pointY[k],3);
}
}
]]>I really admire how Chris Harrison did his color flower, and the way he made his algorithm to create these sets of patterns is amazing and visually satisfying to look at. Although he didn’t specify how he made his algorithm, I can still guess a few of the steps that he took to make this work of art. First he made a set of point data within a boundary of a circle, and assigned values of those points based on the distance of them towards the center of the circle. Then, he used the points and the center of the circle to create vectors from the points and go away from the center of the circle. Eventually, based on hue value stored on each circle, they grab the name of the named color and list them on the vector using the color with the corresponding hue value, making this image a colored and worded art piece. Also, I love that he’s able to use the same algorithm to generate images not just circular but other shapes, such as spirals and others.
Link: https://www.chrisharrison.net/index.php/Visualizations/ColorFlower
]]>I really like June Lee’s Cubic Tower, and I found randomness in their design. The reason why I admire their work on using randomness in computational design (this time is Grasshopper), while the randomness is still controllable. For example, they use boundaries and populate geometry to get computed random points inside the extruded square base using seeds, then they are able to create smaller cubes with only 3 different sizes using the Octree functions, which creates cubes by determining how dense the points are in the area, to be the components of the tower. Even after creating the randomness (that is inside a boundary), they are still able to add details afterward by using functions that turn the mess into individual components. Even after creating the cluster of computer generated randomness, they are still able to split the randomness randomly to add different materials towards the final product. I was really amazed by their ability to fully control the randomness even after already initializing the random points.
Link:
https://www.youtube.com/watch?v=ETWWx88iXec
Explanation for this abstract clock:
/*
* Andrew J Wang
* ajw2@andrew.cmu.edu
* Section A
* Project-05
*
* This program draws clock
*/
//set randam numbers for the wavy lines of reflection of the sun
var rando = 0;
//set sin values for waving reed
var drR=0;
function setup() {
createCanvas(480,480);
background(255);
}
function draw() {
//get dates for hours, minutes, seconds,and miliseconds
var dt = new Date();
//get location for ducks (MINUTES)
var dx=480-dt.getMinutes()*8-dt.getSeconds()*8/60;
//get location for the sun (HOURS)
var dy=(18-dt.getHours()-dt.getMinutes()*1/60-dt.getSeconds()*1/3600)*300/12;
//background
background(80,50,180);
//create reflection of the sun
if (dy>-125 & dy<425)
{
sunReflection (dy);
push();
//hiding the additional parts above sea level
fill (80,50,180);
rect(100,200,280,100);
pop();
}
//show moon between 6PM to 6AM
if (dy<62)
{
moon (300+dy,125);
}
else if (dy>238)
{
moon ((dy-300),125);
}
//create moutains and their reflections
moutain(-50,300,150,100);
moutainReflection(-50,300,150,75);
moutain(50,300,110,50);
moutainReflection(50,300,110,37.5);
moutain(350,300,250,50);
moutainReflection(350,300,250,37.5);
//gradiant sky and sea
gradiantScreen (0,300);
gradiantScreenReverse (300,600);
//draw horizon
stroke(255);
strokeWeight(1);
line (0,300,width,300);
//set sun between 6AM to 6PM
if (dy>-125 & dy<425)
{
sun(dy,125);
}
//creating lands
land2(-100,480,500,50);
land(-200,480,400,75);
//creating clouds (SECONDS)
clouds();
//creating ducks
duck(dx,350);
duck(dx+480,350);
duck(dx-480,350);
//creating reeds
reed2();
reed();
}
//gradiant sky
function gradiantScreen (y1,y2)
{
//for loop changing alpha values for small rectangles
for (var k=0; k<(y2-y1); k++)
{
noStroke();
fill (255,220,220,150/(y2-y1)*k);
rect (0,y1+k,width,1);
}
}
//gradiant sea but the same as gradiant sky but in reverse
function gradiantScreenReverse (y1,y2)
{
for (var k=0; k<(y2-y1); k++)
{
noStroke();
fill (255,220,220,180/(y2-y1)*k);
rect (0,y2-k,width,1);
}
}
//creating sun
function sun (y,r)
{
fill(255,255,180);
//outline of the sun
strokeWeight(5);
stroke(255,255,230,50);
var angle = acos((300-y)/(r/2));
//make arc if parts of the sun is below horizon
if (300-y<=r/2)
{
arc (width/2,y,r,r,-(Math.PI/2-angle)+Math.PI ,2*Math.PI + (Math.PI/2-angle),OPEN);
}
//dont make arc if it is not
else
{
circle(width/2,y,r);
}
}
//creating moon same as sun but having a different arc/circle for the missing piece
function moon (y,r)
{
fill(255,255,180);
strokeWeight(0);
stroke(255,255,230,50);
var anglem1 = acos((300-y)/(r/2));
var anglem2 = acos((300-y+20/Math.sqrt(2))/(r/2-20));
if (Math.abs(300-y)<r/2)
{
arc (width/2,y,r,r,-(Math.PI/2-anglem1)+Math.PI ,2*Math.PI + (Math.PI/2-anglem1),OPEN);
//the missing piece
if (300-y+20/Math.sqrt(2)<=(r/2-20))
{
push();
fill(80,50,180);
arc (width/2+20/Math.sqrt(2),y-20/Math.sqrt(2),r-40,r-40,-(Math.PI/2-anglem2)+Math.PI ,2*Math.PI + (Math.PI/2-anglem2),OPEN);
pop();
}
else
{
push();
fill(80,50,180);
circle(width/2+20/Math.sqrt(2),y-20/Math.sqrt(2),r-40);
pop();
}
}
else
{
circle(width/2,y,r);
push();
fill(80,50,180);
//the missing piece
circle(width/2+20/Math.sqrt(2),y-20/Math.sqrt(2),r-40);
pop();
}
}
//mountain reflection using bezier
function moutainReflection(mx,y,w,h)
{
fill(0,0,255);
strokeWeight(0);
bezier(mx,y,mx,y+h,mx+w,y+h*2,mx+w,y);
}
//mountaini using benzier
function moutain(mx,y,w,h)
{
fill(0,0,255);
stroke(255,255,230,50);
strokeWeight(2);
bezier(mx,y,mx,y-h,mx+w,y-h*2,mx+w,y);
}
//making clouds
function clouds()
{
fill(255,255,255,75);
//getting seconds and milliseconds
var dt = new Date();
var x=dt.getSeconds()*8+dt.getMilliseconds()*0.008;;
var y=480;
push()
translate (0,30);
//original moving clouds
rect(-50+x,120,200,30,15);
rect(-70+x,155,150,20,10);
rect(-100+x,100,150,16,8);
//clones to make the animation look smooth
rect(-50+x+y,120,200,30,15);
rect(-70+x+y,155,150,20,10);
rect(-100+x+y,100,150,16,8);
rect(-50+x-y,120,200,30,15);
rect(-70+x-y,155,150,20,10);
rect(-100+x-y,100,150,16,8);
//original moving clouds
rect(200+x,20,250,30,15);
rect(350+x,50,150,20,10);
//clones to make the animation look smooth
rect(200+x-2*y,20,250,30,15);
rect(350+x-2*y,50,150,20,10);
rect(200+x-y,20,250,30,15);
rect(350+x-y,50,150,20,10);
//seconds indicator circles
fill(255);
circle(0+x,120,20);
circle(0+x-y,120,20);
circle(0+x+y,120,20);
pop();
}
//create reflection of the sun using noice function to make it expand
function sunReflection (y)
{
rando+=0.01;
push()
fill (255,255,255,180);
strokeWeight(0);
stroke (255,255,255,180);
rectMode(CENTER);
rect(width/2,300+(300-y)/2,noise(rando)*50+125,4,2);
rect(width/2,300+(300-y)/2+8,noise(rando*2)*50+75,4,2);
rect(width/2,300+(300-y)/2-8,noise(rando-1)*50+75,4,2);
rect(width/2,300+(300-y)/2+16,noise(rando-0.5)*50+40,4,2);
rect(width/2,300+(300-y)/2-16,noise(rando+0.5)*50+40,4,2);
pop()
}
//land darker
function land(mx,y,w,h)
{
fill(30,30,130);
noStroke();
bezier(mx,y,mx,y-h*2,mx+w,y-h,mx+w,y);
}
//land lighter
function land2(mx,y,w,h)
{
fill(75,75,190);
noStroke();
bezier(mx,y,mx,y-h*2,mx+w,y-h,mx+w,y);
}
//duck
function duck(x,y)
{
fill(30,30,130,180);
triangle (x-5,y,x-10,y+5,x-5,y+5);
triangle (x+5,y+5,x+5,y+10,x+35,y+10);
arc (x,y,10,10,Math.PI,2*Math.PI);
rect (x-5,y,10,10);
arc (x+15,y+10,40,25,0,PI,OPEN);
}
//reed
function reed()
{
//moving based on sin function
var dr = Math.sin(Math.PI*drR);
drR+=0.002;
push();
translate(100,500);
rotate(dr/20);
fill(180,120,30);
rect(-0,-200,10,80,5);
rect(3,-120,4,120);
fill(190,130,60);
rect(-40,-190,10,80,5);
rect(-37,-110,4,120);
fill(210,110,80);
rect(-20,-160,10,80,5);
rect(-17,-80,4,120);
pop();
}
//second types of reed (blue)
function reed2()
{
var dr = Math.sin(Math.PI*drR);
drR+=0.002;
push();
translate(50,500);
rotate(-dr/20);
fill(50,60,100);
rect(-0,-200,10,80,5);
rect(3,-120,4,120);
fill(30,70,100);
rect(-40,-190,10,80,5);
rect(-37,-110,4,120);
pop();
}
]]>