slice particle effects added

This commit is contained in:
Haeri Kim
2026-05-05 13:57:33 +09:00
parent e9c0d3e6fa
commit 3b2c52267a
2 changed files with 160 additions and 7 deletions

View File

@@ -7,10 +7,9 @@
</head>
<body>
<script src="lib/p5.min.js"></script>
<script src="lib/matter.min.js"></script>
<script src="lib/gsap.min.js"></script>
<script src="sketch.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="sketch.js"></script>
</body>
</html>

158
sketch.js
View File

@@ -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));
}
}