)
}
}
)
(
}
{
)
)
(
)
(
(
{
}
)
(
)
}
)
)
{
(
(
)
)
}
)
(
}

Two Circles Explode

  1. const { random, min, sqrt, cos, sin, PI } = Math
  2. let TWO_PI = PI * 2
  3. let minSize
  4.  
  5. document.body.style.margin = 0
  6. document.body.style.background = 'black'
  7. const canvas = document.body.appendChild(
  8.   document.createElement('canvas')
  9. )
  10. const c = canvas.getContext('2d')
  11.  
  12. addEventListener('resize', resize)
  13. resize()
  14.  
  15. function resize() {
  16.   canvas.width = innerWidth
  17.   canvas.height = innerHeight
  18.   minSize = min(innerWidth, innerHeight)
  19.   clear()
  20. }
  21.  
  22. function clear() {
  23.   c.fillStyle = 'rgba(0, 0, 0, .15)'
  24.   c.fillRect(0, 0, innerWidth, innerHeight)
  25. }
  26.  
  27. let dots = []
  28. function dot({x, y, vx, vy, rad, grav = .15}) {
  29.   let sx = x
  30.   let sy = y
  31.   let svx = vx
  32.   let svy = vy
  33.   let intersected
  34.   let partsNum = 20
  35.   let parts = []
  36.   let delay = random() * 5
  37.   let time = 0
  38.  
  39.   dots.push(() => y > innerHeight)
  40.  
  41.   return {
  42.     step() {
  43.       time++
  44.       if (time < delay) return
  45.       if (intersected) {
  46.         for (let i = 0; i < partsNum; i++) {
  47.           parts[i].step()
  48.         }
  49.         return
  50.       }
  51.       x += vx
  52.       y += vy
  53.       vy += grav;
  54.       c.beginPath()
  55.       c.arc(x, y, rad(), 0, 7)
  56.       c.fill()
  57.     },
  58.     reset() {
  59.       x = sx;
  60.       y = sy;
  61.       vx = svx;
  62.       vy = svy;
  63.       intersected = false
  64.     },
  65.     hit() {
  66.       if (!intersected) {
  67.         partsNum = rad() / 3
  68.         for (let i = 0; i < partsNum; i++) {
  69.           let t = random() * TWO_PI
  70.           let r = 5 + random() * 5
  71.           let size = random() * 10
  72.  
  73.           parts.push(
  74.             dot({
  75.               x, y,
  76.               vx: r * cos(t),
  77.               vy: r * sin(t),
  78.               rad: () => size
  79.             })
  80.           )
  81.         }
  82.       }
  83.       intersected = true
  84.     },
  85.     get x() {
  86.       return x
  87.     },
  88.     get y() {
  89.       return y
  90.     }
  91.   }
  92. }
  93.  
  94. const bigRad = () => minSize * .14;
  95.  
  96. let leftDot
  97. let rightDot
  98.  
  99. function start() {
  100.  
  101.   rightDot = dot({
  102.     x: innerWidth, 
  103.     y: innerHeight / 2, 
  104.     vx: -innerWidth * .005, 
  105.     vy: -6, rad: bigRad
  106.   })
  107.  
  108.   leftDot = dot({
  109.     x: 0, 
  110.     y: innerHeight / 2, 
  111.     vx: innerWidth * .005, 
  112.     vy: -6, rad: bigRad
  113.   })
  114. }
  115. start()
  116.  
  117. function collide(a, b) {
  118.   const dx = a.x - b.x
  119.   const dy = a.y - b.y
  120.   const dist = sqrt(dx**2 + dy**2)
  121.   return dist <= bigRad() * 1.8
  122. }
  123.  
  124. function loop() {
  125.   let inc = 2
  126.  
  127.   clear()
  128.   c.fillStyle = 'white'
  129.   if (collide(leftDot, rightDot)) {
  130.  
  131.     leftDot.hit()
  132.     rightDot.hit()
  133.   }
  134.  
  135.   leftDot.step()
  136.   rightDot.step()
  137.  
  138.   dots.forEach(done => {
  139.     if (done()) inc++;
  140.   }) 
  141.  
  142.   if (dots.length > 2 && inc == dots.length)  {
  143.     dots = []
  144.     start()
  145.   }
  146.  
  147.   requestAnimationFrame(loop)
  148. }
  149. loop()

Two circles intersect and explode repeatedly… works at any browser size…

snippet.zone ~ 2021-24 /// {s/z}