2. Looking Outwards 11: Societal Impacts of Digital Art

While reading the article ‘NFTs and Copyright’ I released the unethical use of art and artworks in the new digital world. In my opinion, obviously it isn’t right for an artwork to be sold off at an online auction without the consent of the artist, but that won’t cloud the reality that it happens, more so now than before the boom of the internet. Reading about the impact NFTs have had on this was awakening and it made me wonder as an artist if it is even right to put out your work on digital platforms where anyone can access it and potentially illegally sell it and make money. Although NFTs are a great source for artists to earn money as it has opened up an entirely new avenue of revenue generation for artists. I was amazed to learn about how NFTs operate and how the token is for copyright and ownership, however, it is kind of terrifying to hear and learn how unethically it can be used. I honestly do not know if this problem could be curbed, but I sincerely hope that they introduce more rigorous checks to ensure that the artwork’s token is the right copyright holder of that piece, as it sounds like an interesting avenue for new generation artists.

Link

Project 11 – Moving Landscape

The project is a relaxing view of sunset in an air balloon – if you take the time to watch the full animation, you can see the colors of the sky, sun, and clouds change as well through gradual RGB changes and color theory. I wanted a lowpoly style animation, and worked to get effect through the “shifting clouds”

sketch
//Aarnav Patel
//aarnavp@andrew.cmu.edu
//Section D

var r = 140;
var g = 200;
var b = 230;
var cloudR = 255;
var cloudG = 255;
var cloudB = 255;
var sunX;
var sunY = 0; 
var sunR = 255;
var sunG = 247;
var sunB = 197;
var sunSize = 50;


var airBalloons = [];
var clouds = [];
var sceneCount = 0;
var bPics = ["https://i.imgur.com/El159Qi.png", "https://i.imgur.com/Inz2K7i.png", "https://i.imgur.com/IjQkLRr.png"]
var balloons = []

function preload() {
	//load the images
	for (var i = 0; i < bPics.length; i++) {
		balloons.push(loadImage(bPics[i]));
	}
}

function setup() {
    createCanvas(480, 200);
    sunX = width;
  	frameRate(10);

}

function draw() {

	var sky = color(r, g, b);
	fill(sky);
	rect(0, 0, width, height);


	//sky color change
	if (r < 255) {
		r += 0.1

	} 
	if (g > 150) {
		g -= 0.1;

	} 
	if (b > 87) {
		b -= 0.1;

	}

	//sky grandient
	for (var i = 0; i < 50; i+= 0.5) {
		stroke(r + i, g + i, b + i);
		var amount = map(i * 2, 0, 100, height * 0.75, height);
		line(0, amount, width, amount);
	}

	//SUN 
	if (sunR > 242) {
		sunR -= 0.1;
	}
	if (sunG > 60) {
		sunG -= 0.1;
	}
	if (sunB > 10) {
		sunB -= 0.1;
	}

	noStroke();
	fill(sunR, sunG, sunB);
	ellipse(sunX, sunY, sunSize, sunSize)

	sunX -= 0.25;
	sunY += 0.1;
	sunSize += 0.01;


	//cloud color change
	if (cloudR >= 244) {
		cloudR -= 0.05;
	}
	if (cloudG >= 223) {
		cloudG -= 0.05;
	} 
	if (cloudB > 208) {
		cloudB -= 0.05;
	}
	generateClouds();
	generateAirBalloons();


	updateClouds();
	updateBalloons();
	sceneCount++;

}

function makeCloud(stormCloud) {
	var cloud = {
		cX: random(0, 1.5 * width), cY: random(0, height), cDx:0, 
		cW: random(100, 300), 
		isStorm: stormCloud,
		show: drawCloud, 
		move: moveCloud, 
	}
	return cloud;
}


function drawCloud() {
	noStroke();
	var xInterval = this.cW / 8; //makes sure the x points never exceed the assigned cloudWidth
	var xPoint = this.cX
	var yPoint = this.cY

	//foreground clouds are lightest
	if (this.cW > 200) {
		this.cDx = 5;
		fill(cloudR, cloudG, cloudB, 255);
	} else if (this.cW > 100){	//midGround are slightly opaque
		fill(cloudR, cloudG, cloudB, 200)
		this.cDx = 3;
	} else {
		fill(cloudR, cloudG, cloudB, 100);	//background are most opaque
		this.cDx = 1;
	}
	//checks if its storm cloud
	if (this.isStorm) {
		fill(200, 255);
		
	}


	//generating points for the lowPoly Clouds
	var y = [yPoint, yPoint - 15, yPoint - 20, yPoint - 15, yPoint, yPoint + 15, yPoint + 20, yPoint + 15];
	//Y points are fixed
	var x = [xPoint];
	for (var i = 0; i < 8; i++) {
		if (i < 4) {
			xPoint += xInterval
		} else {
			xPoint -= xInterval
		}
		x.push(xPoint);
		

	}


		//gives animating effect
		for (var i = 0; i < x.length; i++) {
			x[i] += random(-5, 5);
			y[i] += random(-5, 5);
		}



	//draw cloud based on array made
	beginShape();
	for (var i = 0; i < x.length; i++) {
		vertex(x[i], y[i]);
	}
	endShape(CLOSE);

}


