//Charmaine Qiu
//Section E
//charmaiq@andrew.cmu.edu
//Project 11
//set the speed and detail for terrain
var terrainSpeed = 0.0005;
var terrainDetail = 0.008;
//create empty array for ducks on screen
var ducks = [];
function setup() {
createCanvas(480, 200);
frameRate(10);
//set the number of ducks that appears in the beginning randomly on screen
for (var i = 0; i <3; i++){
var rx = random(width);
ducks[i] = makeDuck(rx);
}
}
function draw() {
//set background visuals
//the sky
background('#95dddd');
//the river
fill('#419696')
noStroke();
rect(0, height / 2, width, height);
//the sun and its reflection
fill('red');
ellipse(width - 60, 10, 60, 60);
fill('#6e1616');
ellipse(width - 60, height - 10, 60, 60);
//draw mountain and ripple function
mountains();
ripples();
//draw the ducks
push();
translate(0.1 * width, 0.1 * height);
scale(0.8);
updateAndDisplayDucks();
removeDucksThatHaveSlippedOutOfView();
addNewDucksWithSomeRandomProbability();
pop();
}
function mountains(){
//create the mountain
fill('#e1a952');
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail) + (millis() * terrainSpeed);
var y = map(noise(t), 0,1, 0, height / 2);
vertex(x, y);
}
vertex(width, height/2);
vertex(0, height/2)
endShape();
//create the reflection
fill('#dd5a62');
beginShape();
noStroke();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail) + (millis() * terrainSpeed);
//inverse the y component to flip the mountain upside-down
var y = map(noise(t), 0,1, height, height / 2);
vertex(x, y);
}
vertex(width, height/2);
vertex(0, height/2)
endShape();
}
function ripples(){
//create the ripples
frameRate(7);
stroke(255);
//set individual random values for x and y coordinates of ripples
rX = random(width / 2 - 50, width / 2 + 50);
rY = random(height / 2 + 10, height);
rX2 = random(width / 2 - 50, width / 2 + 50);
rY2 = random(height / 2 + 10, height);
rX3 = random(width / 2 - 50, width / 2 + 50);
rY3 = random(height / 2 + 10, height);
//set individual random values for width and weight of ripples
rWidth = random(5, 20);
rWeight = random(1, 4);
rWidth2 = random(5, 20);
rWeight2 = random(1, 4);
rWidth3 = random(5, 20);
rWeight3 = random(1, 4);
//draw out the lines of ripples
strokeWeight(rWeight);
line(rX, rY, rX + rWidth, rY);
strokeWeight(rWeight2);
line(rX2, rY2, rX2 + rWidth2, rY2);
strokeWeight(rWeight3);
line(rX3, rY3, rX3 + rWidth3, rY3);
}
function updateAndDisplayDucks(){
// Update the duck's positions, and display them.
for (var i = 0; i < ducks.length; i++){
ducks[i].move();
ducks[i].display();
}
}
function removeDucksThatHaveSlippedOutOfView(){
// copy all the ducks that's kept into a new array.
var ducksToKeep = [];
for (var i = 0; i < ducks.length; i++){
if (ducks[i].x + ducks[i].breadth > 0) {
ducksToKeep.push(ducks[i]);
}
}
ducks = ducksToKeep; //remember the surviving ducks
}
function addNewDucksWithSomeRandomProbability() {
// With a very tiny probability, add a new duck to the end.
var newDuckLikelihood = 0.007;
if (random(0,1) < newDuckLikelihood) {
ducks.push(makeDuck(width));
}
}
// method to update position of duck every frame
function duckMove() {
this.x += this.speed;
}
function duckDisplay() {
// draw the ducks
var headHeight = 20;
fill(255);
noStroke();
push();
//translate duck to lower part of canvas
translate(this.x, height - 40);
ellipse(0, -headHeight, this.breadth, headHeight);
fill(0);
ellipse(0, -headHeight, 5, 5);
fill("#70547c");
arc(10, -10, 30, 30, 0, PI);
fill("#f8e184");
arc(10, -10, 10, 10, 0, PI);
fill("green");
arc(-10, -20, 10, 10, 0, PI);
pop();
}
//the function to create the duck object
function makeDuck(birthLocationX) {
var mdk = {x: birthLocationX,
breadth: 20,
speed: -1.0,
move: duckMove,
display: duckDisplay}
return mdk;
}
In this project, I was able to create a generative landscape with customized features. I really enjoyed sceneries that has a complete reflection on a water surface, and decided to create an animation with a mountain and its reflection on the lake. I added a fun component of ducks swimming around to create a fun element.