Press P for sound effects! Move the mouse around to guide a fish to find its food.
A fork of Pond by David Leibovic, Sunah Suh & Ricardo Sánchez by jcponcemath
xxxxxxxxxx
/*
* Based upon the amazing Processing project: My Life Aquatic
* by David Leibovic, Sunah Suh and Ricardo Sánchez
* Source: https://github.com/dasl-/my-life-aquatic
*
* Translated to p5.js by Juan Carlos Ponce Campuzano
* 27/Jul/2024
* https://www.dynamicmath.xyz
*
* TO-DO:
* Fix sound effects but it seems to be working now.
* I want to fix the water drops sound effect with ripples on the water.
*/
let foregroundBubbles = [];
let backgroundBubbles = [];
let foods = [];
let myFish;
let numBoids = 10;
let boids = [];
let ripples = [];
function setup() {
let pondWidth = window.innerWidth;
let pondHeight = window.innerHeight;
createCanvas(pondWidth, pondHeight);
frameRate(50);
let location = createVector(random(0.2 * pondWidth, 0.8 * pondWidth), random(0.2 * pondHeight, 0.8 * pondHeight));
myFish = new Fish(location, random(2.0, 2.5), 0.2);
cursor(HAND);
// Create fishes
for (let n = 0; n < numBoids; n++) {
let location2 = createVector(random(100, width - 100), random(100, height - 100));
let fish = new Fish(location2, random(1.0, 3.5), 0.2);
boids.push(fish);
}
}
function draw() {
background(0, 96, 128);
// We can use "background()" to color the water,
// but it is easier to set the color of the canvas using CSS.
// That's why we need to clear the canvas
//clear();
let randomNumber = random(0, 1000);
myFish.update();
myFish.render();
if (myFish.getFoodEaten() > 11 && !myFish.getIsExploding()) {
myFish.explode();
}
for (let fish of boids) {
fish.update();
fish.render();
// If there is any food in the pond
///*
if (foods.length > 0) {
// Check if a fish is near one and apply arrive behavior
for (let j = 0; j < foods.length; j++) {
let food = foods[j];
let fLoc = food.location.copy();
let bLoc = fish.location.copy();
let d = bLoc.dist(fLoc);
if (d < 100.0) {
fish.arrive(fLoc);
if (fish.hasArrive === true) {
food.isDead = true;
fish.hasArrive = false;
}
fish.wander();
}
}
}
//*/
}
if (randomNumber <= 6) {
let foodLocation = createVector(random(100, width - 100), random(100, height - 100));
let food = new Food(foodLocation);
foods.push(food);
}
for (let i = foods.length - 1; i >= 0; i--) {
let food = foods[i];
if (!food.getIsDead()) {
food.update();
food.render();
if (myFishAteFood(food)) {
foods.splice(i, 1);
}
} else {
foods.splice(i, 1);
}
}
// Create a new ripple at a random position at intervals
if (frameCount % 20 === 0) {
let ripple = {
x: random(width),
y: random(height),
radius: 0,
speed: 2,
maxRadius: 100
};
ripples.push(ripple);
}
// Update and draw ripples
for (let i = ripples.length - 1; i >= 0; i--) {
let r = ripples[i];
stroke(`rgba(198, 217, 236, ${1 - r.radius / r.maxRadius})`); // Nice color with fading effect
push();
noFill();
ellipse(r.x, r.y, r.radius * 2);
pop();
r.radius += r.speed;
// Remove the ripple if it exceeds maxRadius
if (r.radius > r.maxRadius) {
ripples.splice(i, 1);
}
}
}
function myFishAteFood(food) {
let foodEaten = false;
let distanceToFood = p5.Vector.sub(myFish.getLocation(), food.getLocation()).mag();
if (distanceToFood < 10) {
foodEaten = true;
gulp.play(); // Uncomment if you have a gulp sound to play
myFish.setBodySizeH(myFish.getBodySizeH() * 1.1);
myFish.setBodySizeW(myFish.getBodySizeW() * 1.1);
myFish.setLastAteTimer(int(frameRate() / 2));
myFish.setFoodEaten(myFish.getFoodEaten() + 1);
}
return foodEaten;
}
function mouseMoved() {
let mousePosition = createVector(mouseX, mouseY);
myFish.setMousePosition(mousePosition);
}
function touchMoved() {
let mousePosition = createVector(mouseX, mouseY);
myFish.setMousePosition(mousePosition);
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}