// Simin Li
// Section C
// siminl@andrew.cmu.edu
// Project 10
var clowns = [];
//store the clown fish
var terrainSpeed = 0.0005;
var terrainDetail = 0.005;
//used to control sea rocks
function setup() {
createCanvas(600, 400);
// create an initial collection of fish
for (var i = 0; i < 4; i++){
var rx = random(width);
var ry = random(0.8 * height);
clowns[i] = makeClownFish(rx,ry);
}
frameRate(10);
}
function draw() {
background(160);
seaViewer(150,200);
seaViewer(450,200);
seaRocks();
updateAndDisplayClownFish();
removeClownFishThatHaveSlippedOutOfView();
addNewClownFishWithSomeRandomProbability();
fill(41,115,179,0.2);
rect(0,0,width,height);
}
function updateAndDisplayClownFish(){
// Update the fish's positions, and display them.
for (var i = 0; i < clowns.length; i++){
clowns[i].move();
clowns[i].display();
}
}
function removeClownFishThatHaveSlippedOutOfView(){
var clownsToKeep = [];
for (var i = 0; i < clowns.length; i++){
if (clowns[i].fishX + clowns[i].fishWidth > 0) {
clownsToKeep.push(clowns[i]);
}
}
clowns = clownsToKeep; // remember the surviving buildings
}
function addNewClownFishWithSomeRandomProbability() {
// With a very tiny probability, add a new fish to the end.
var newClownLikelihood = 0.009;
if (random(0,1) < newClownLikelihood) {
clowns.push(makeClownFish(width,random(0,0.8 * height)));
}
}
// method to update position of fish every frame
function clownFishMove() {
this.fishX += this.speed;
this.fishY += noise(-this.speed,this.speed);
//randomize speed
}
//draw the clown fish
function clownFishDisplay(){
var fishHeight = this.fishWidth / 2;
noStroke();
fill(255,this.greeness,0);
beginShape();
curveVertex(this.fishX, this.fishY);//head of fish
curveVertex(this.fishX, this.fishY);//head of fish
curveVertex(this.fishX + 0.15 * this.fishWidth, this.fishY - fishHeight * 2 / 5);
curveVertex(this.fishX + this.fishWidth / 3, this.fishY - fishHeight * 2 / 3);
curveVertex(this.fishX + this.fishWidth * 2 / 3, this.fishY - (fishHeight / 4));
curveVertex(this.fishX + this.fishWidth * 7 / 8, this.fishY - (fishHeight / 3));
curveVertex(this.fishX + this.fishWidth, this.fishY);//tail of fish
curveVertex(this.fishX + this.fishWidth * 7 / 8, this.fishY + (fishHeight / 3));
curveVertex(this.fishX + this.fishWidth * 2 / 3, this.fishY + (fishHeight / 5));
curveVertex(this.fishX + this.fishWidth / 3, this.fishY + fishHeight / 3);
curveVertex(this.fishX + 0.1 * this.fishWidth, this.fishY + fishHeight * 1 / 6);
curveVertex(this.fishX, this.fishY);//head of fish
curveVertex(this.fishX, this.fishY);//head of fish
endShape();
//draw body
noStroke();
fill(255);
beginShape();
curveVertex(this.fishX + 0.15 * this.fishWidth, this.fishY - fishHeight * 2 / 5);
curveVertex(this.fishX + 0.15 * this.fishWidth, this.fishY - fishHeight * 2 / 5);
curveVertex(this.fishX + this.fishWidth / 3, this.fishY - fishHeight * 2 / 3);
curveVertex(this.fishX + this.fishWidth / 3 + this.headStripe, this.fishY - fishHeight * 1 / 3);
curveVertex(this.fishX + this.fishWidth / 3 - 0.3 * this.headStripe, this.fishY);
curveVertex(this.fishX + this.fishWidth / 3, this.fishY + fishHeight / 3);
curveVertex(this.fishX + 0.1 * this.fishWidth, this.fishY + fishHeight * 1 / 6);
curveVertex(this.fishX + 0.1 * this.fishWidth, this.fishY - fishHeight * 1 / 3);
endShape();
//draw head stripe
noStroke();
fill(255);
beginShape();
curveVertex(this.fishX + this.fishWidth * 2 / 3, this.fishY - (fishHeight / 4));
curveVertex(this.fishX + this.fishWidth * 2 / 3, this.fishY - (fishHeight / 4));
curveVertex(this.fishX + this.fishWidth * 7 / 8, this.fishY - (fishHeight / 3));
curveVertex(this.fishX + this.fishWidth * 7 / 8 + this.tailStripe, this.fishY - (fishHeight / 6));
curveVertex(this.fishX + this.fishWidth * 7 / 8 + 0.3 * this.tailStripe, this.fishY);
curveVertex(this.fishX + this.fishWidth * 7 / 8 - this.tailStripe, this.fishY + (fishHeight / 6));
curveVertex(this.fishX + this.fishWidth * 7 / 8, this.fishY + (fishHeight / 3));
curveVertex(this.fishX + this.fishWidth * 2 / 3, this.fishY + (fishHeight / 5));
curveVertex(this.fishX + this.fishWidth * 2 / 3, this.fishY + (fishHeight / 5));
curveVertex(this.fishX + this.fishWidth * 2 / 3 + this.tailStripe, this.fishY);
curveVertex(this.fishX + this.fishWidth * 2 / 3, this.fishY - (fishHeight / 4));
endShape();
//draw tail stripe
fill(0);
ellipse(this.fishX + 0.1 * this.fishWidth, this.fishY - fishHeight * 0.05,fishHeight / 10,fishHeight / 10);
//draw eye
}
function seaViewer(windowX,windowY){
//draw submarine outside window
strokeWeight(3);
stroke(90);
rectMode(CENTER);
noFill();
rect(windowX,windowY,240,340,80,80,80,80);
fill("LightBlue");
noStroke();
rect(windowX,windowY,200,300,70,70,70,70);
nail(windowX,windowY - 160, 12);
nail(windowX,windowY + 160, 12);
nail(windowX - 110,windowY, 12);
nail(windowX + 110,windowY, 12);
nail(windowX - 100,windowY - 120, 12);
nail(windowX + 100,windowY + 120, 12);
nail(windowX - 100,windowY + 120, 12);
nail(windowX + 100,windowY - 120, 12);
}
//draw nails on window
function nail(nailX, nailY, nailSize){
noStroke();
fill(100);
ellipse(nailX,nailY,nailSize,nailSize);
var screwlength = nailSize / (4 * sqrt(2));
strokeWeight(1);
stroke(0);
line(nailX - screwlength,nailY - screwlength,nailX + screwlength,nailY + screwlength);
line(nailX - screwlength,nailY + screwlength,nailX + screwlength,nailY - screwlength);
}
//draw sea rocks
function seaRocks(){
fill(11,20,61);
noStroke();
push();
translate(0,80);
//move down 80
beginShape();
vertex(0, height);
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail) + (millis() * terrainSpeed) * 3 / 4;
var y = map(noise(t), 0,1, 0, height );
vertex(x, y);
}
vertex(width, height);
endShape();
pop();
}
//create an object to store clownfish
function makeClownFish(birthLocationX,birthLocationY) {
var clownFish = {
fishX: birthLocationX,
//x location of fish
fishY: birthLocationY,
//y location of fish
fishWidth: random(30,120),
//width of fish
greeness: random(30,140),
//G value of the fish body color
move: clownFishMove,
//move the fish
speed: -random(0,4),
//randomize horizontal speed
display: clownFishDisplay,
//draw fish
headStripe: random(-8,8),
//randomize the stripe on head
tailStripe: random(-5,5)
//randomize the stripe on tail
}
return clownFish;
}
In this project I wanted to depict a view of marine life in front of a submarine window. The camera is following the submarine from outside. At first I only changed the color and size of the fish, then I realized I could make variations in the patterns of the fish as well.