Bot commited on
Commit
31fcb83
·
1 Parent(s): 292ab5d

feat: increase fireball size and speed

Browse files
Files changed (1) hide show
  1. static/main.js +82 -52
static/main.js CHANGED
@@ -121,6 +121,9 @@ let prevHands = null;
121
  let chargeFrames = 0;
122
  let throwCooldown = 0;
123
  const fireballs = [];
 
 
 
124
 
125
  // Heart State
126
  const hearts = [];
@@ -331,31 +334,63 @@ function processFireball(hands) {
331
  let chargeRadius = 0;
332
  let chargePos = null;
333
 
 
 
 
334
  if (hands.length === 2 && prevHands && prevHands.length === 2) {
335
  const c1 = palmCenter(hands[0]), c2 = palmCenter(hands[1]);
336
  const d = Math.hypot(c1.x - c2.x, c1.y - c2.y);
337
- if (d < 0.3) {
338
- chargeFrames++;
339
- // Grow fireball up to 300px radius to engulf hands in 5 seconds (300 frames)
340
- chargeRadius = Math.min(300, chargeFrames * 1.0);
341
- chargePos = { x: (c1.x + c2.x) / 2 * W, y: (c1.y + c2.y) / 2 * H };
342
-
343
- if (chargeFrames > 30 && throwCooldown === 0) {
344
- const v1 = getVelocity(c1, palmCenter(prevHands[0]));
345
- const v2 = getVelocity(c2, palmCenter(prevHands[1]));
346
- if (v1.speed > 0.02 && v2.speed > 0.02) {
347
- audio.play('fireball');
348
- fireballs.push(new Fireball(chargePos.x, chargePos.y, (v1.vx+v2.vx)*W*0.5, (v1.vy+v2.vy)*H*0.5, Math.max(40, chargeRadius)));
349
- chargeFrames = 0; throwCooldown = 30; chargeRadius = 0;
350
- actionText = "🔥 MASSIVE FIREBALL";
351
- }
 
 
 
 
 
 
 
 
 
 
 
 
352
  }
353
- if (chargeFrames > 10 && !actionText) actionText = "🔥 CHARGING";
354
  } else {
355
- chargeFrames = 0;
 
356
  }
357
- } else if (hands.length === 1 && prevHands && prevHands.length === 1) {
358
- chargeFrames = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
359
  const c = palmCenter(hands[0]);
360
  const v = getVelocity(c, palmCenter(prevHands[0]));
361
  if (v.speed > 0.04 && throwCooldown === 0) {
@@ -364,9 +399,8 @@ function processFireball(hands) {
364
  throwCooldown = 20;
365
  actionText = "🔥 THROW";
366
  }
367
- } else {
368
- chargeFrames = 0;
369
  }
 
370
  return { actionText, chargeRadius, chargePos };
371
  }
372
 
@@ -401,11 +435,12 @@ function detectLoop() {
401
  ctx.fillRect(0, 0, canvas.width, canvas.height);
402
 
403
  const hands = results.landmarks || [];
404
- document.getElementById('handCount').textContent = hands.length;
 
 
 
405
 
406
- if (hands.length > 0) {
407
- // Mirror X coords
408
- const mirroredHands = hands.map(hand => hand.map(lm => ({...lm, x: 1 - lm.x})));
409
 
410
  // Draw Particles
411
  for (let i = particles.length - 1; i >= 0; i--) {
@@ -446,33 +481,6 @@ function detectLoop() {
446
  drawMultiverseConnections(mirroredHands[0], mirroredHands[1]);
447
  }
448
 
449
- // Stats
450
- const fbData = processFireball(mirroredHands);
451
-
452
- // Draw Charging Fireball
453
- if (fbData.chargeRadius > 0 && fbData.chargePos) {
454
- const r = fbData.chargeRadius;
455
- ctx.save();
456
- ctx.globalAlpha = 0.8 + Math.random() * 0.2; // Flicker
457
- const g = ctx.createRadialGradient(fbData.chargePos.x, fbData.chargePos.y, 0, fbData.chargePos.x, fbData.chargePos.y, r);
458
- g.addColorStop(0, '#fff');
459
- g.addColorStop(0.3, '#ffaa00');
460
- g.addColorStop(1, 'rgba(255,0,0,0)');
461
- ctx.fillStyle = g;
462
- ctx.beginPath();
463
- ctx.arc(fbData.chargePos.x, fbData.chargePos.y, r, 0, Math.PI*2);
464
- ctx.fill();
465
-
466
- // Add some spark particles while charging
467
- if (Math.random() > 0.5) {
468
- ctx.fillStyle = `hsl(${20 + Math.random()*30}, 100%, 50%)`;
469
- ctx.beginPath();
470
- ctx.arc(fbData.chargePos.x + (Math.random()-0.5)*r, fbData.chargePos.y + (Math.random()-0.5)*r, 1.5, 0, Math.PI*2);
471
- ctx.fill();
472
- }
473
- ctx.restore();
474
- }
475
-
476
  const g = fbData.actionText || detectGesture(mirroredHands[0]);
477
  const s = calcSpread(mirroredHands[0]);
478
  audio.updateSound(s, mirroredHands.length);
@@ -510,6 +518,28 @@ function detectLoop() {
510
  }
511
  }
512
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
  animFrameId = requestAnimationFrame(detectLoop);
514
  } catch (err) {
515
  console.error("Error in detectLoop:", err);
 
121
  let chargeFrames = 0;
122
  let throwCooldown = 0;
123
  const fireballs = [];
124
+ let chargeAmount = 0;
125
+ let fullGrownFrames = 0;
126
+ let pendingFireballPos = null;
127
 
128
  // Heart State
129
  const hearts = [];
 
334
  let chargeRadius = 0;
335
  let chargePos = null;
336
 
337
+ let isCharging = false;
338
+ let v1 = {vx:0, vy:0, speed:0}, v2 = {vx:0, vy:0, speed:0};
339
+
340
  if (hands.length === 2 && prevHands && prevHands.length === 2) {
341
  const c1 = palmCenter(hands[0]), c2 = palmCenter(hands[1]);
342
  const d = Math.hypot(c1.x - c2.x, c1.y - c2.y);
343
+ if (d < 0.4) {
344
+ isCharging = true;
345
+ v1 = getVelocity(c1, palmCenter(prevHands[0]));
346
+ v2 = getVelocity(c2, palmCenter(prevHands[1]));
347
+ pendingFireballPos = { x: (c1.x + c2.x) / 2 * W, y: (c1.y + c2.y) / 2 * H };
348
+ }
349
+ }
350
+
351
+ if (isCharging || chargeAmount >= 500) {
352
+ if (isCharging) {
353
+ const rubSpeed = v1.speed + v2.speed;
354
+ chargeAmount += 1.0 + (rubSpeed * 30.0);
355
+ }
356
+
357
+ chargeRadius = Math.min(500, chargeAmount * 1.5);
358
+ chargePos = pendingFireballPos || { x: W/2, y: H/2 };
359
+
360
+ if (chargeRadius >= 500) {
361
+ fullGrownFrames++;
362
+ if (fullGrownFrames > 180) { // 3 seconds at 60fps
363
+ audio.play('fireball');
364
+ const angle = Math.random() * Math.PI * 2;
365
+ fireballs.push(new Fireball(chargePos.x, chargePos.y, Math.cos(angle)*15, Math.sin(angle)*15, chargeRadius));
366
+ chargeAmount = 0; fullGrownFrames = 0; pendingFireballPos = null; throwCooldown = 30; chargeRadius = 0;
367
+ actionText = "🔥 AUTO THROW";
368
+ } else {
369
+ actionText = "🔥 FULLY CHARGED";
370
  }
 
371
  } else {
372
+ fullGrownFrames = 0;
373
+ actionText = "🔥 CHARGING";
374
  }
375
+
376
+ if (isCharging && chargeAmount > 30 && throwCooldown === 0) {
377
+ if (v1.speed > 0.05 && v2.speed > 0.05) {
378
+ audio.play('fireball');
379
+ let dx = (v1.vx + v2.vx) * W * 0.5;
380
+ let dy = (v1.vy + v2.vy) * H * 0.5;
381
+ if (Math.hypot(dx, dy) < 5) { dx = 0; dy = -15; }
382
+ fireballs.push(new Fireball(chargePos.x, chargePos.y, dx, dy, Math.max(40, chargeRadius)));
383
+ chargeAmount = 0; fullGrownFrames = 0; pendingFireballPos = null; throwCooldown = 30; chargeRadius = 0;
384
+ actionText = "🔥 MASSIVE FIREBALL";
385
+ }
386
+ }
387
+ } else {
388
+ chargeAmount = 0;
389
+ fullGrownFrames = 0;
390
+ pendingFireballPos = null;
391
+ }
392
+
393
+ if (chargeAmount === 0 && hands.length === 1 && prevHands && prevHands.length === 1) {
394
  const c = palmCenter(hands[0]);
395
  const v = getVelocity(c, palmCenter(prevHands[0]));
396
  if (v.speed > 0.04 && throwCooldown === 0) {
 
399
  throwCooldown = 20;
400
  actionText = "🔥 THROW";
401
  }
 
 
402
  }
403
+
404
  return { actionText, chargeRadius, chargePos };
405
  }
406
 
 
435
  ctx.fillRect(0, 0, canvas.width, canvas.height);
436
 
437
  const hands = results.landmarks || [];
438
+ const mirroredHands = hands.map(hand => hand.map(lm => ({...lm, x: 1 - lm.x})));
439
+ document.getElementById('handCount').textContent = mirroredHands.length;
440
+
441
+ const fbData = processFireball(mirroredHands);
442
 
443
+ if (mirroredHands.length > 0) {
 
 
444
 
445
  // Draw Particles
446
  for (let i = particles.length - 1; i >= 0; i--) {
 
481
  drawMultiverseConnections(mirroredHands[0], mirroredHands[1]);
482
  }
483
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
  const g = fbData.actionText || detectGesture(mirroredHands[0]);
485
  const s = calcSpread(mirroredHands[0]);
486
  audio.updateSound(s, mirroredHands.length);
 
518
  }
519
  }
520
 
521
+ // Draw Charging Fireball (global so it persists if hands drop)
522
+ if (fbData.chargeRadius > 0 && fbData.chargePos) {
523
+ const r = fbData.chargeRadius;
524
+ ctx.save();
525
+ ctx.globalAlpha = 0.8 + Math.random() * 0.2;
526
+ const grad = ctx.createRadialGradient(fbData.chargePos.x, fbData.chargePos.y, 0, fbData.chargePos.x, fbData.chargePos.y, r);
527
+ grad.addColorStop(0, '#fff');
528
+ grad.addColorStop(0.3, '#ffaa00');
529
+ grad.addColorStop(1, 'rgba(255,0,0,0)');
530
+ ctx.fillStyle = grad;
531
+ ctx.beginPath();
532
+ ctx.arc(fbData.chargePos.x, fbData.chargePos.y, r, 0, Math.PI*2);
533
+ ctx.fill();
534
+ if (Math.random() > 0.5) {
535
+ ctx.fillStyle = `hsl(${20 + Math.random()*30}, 100%, 50%)`;
536
+ ctx.beginPath();
537
+ ctx.arc(fbData.chargePos.x + (Math.random()-0.5)*r, fbData.chargePos.y + (Math.random()-0.5)*r, 1.5, 0, Math.PI*2);
538
+ ctx.fill();
539
+ }
540
+ ctx.restore();
541
+ }
542
+
543
  animFrameId = requestAnimationFrame(detectLoop);
544
  } catch (err) {
545
  console.error("Error in detectLoop:", err);