xxxxxxxxxx
240
let Engine = Matter.Engine,
Runner = Matter.Runner,
World = Matter.World,
Bodies = Matter.Bodies,
Body = Matter.Body;
let engine, runner;
let bubbles = [];
let particles = []; // Array to store popping particles
let gameOver = false;
let dragging = false;
let offsetX, offsetY;
let bubbleGenerationTimer = 50; // Timer for bubble generation
function setup() {
createCanvas(600, 600);
engine = Engine.create();
engine.world.gravity.y = 0; // Disable gravity
runner = Runner.create();
Runner.run(runner, engine);
// Add initial bubbles
for (let i = 0; i < 3; i++) {
addBubble();
}
}
function draw() {
background(51);
// Display all the bubbles and handle their behavior
for (let i = bubbles.length - 1; i >= 0; i--) {
if (bubbles[i]) {
bubbles[i].show();
bubbles[i].floatAround();
// Check for game over condition
if (bubbles[i].number === 2048) {
gameOver = true;
noLoop();
fill(255);
textAlign(CENTER, CENTER);
textSize(32);
text("You Win!", width / 2, height / 2);
break;
}
}
}
// Display and update particles
for (let i = particles.length - 1; i >= 0; i--) {
particles[i].update();
particles[i].show();
if (particles[i].finished()) {
particles.splice(i, 1); // Remove finished particles
}
}
// Generate new bubbles
if (!gameOver) {
bubbleGenerationTimer++;
if (bubbleGenerationTimer > 60) {
addBubble();
bubbleGenerationTimer = 30;
}
}
}
// Function to add a new bubble
function addBubble() {
let size = random(32, 64);
let newBubble = new Bubble(random(100, width - 100), height, size, random([2, 4]));
World.add(engine.world, newBubble.body);
Body.setVelocity(newBubble.body, { x: random(-1, 1), y: random(-2, -1) });
bubbles.push(newBubble);
}
// Mouse pressed event for dragging
function mousePressed() {
for (let i = 0; i < bubbles.length; i++) {
if (bubbles[i].isMouseOver()) {
dragging = true;
offsetX = mouseX - bubbles[i].body.position.x;
offsetY = mouseY - bubbles[i].body.position.y;
bubbles[i].isDragging = true;
break;
}
}
}
// Mouse dragged event for moving bubbles
function mouseDragged() {
if (dragging) {
for (let i = 0; i < bubbles.length; i++) {
if (bubbles[i].isDragging) {
Body.setPosition(bubbles[i].body, { x: mouseX - offsetX, y: mouseY - offsetY });
// Check for merging
for (let j = 0; j < bubbles.length; j++) {
if (i !== j && bubbles[j].isMouseOver()) {
if (bubbles[i].number === bubbles[j].number) {
let mergedSize = bubbles[i].r * 1.1;
let newNumber = bubbles[i].number * 2;
// Create particle effect for popping
createParticles(bubbles[i].body.position.x, bubbles[i].body.position.y, bubbles[i].r);
createParticles(bubbles[j].body.position.x, bubbles[j].body.position.y, bubbles[j].r);
// Remove the old bubbles
World.remove(engine.world, bubbles[i].body);
World.remove(engine.world, bubbles[j].body);
let mergedBubble = new Bubble(
(bubbles[i].body.position.x + bubbles[j].body.position.x) / 2,
(bubbles[i].body.position.y + bubbles[j].body.position.y) / 2,
mergedSize,
newNumber
);
bubbles.splice(j, 1);
bubbles.splice(i, 1);
bubbles.push(mergedBubble);
break;
}
}
}
break;
}
}
}
}
// Mouse released event to stop dragging
function mouseReleased() {
dragging = false;
for (let i = 0; i < bubbles.length; i++) {
bubbles[i].isDragging = false;
}
}
// Bubble Class
class Bubble {
constructor(x, y, r, number) {
this.r = r;
this.number = number;
this.isDragging = false;
this.body = Bodies.circle(x, y, this.r, {
restitution: 0.7,
friction: 0.1,
});
this.color = this.getColorByNumber();
}
show() {
let pos = this.body.position;
push();
translate(pos.x, pos.y);
fill(this.color);
stroke(255);
strokeWeight(2);
ellipse(0, 0, this.r * 2);
fill(255);
noStroke();
textAlign(CENTER, CENTER);
textSize(24);
text(this.number, 0, 0);
pop();
}
floatAround() {
let randomX = random(-0.1, 0.1);
let randomY = random(-0.1, 0.1);
Body.setVelocity(this.body, { x: this.body.velocity.x + randomX, y: this.body.velocity.y + randomY });
Body.setVelocity(this.body, {
x: constrain(this.body.velocity.x, -2, 2),
y: constrain(this.body.velocity.y, -2, 0)
});
}
isMouseOver() {
let d = dist(mouseX, mouseY, this.body.position.x, this.body.position.y);
return d < this.r;
}
getColorByNumber() {
switch (this.number) {
case 2: return color(102, 178, 255);
case 4: return color(255, 153, 153);
case 8: return color(255, 204, 102);
case 16: return color(204, 255, 153);
case 32: return color(255, 153, 204);
case 64: return color(153, 255, 255);
case 128: return color(255, 102, 102);
case 256: return color(102, 255, 178);
case 512: return color(255, 255, 102);
case 1024: return color(178, 102, 255);
case 2048: return color(255, 204, 229);
default: return color(150, 150, 150);
}
}
}
// Particle Class for popping effect
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.r = random(2, 5);
this.lifetime = 255;
this.color = color(random(100, 255), random(100, 255), random(100, 255));
}
update() {
this.lifetime -= 5; // Decrease lifetime
this.r *= 0.95; // Shrink size
this.x += random(-2, 2);
this.y += random(-2, 2);
}
show() {
noStroke();
fill(this.color.levels[0], this.color.levels[1], this.color.levels[2], this.lifetime);
ellipse(this.x, this.y, this.r * 2);
}
finished() {
return this.lifetime <= 0;
}
}
// Function to create particles
function createParticles(x, y, num) {
for (let i = 0; i < num; i++) {
particles.push(new Particle(x, y));
}
}