For my project, I decided to create a relaxing underwater scene. Although it was a bit challenging to figure out how to execute my ideas, I had fun making my landscape and adjusting properties to make it more interesting. To create my landscape, I combined concepts that we learned in the past, such as arrays, objects, loops, noise, images, and functions. I randomized properties such as the x/y positions, sizes, colors, and speeds of my objects.
var terrain = [];
var coral;
var bubbles = [];
var fish = [];
var noiseParam = 0;
var noiseStep = 0.05;
function preload() {
coral = loadImage("https://i.imgur.com/S5HGpZa.png");
}
function setup() {
createCanvas(480, 300);
//setup noise for terrain
for(var i=0; i<=width/5; i++) {
var n = noise(noiseParam);
var value = map(n, 0, 1, 0, height);
terrain.push(value);
noiseParam += noiseStep;
}
//setup for fish
for (var i = 0; i < 15; i++) {
fishx = random(width);
fish[i] = makeFish(fishx);
}
//setup for bubbles
for (var i = 0; i < 10; i++) {
bubblex = random(width);
bubbley = random(height);
bubbles[i] = makeBubble(bubblex, bubbley);
}
frameRate(10);
}
function draw() {
background(0, 180, 200);
noStroke();
fill(0, 230, 255, 90);
ellipse(240, 0, 600, 200);
blueTerrain();
updateAndDisplayFish();
removeFish();
addNewFish();
displayBubbles();
}
//background terrain
function blueTerrain() {
terrain.shift();
var n = noise(noiseParam);
var value = map(n, 0, 1, 0, height);
terrain.push(value);
noiseParam += noiseStep;
//blue terrain
noStroke();
fill(0, 66, 115);
beginShape();
vertex(0, height);
for(var i=0; i<width/4; i++) {
vertex(i*5, terrain[i]);
//placement of coral on terrain
if(terrain[i] < terrain[i-1] & terrain[i] < terrain[i+1]) {
drawCoral(i*5, terrain[i]);
}
}
vertex(width, height);
endShape(CLOSE);
}
//draws coral on terrain
function drawCoral(x, y) {
imageMode(CENTER);
image(coral, x, y-10, 65, 80);
}
//update the fish positions and display them
function updateAndDisplayFish() {
for (var i = 0; i < fish.length; i++) {
fish[i].move();
fish[i].draw();
}
}
//remove fish that are off the canvas from the array
function removeFish() {
var fishToKeep = [];
for (var i = 0; i < fish.length; i++) {
if (fish[i].x + fish[i].w > 0) {
fishToKeep.push(fish[i]);
}
}
fish = fishToKeep;
}
//with a small probability, add a new fish to end of the array
function addNewFish() {
var newFishLikelihood = 0.3;
if (random(0,1) < newFishLikelihood) {
fish.push(makeFish(width+20));
}
}
function moveFish() {
this.x += this.speed;
}
function drawFish() {
push();
translate(this.x, this.y);
fill(this.color);
ellipse(0, 0, this.w, this.h);
strokeWeight(1.5);
stroke(240);
fill(50);
ellipse(-15, -4, 8, 8);
noStroke();
fill(this.fincolor);
triangle(0, -4, 0, 4, 15, 0);
noFill();
push();
fill(this.color);
triangle(this.w/2+20, -8, this.w/2+20, 8, (this.w/2)-2, 0);
pop();
pop();
}
//fish constructor
function makeFish(fishx) {
var f = {x: fishx, y: random(height),
w: random(40, 80), h: random(10, 45),
color: color(random(100, 255), random(100, 255), random(100, 255)),
fincolor: color(random(50, 200), random(50, 200), random(50, 200)),
speed: random(-10, -20),
move: moveFish,
draw: drawFish
}
return f;
}
function displayBubbles() {
for (var i = 0; i < bubbles.length; i++) {
bubbles[i].move();
bubbles[i].draw();
}
}
//bubbles float upwards
function moveBubbles() {
this.x += this.speed;
this.y += this.speed;
if (this.x <= 0) {
this.x = width;
}
if (this.y <= 0) {
this.y = height;
}
}
function drawBubbles() {
push();
strokeWeight(1);
stroke(255, 255, 255, 80);
fill(100, 255, 255, 60);
ellipse(this.x, this.y, this.size, this.size);
noFill();
strokeWeight(2);
arc(this.x - this.size/12, this.y - this.size/12, 15, 15, PI, PI + HALF_PI);
pop();
}
//bubbles constructor
function makeBubble(bubblex, bubbley) {
var b = {x: bubblex, y: bubbley,
size: random(20, 40),
speed: random(-1, -6),
move: moveBubbles,
draw: drawBubbles
}
return b;
}