diff --git a/index.html b/index.html index 760daba..f8e0d7c 100644 --- a/index.html +++ b/index.html @@ -7,10 +7,9 @@ - - - - - + + + + \ No newline at end of file diff --git a/sketch.js b/sketch.js index 9949ee1..39e9d7a 100644 --- a/sketch.js +++ b/sketch.js @@ -1,7 +1,161 @@ +// ====== [GLOBAL VARIABLES] ====== +let trail = []; +let velocities = []; + +let particles = []; +let flashAlpha = 0; +let lastSliceTime = 0; + +let coconut = { + x: 400, + y: 300, + r: 50 +}; + +// ====== [SETUP] ====== function setup() { - createCanvas(800, 600); + createCanvas(800, 600); } +// ====== [DRAW LOOP] ====== function draw() { - background(30); + background(30); + + drawTrail(); + drawCoconut(); + checkSlice(); + + // ====== PARTICLES ====== + for (let i = particles.length - 1; i >= 0; i--) { + particles[i].update(); + particles[i].draw(); + + if (particles[i].life <= 0) { + particles.splice(i, 1); + } + } + + // ====== FLASH EFFECT ====== + if (flashAlpha > 0) { + fill(255, flashAlpha); + rect(0, 0, width, height); + flashAlpha -= 20; + } +} + +// ====== [INPUT: KNIFE TRACKING] ====== +function mouseDragged() { + let pos = createVector(mouseX, mouseY); + trail.push(pos); + + if (trail.length > 1) { + let v = p5.Vector.sub( + trail[trail.length - 1], + trail[trail.length - 2] + ); + velocities.push(v.mag()); + } + + if (trail.length > 20) trail.shift(); + if (velocities.length > 20) velocities.shift(); +} + +// ====== [DRAW TRAIL] ====== +function drawTrail() { + noFill(); + + for (let i = 1; i < trail.length; i++) { + let speed = velocities[i] || 0; + let thickness = map(speed, 0, 50, 1, 10); + + strokeWeight(thickness); + stroke(255, 200); + + line( + trail[i - 1].x, + trail[i - 1].y, + trail[i].x, + trail[i].y + ); + } +} + +// ====== [DRAW COCONUT] ====== +function drawCoconut() { + fill(100, 255, 100); + noStroke(); + ellipse(coconut.x, coconut.y, coconut.r * 2); +} + +// ====== [SLICE CHECK] ====== +function checkSlice() { + for (let i = 1; i < trail.length; i++) { + let hit = lineCircle( + trail[i - 1], + trail[i], + coconut.x, + coconut.y, + coconut.r + ); + + if (hit && millis() - lastSliceTime > 100) { + lastSliceTime = millis(); + + let speed = velocities[i] || 10; + + console.log("SLICE!"); + + spawnParticles(coconut.x, coconut.y, speed); + flashAlpha = map(speed, 0, 50, 50, 150); + } + } +} + +// ====== [COLLISION: LINE vs CIRCLE] ====== +function lineCircle(p1, p2, cx, cy, r) { + let ac = createVector(cx - p1.x, cy - p1.y); + let ab = p5.Vector.sub(p2, p1); + + let ab2 = ab.magSq(); + let acab = ac.dot(ab); + + let t = constrain(acab / ab2, 0, 1); + + let h = createVector( + p1.x + ab.x * t, + p1.y + ab.y * t + ); + + let distSq = (h.x - cx) ** 2 + (h.y - cy) ** 2; + + return distSq <= r * r; +} + +// ====== [PARTICLE CLASS] ====== +class Particle { + constructor(x, y, speed) { + this.pos = createVector(x, y); + this.vel = p5.Vector.random2D().mult(random(1, speed * 0.3)); + this.life = 255; + } + + update() { + this.pos.add(this.vel); + this.life -= 5; + } + + draw() { + noStroke(); + fill(200, 255, 200, this.life); + ellipse(this.pos.x, this.pos.y, 5); + } +} + +// ====== [SPAWN PARTICLES] ====== +function spawnParticles(x, y, speed) { + let count = map(speed, 0, 50, 5, 25); + + for (let i = 0; i < count; i++) { + particles.push(new Particle(x, y, speed)); + } } \ No newline at end of file