<html><head><title>Crypto Collision Physics Simulation</title>

<style>

  body {

    display: flex;

    justify-content: center;

    align-items: center;

    height: 100vh;

    margin: 0;

    background-color: #f0f0f0;

    font-family: Arial, sans-serif;

  }

  

  #container {

    width: 400px;

    height: 400px;

    border-radius: 50%;

    border: 2px solid #333;

    position: relative;

    overflow: hidden;

  }

  

  .crypto-ball {

    width: 40px;

    height: 40px;

    border-radius: 50%;

    position: absolute;

    display: flex;

    justify-content: center;

    align-items: center;

    font-weight: bold;

    font-size: 10px;

    color: #fff;

    text-shadow: 1px 1px 1px rgba(0,0,0,0.5);

  }


  #controls {

    position: absolute;

    top: 20px;

    left: 20px;

    background-color: rgba(255, 255, 255, 0.8);

    padding: 10px;

    border-radius: 5px;

  }


  label {

    display: block;

    margin-bottom: 5px;

  }


  input[type="range"] {

    width: 200px;

  }


  button {

    margin-top: 10px;

    padding: 5px 10px;

    background-color: #4CAF50;

    color: white;

    border: none;

    border-radius: 3px;

    cursor: pointer;

  }


  button:hover {

    background-color: #45a049;

  }

</style>

</head>

<body>

<div id="container"></div>


<div id="controls">

  <label for="gravity">Gravity: <span id="gravityValue">0.5</span></label>

  <input type="range" id="gravity" min="0" max="2" step="0.1" value="0.5">

  

  <label for="friction">Friction: <span id="frictionValue">0.99</span></label>

  <input type="range" id="friction" min="0.9" max="1" step="0.01" value="0.99">

  

  <label for="restitution">Restitution: <span id="restitutionValue">0.7</span></label>

  <input type="range" id="restitution" min="0" max="1" step="0.1" value="0.7">


  <button id="resetBalls">Reset Crypto</button>

</div>


<script>

const container = document.getElementById('container');

const containerRect = container.getBoundingClientRect();


let cryptoBalls = [];

let gravity = 0.5;

let friction = 0.99;

let restitution = 0.7;


const cryptoSymbols = ['BTC', 'ETH', 'ADA', 'SOL', 'DOGE', 'QQ', 'NO', 'PEPE', 'GF', 'PANDA', 'YAYA', 'SATOSHI', 'CAT', 'ORD', 'CLOWN', 'YY', 'JUMP', 'DONALD', 'A', 'MIMI', 'MIQI', 'RABBIT', 'SHEEP', 'SNAKE', 'PEACE', 'RAT', 'MONKEY', 'DRAGON', 'X', 'SEAL', 'COW', 'OTTER', 'ORD(', 'ORD{', 'ORD%', 'ORD<'];


const gravitySlider = document.getElementById('gravity');

const frictionSlider = document.getElementById('friction');

const restitutionSlider = document.getElementById('restitution');

const gravityValue = document.getElementById('gravityValue');

const frictionValue = document.getElementById('frictionValue');

const restitutionValue = document.getElementById('restitutionValue');

const resetButton = document.getElementById('resetBalls');


gravitySlider.addEventListener('input', updatePhysics);

frictionSlider.addEventListener('input', updatePhysics);

restitutionSlider.addEventListener('input', updatePhysics);

resetButton.addEventListener('click', resetCryptoBalls);


function updatePhysics() {

  gravity = parseFloat(gravitySlider.value);

  friction = parseFloat(frictionSlider.value);

  restitution = parseFloat(restitutionSlider.value);

  

  gravityValue.textContent = gravity.toFixed(1);

  frictionValue.textContent = friction.toFixed(2);

  restitutionValue.textContent = restitution.toFixed(1);

}


function resetCryptoBalls() {

  cryptoBalls.forEach(ball => container.removeChild(ball.element));

  cryptoBalls = [];

  createCryptoBall();

}


function createCryptoBall() {

  if (cryptoBalls.length >= 50) return null; // Limit the number of crypto balls


  const ballElement = document.createElement('div');

  ballElement.className = 'crypto-ball';

  const symbol = cryptoSymbols[Math.floor(Math.random() * cryptoSymbols.length)];

  ballElement.textContent = symbol;

  ballElement.style.backgroundColor = getRandomColor();

  container.appendChild(ballElement);


  const ball = {

    element: ballElement,

    x: containerRect.width / 2 - 20,

    y: containerRect.height / 2 - 20,

    vx: (Math.random() - 0.5) * 10,

    vy: (Math.random() - 0.5) * 10,

    radius: 20,

    lastBounceTime: 0,

    symbol: symbol

  };


  cryptoBalls.push(ball);

  return ball;

}


function getRandomColor() {

  const hue = Math.floor(Math.random() * 360);

  return `hsl(${hue}, 70%, 50%)`;

}