function moveCloud() {
	//updates cloudX by its speed
	this.cX -= this.cDx;

	//when cloudX is off left of screen, assigns it new position
	if (this.cX + this.cW < 0) {	//checks right side of cloud
		this.cX = random(width, 1.5 * width);
		this.cY = random(0, height / 1.5);
	}
}


function updateClouds() {
	//moves all the clouds from global cloud array
	for (var i = 0; i < clouds.length; i++) {
		clouds[i].move();
		
	}
}

function generateClouds() {
	//creates clouds with a 1/8 chance of a cloud being a storm cloud
	var isStorm = false;
	for (var i = 0; i < 15; i++) {
		
		if (amount = Math.floor(random(1, 8)) == 2) {
			isStorm = true;
		}
    	var c = makeCloud(isStorm);
    	clouds.push(c);
    	clouds[i].show();
    	isStorm = false;
    }
}

function generateAirBalloons() {
	//generates air balloons from image I have
	for (var i = 0; i < 10; i++) {
		var b = makeBalloon()
		airBalloons.push(b);
		airBalloons[i].show();
	}
}

function makeBalloon() {
	var b = {
		bX: random(0, width), bY: random(height * -5, height),
		bDx: Math.floor(random(-4, 4)), bDy: Math.floor(random(2, 4)),
		bImage:  Math.floor(random(0, 3)),	//ranodm number to select the type of balloon image
		ratio: Math.floor(random(0, 2)),
		show: drawBalloon, 
		float: floatBalloon,
	}

	return b;
}

function updateBalloons() {
	for (var i = 0; i < airBalloons.length; i++) {
		airBalloons[i].float();
	}
}

function floatBalloon() {
	this.bX += this.bDx;
	this.bY += this.bDy;

	if (this.bY > height) {
		this.bY = random(height * -5, height * -0.25);
		this.bX = random(0, width);
	}

}

function drawBalloon() {
	image(balloons[this.bImage], this.bX, this.bY, balloons[this.bImage].width * this.ratio, balloons[this.bImage].height * this.ratio);
}

Looking Outwards 11-Racial Bias in AI

The article AI & Creativity: Addressing Racial Bias in Computer Graphics discusses a topic brought up by Theodore Kim at SIGGRAPH 2021. Kim asserts that algorithms used for human computer generated images have encoded racial biases that reflect in the final outcome, and are being propagated in more forms of CG AI – a dangerous seed in spreading racial bias within society. Specifically, Kim talks about the subsurface light transport feature that CG artists use to give a realistic glow to their characters. While it reflects well in white figures, it produces inaccurate results when translated to darker skinned ones, as they have an observed shine to their skin surface. The same can be applied with the variety in hair textures, and the accuracy with portraying different hairs/defaulting to blonde hair. The issue with this is that algorithms are programmed to more accurately depict lighter skinned individuals compared to darker ones, creating a bias for CG artists to choose the first when doing these projects. Kim’s call to action is for these artists to be more conscious of their encoded racial biases, and make the effort to develop diversity with their own works. It was especially interesting when the comparison was brought up in regards to fine arts, and how artists had to “learn” to paint darker skinned people as there was a lack of exposure during their education.

https://nettricegaskins.medium.com/ai-creativity-addressing-racial-bias-in-computer-graphics-f5fc0c255e7

LO11:Societal Impacts of Digital Art

In this week’s looking outward, I read the article about NFT and copyright.

In this reading, the author mainly talks about the newly appeared NFT(Non Fungible Token), as well as its unique features. NFT, as a special token, gives a person more connection to the artwork he buys, and an “ownership” of the artwork. Yet the ownership is tricky because it doesn’t mean that the buyer has full control of the artwork, as the copyright and the right to print on other places without creator’s permission. In the condition that NFT is so expensive, this copyright problem is something that people need to think about.

Also, the definition of NFT determines that there are some sort of copyright problems coming up. As the original artist that create the NFT is allowed to create derivative works from the NFT already sold, there might be NFTs that are similar, or maybe the buyer will not be happy. Yet the original artist has the right to do so, therefore, the buyer could not sue the artist, which makes the situation hard to explain.

Looking Outwards 11

For this Week’s Looking Outwards, I read AI & Creativity: Addressing Racial Bias in ComputerGraphics. I chose this article because it aligns with a recent discussion we had in Design Cultures about design and race. In the article they talk about racial bias in computer graphic tracing back to when the technology was first developed. One example given is the glow that is added to create inclusion of lighting. When these techniques were developed they did not count for the effects it would have on darker skin. The result is that darker skin looks less realistic. Another example is in hair generation software that often ignores type 4, afro hair types. These issues with software limit creators and representation in video games, and other computer aided works. One interesting solution the article gave was to use deep machine learning to generate better images, as an example of this they shared artwork Netteice Gaskins created by such algorithms.

