xxxxxxxxxx
// Ocean with Jellyfish
// Created for OpenProcessing
let jellyfishes = [];
let bubbles = [];
let jellyfishColors = [
[255, 50, 150, 180], // Pink
[150, 50, 255, 180], // Purple
[50, 150, 255, 180], // Blue
[255, 150, 50, 180], // Orange
[50, 255, 150, 180] // Green
];
function setup() {
createCanvas(windowWidth, windowHeight);
// Create a group of jellyfish with different colors
for (let i = 0; i < 12; i++) {
let x = random(width);
let y = random(height);
let size = random(30, 80);
let c = jellyfishColors[floor(random(jellyfishColors.length))];
jellyfishes.push(new Jellyfish(x, y, size, c));
}
// Create some bubbles
for (let i = 0; i < 50; i++) {
bubbles.push(new Bubble(random(width), random(height), random(5, 15)));
}
}
function draw() {
// Ocean gradient background
background(10, 30, 70);
// Create light rays
drawLightRays();
// Handle bubbles
for (let i = bubbles.length - 1; i >= 0; i--) {
bubbles[i].move();
bubbles[i].display();
// If bubble is off the top, create a new one at the bottom
if (bubbles[i].isOffScreen()) {
bubbles.splice(i, 1);
bubbles.push(new Bubble(random(width), height + random(20), random(5, 15)));
}
}
// Draw and move jellyfish
for (let jf of jellyfishes) {
jf.move();
jf.display();
}
}
function drawLightRays() {
// Draw light rays from the top
noStroke();
for (let i = 0; i < width; i += 50) {
fill(255, 255, 255, 10);
beginShape();
vertex(i, 0);
vertex(i + 30, 0);
vertex(i + random(100, 200), height);
vertex(i - random(50, 100), height);
endShape(CLOSE);
}
}
class Jellyfish {
constructor(x, y, size, c) {
this.x = x;
this.y = y;
this.size = size;
this.c = c;
this.phase = random(TWO_PI);
this.speed = random(0.5, 1.5);
}
move() {
// Gently float upward with some side-to-side motion
this.y -= this.speed;
this.x += sin(frameCount * 0.02 + this.phase) * 0.5;
// Wrap around when off screen
if (this.y < -this.size * 2) {
this.y = height + this.size;
this.x = random(width);
}
}
display() {
push();
translate(this.x, this.y);
// Draw the bell (main body)
fill(this.c);
noStroke();
ellipse(0, 0, this.size, this.size * 1.2);
// Calculate tentacle movement
let tentaclePhase = frameCount * 0.1;
// Draw the tentacles
for (let i = 0; i < 8; i++) {
let angle = TWO_PI * i / 8;
let xOffset = sin(tentaclePhase + i * 0.5) * 5;
push();
rotate(angle);
// Main tentacle
beginShape();
noFill();
stroke(this.c);
strokeWeight(3);
for (let t = 0; t <= 1; t += 0.1) {
let xPos = xOffset * t * sin(tentaclePhase + t * 3);
let yPos = this.size * 0.6 + t * this.size * 1.5;
vertex(xPos, yPos);
}
endShape();
// Draw the wavy lines inside tentacles
stroke(this.c[0], this.c[1], this.c[2], 150);
strokeWeight(2);
noFill();
beginShape();
for (let t = 0; t <= 1; t += 0.1) {
let xPos = xOffset * t * sin(tentaclePhase + t * 3);
let yPos = this.size * 0.6 + t * this.size * 1.5;
vertex(xPos, yPos);
}
endShape();
pop();
}
// Draw highlights on the bell
fill(255, 255, 255, 50);
ellipse(-this.size * 0.2, -this.size * 0.2, this.size * 0.3, this.size * 0.3);
pop();
}
}
class Bubble {
constructor(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.speed = map(size, 5, 15, 0.5, 2);
this.wobble = random(TWO_PI);
}
move() {
// Bubbles rise and wobble side to side
this.y -= this.speed;
this.x += sin(frameCount * 0.05 + this.wobble) * 0.5;
}
display() {
// Draw the bubble
noFill();
stroke(255, 255, 255, 100);
strokeWeight(1.5);
ellipse(this.x, this.y, this.size, this.size);
// Draw highlight
stroke(255, 255, 255, 150);
strokeWeight(1);
arc(this.x, this.y, this.size * 0.7, this.size * 0.7, PI * 0.7, PI * 1.5);
}
isOffScreen() {
return this.y < -this.size;
}
}
// Make canvas responsive
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}