function animate() {

  const containerRadius = containerRect.width / 2;

  const centerX = containerRect.width / 2;

  const centerY = containerRect.height / 2;

  const currentTime = Date.now();


  cryptoBalls.forEach(ball => {

    // Apply gravity

    ball.vy += gravity;


    // Apply friction

    ball.vx *= friction;

    ball.vy *= friction;


    // Update position

    ball.x += ball.vx;

    ball.y += ball.vy;


    // Check for collisions with container

    const distanceFromCenter = Math.sqrt(Math.pow(ball.x - centerX, 2) + Math.pow(ball.y - centerY, 2));


    if (distanceFromCenter + ball.radius > containerRadius) {

      const angle = Math.atan2(ball.y - centerY, ball.x - centerX);

      const normalX = Math.cos(angle);

      const normalY = Math.sin(angle);

      

      const dotProduct = ball.vx * normalX + ball.vy * normalY;

      

      ball.vx -= (1 + restitution) * dotProduct * normalX;

      ball.vy -= (1 + restitution) * dotProduct * normalY;

      

      ball.x = centerX + (containerRadius - ball.radius) * Math.cos(angle);

      ball.y = centerY + (containerRadius - ball.radius) * Math.sin(angle);


      // Check if the ball is moving fast enough to consider it a bounce

      const speed = Math.sqrt(ball.vx * ball.vx + ball.vy * ball.vy);

      if (speed > 1 && currentTime - ball.lastBounceTime > 500) {

        ball.lastBounceTime = currentTime;

        createCryptoBall(); // Instantly create a new crypto ball on bounce

      }

    }


    // Check for collisions with other crypto balls

    cryptoBalls.forEach(otherBall => {

      if (ball === otherBall) return;


      const dx = otherBall.x - ball.x;

      const dy = otherBall.y - ball.y;

      const distance = Math.sqrt(dx * dx + dy * dy);


      if (distance < ball.radius + otherBall.radius) {

        // Collision detected

        const angle = Math.atan2(dy, dx);

        const sin = Math.sin(angle);

        const cos = Math.cos(angle);


        // Rotate ball velocities

        const vx1 = ball.vx * cos + ball.vy * sin;

        const vy1 = ball.vy * cos - ball.vx * sin;

        const vx2 = otherBall.vx * cos + otherBall.vy * sin;

        const vy2 = otherBall.vy * cos - otherBall.vx * sin;


        // Swap ball velocities

        const temp_vx1 = vx2;

        const temp_vy1 = vy1;

        const temp_vx2 = vx1;

        const temp_vy2 = vy2;


        // Rotate velocities back

        ball.vx = temp_vx1 * cos - temp_vy1 * sin;

        ball.vy = temp_vy1 * cos + temp_vx1 * sin;

        otherBall.vx = temp_vx2 * cos - temp_vy2 * sin;

        otherBall.vy = temp_vy2 * cos + temp_vx2 * sin;


        // Move balls apart

        const overlap = ball.radius + otherBall.radius - distance;

        const moveX = overlap * cos / 2;

        const moveY = overlap * sin / 2;


        ball.x -= moveX;

        ball.y -= moveY;

        otherBall.x += moveX;

        otherBall.y += moveY;

      }

    });


    // Update ball position

    ball.element.style.left = `${ball.x - ball.radius}px`;

    ball.element.style.top = `${ball.y - ball.radius}px`;

  });


  requestAnimationFrame(animate);

}


// Initialize with one crypto ball

createCryptoBall();

animate();


// Add interactivity to the crypto balls

let isDragging = false;

let draggedBall = null;

let startX, startY;


container.addEventListener('mousedown', startDrag);

document.addEventListener('mousemove', drag);

document.addEventListener('mouseup', endDrag);


container.addEventListener('touchstart', startDrag);

document.addEventListener('touchmove', drag);

document.addEventListener('touchend', endDrag);


function startDrag(e) {

  const clientX = e.type === 'mousedown' ? e.clientX : e.touches[0].clientX;

  const clientY = e.type === 'mousedown' ? e.clientY : e.touches[0].clientY;


  cryptoBalls.forEach(ball => {

    const rect = ball.element.getBoundingClientRect();

    if (clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom) {

      isDragging = true;

      draggedBall = ball;

      startX = clientX - ball.x;

      startY = clientY - ball.y;

      e.preventDefault();

      return;

    }

  });

}


function drag(e) {

  if (!isDragging || !draggedBall) return;

  

  const clientX = e.type === 'mousemove' ? e.clientX : e.touches[0].clientX;

  const clientY = e.type === 'mousemove' ? e.clientY : e.touches[0].clientY;


  draggedBall.x = clientX - startX;

  draggedBall.y = clientY - startY;


  const containerRadius = containerRect.width / 2;

  const centerX = containerRect.width / 2;

  const centerY = containerRect.height / 2;


  const distanceFromCenter = Math.sqrt(Math.pow(draggedBall.x - centerX, 2) + Math.pow(draggedBall.y - centerY, 2));


  if (distanceFromCenter + draggedBall.radius > containerRadius) {

    const angle = Math.atan2(draggedBall.y - centerY, draggedBall.x - centerX);

    draggedBall.x = centerX + (containerRadius - draggedBall.radius) * Math.cos(angle);

    draggedBall.y = centerY + (containerRadius - draggedBall.radius) * Math.sin(angle);

  }


  draggedBall.element.style.left = `${draggedBall.x - draggedBall.radius}px`;

  draggedBall.element.style.top = `${draggedBall.y - draggedBall.radius}px`;

}


function endDrag() {

  if (isDragging && draggedBall) {

    isDragging = false;

    draggedBall.vx = 0;

    draggedBall.vy = 0;

    draggedBall = null;

  }

}

</script>

</body></html>