https://nettricegaskins.medium.com/ai-creativity-addressing-racial-bias-in-computer-graphics-f5fc0c255e7

Nettrice Gaskins. “Dandy Dream,” 2021. Created using a deep learning algorithm

Looking Outwards 11: Societal Impacts of Digital Art

Theodore Kim addresses racial bias in computer graphics and poses solutions to prevent systemic bias. Kim claims that early film technology and procedures from the analog period have biases ingrained in them. For example, “subsurface light transport” is a component of digital design that allows for a skin glow effect, but this doesn’t apply to darker skin tones. This same algorithm can look unrealistic on people with darker skin tones. In addition, there are no algorithms for kinky hair. The use of deep machine learning can offset historical racial bias in computer graphics. He further proposes that this process enables artists to discard outdated rules and produce a futuristic aesthetic for digital media.

Alexia Forsyth

https://www.tkim.graphics/

Blog 11

The article “Women in Media Arts: Does AI think like a (white) man?” addresses the biases in Ai, specifically regarding gender and race. “Gender Shades,” just one of the many artists’ works mentioned in the story, explores the differences in how AI facial recognition works for different races and genders. Through the research Joy Buolamwini and Timnit Gebru, the creators of the investigation, have done has led them to the conclusion that women, especially women of color, when using facial recognition, have a higher error rate than when recognizing other genders and races. They found that the developers used incorrect or incomplete data sets to train the programs, and, in turn, created the first data set that includes all skin color types and can test face-based gender recognition.

Another set of artists mentioned in the article, Birgitte Aga and Coral Manton, focus on gender-specific AI through their project, “Women Reclaiming AI.” The pair learned that AI language assistants are usually developed by teams that lack diversity and, through AI, reinforce stereotypes that reinforce traditional gender roles. In their project, they attack these biases and created a “feminist data set” for future AI systems. The artists mentioned are taking the steps to address the downfalls of AI and bring up questions around and problems to be solved with equality and AI.

Women in Media Arts: Does AI think like a (white) man?

Looking Outwards 11

This week I read about NFT and Copyright, discussing what is NFT, why they are valuable and the issue of its copyright. NFT(Non-fungible Token) means digital and unique token. NFT can give artists a potential revenue stream when they are selling their own art. Everyone can easily access other creators’ NFT, while this raises another question that spammers can also steal it for money. Thus, copyright issues seem to be more critical: NFT auction sites created DMCA processes to prevent the spread of unauthorized NFT, but it’s not effective enough. In this article, the author also mentions that block-chain might be the perfect tool for solving copyright problems, but it still brings new privacy concerns. In a nutshell, NFT itself needs to be scarce if it wants to create artificial scarcity. There is still a long way to go.

https://www.plagiarismtoday.com/2021/03/16/nfts-and-copyright/

Project 11

just my lil German boy

sketch
// Sowang Kundeling Section C Project 11

var backgroundX = 355;
var foregroundX = 250;

function preload() {
    germanboy = loadImage("https://i.imgur.com/8g7kXHX.png");
    neighborhood = loadImage("https://i.imgur.com/ueqfD0Q.png");
    house = loadImage("https://i.imgur.com/VeVnWaO.png");
    montain = loadImage("https://i.imgur.com/xImWYKs.png");

    long = loadImage("https://i.imgur.com/6kAoEti.png");
    short = loadImage("https://i.imgur.com/hGhArWq.png");
}


 function setup() {
    createCanvas(480, 240);
 }


 function draw() {
// sky
    noStroke();
    fill(180, 227, 242);
    rect(0, 0, 480, 25); // x7
    fill(163, 194, 207);
    rect(0, 25, 480, 25);
    fill(137, 165, 176);
    rect(0, 50, 480, 25);
    fill(121, 146, 156);
    rect(0, 75, 480, 25);
    fill(98, 119, 128);
    rect(0, 100, 480, 25);
    fill(79, 95, 102);
    rect(0, 125, 480, 25);
    fill(60, 74, 79);
    rect(0, 150, 480, 25);
    
    imageMode(CENTER);

// background elements
    for (var i = 0; i < 2; i ++) {
        image(short, backgroundX - (i * 150), 159, short.width/2, short.height/2);
        image(long, (backgroundX + 90) - (i * 200), 145, long.width/2, long.height/2);
    }

// land
    fill(107, 96, 81);
    rect(0, 175, 480, 65); // land

// foreground elements
    image(montain, foregroundX-120, 115, 265, montain.width/4, montain.height/4);
    image(neighborhood, foregroundX - 140, 137, neighborhood.width/2, neighborhood.height/2);
    image(house, foregroundX + 250, 140, house.width/4, house.height/4);
    image(germanboy, 100, 200, germanboy.width/2, germanboy.height/2);
    backgroundX -= 1; 
    foregroundX -= 1;

// reset
    if (backgroundX <= -300) {
        backgroundX = 900;
    }

    if (foregroundX <= -300) {
        foregroundX = 825
    }
}

Project-11-Landscape

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();

}