HTML Canvas Animation Bouncing Balls With Interactions

Description

HTML Canvas Animation Bouncing Balls With Interactions

View in separate window

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>/*ww w  .j a v  a2s .  c  o m*/
<body>
  <canvas id="canvasOne" width="500" height="500">
 Your browser does not support the HTML 5 Canvas. 
</canvas>
  <script type="text/javascript">
    function drawScreen() {
      context.fillStyle = '#EEEEEE';
      context.fillRect(0, 0, theCanvas.width, theCanvas.height);
      //Box
      context.strokeStyle = '#000000';
      context.strokeRect(1, 1, theCanvas.width - 2, theCanvas.height - 2);

      update();
      testWalls();
      collide();
      render();

    }

    function update() {
      for (let i = 0; i < balls.length; i++) {
        ball = balls[i];
        ball.nextx = (ball.x += ball.velocityx);
        ball.nexty = (ball.y += ball.velocityy);
      }

    }

    function testWalls() {
      let ball;
      let testBall;

      for (let i = 0; i < balls.length; i++) {
        ball = balls[i];

        if (ball.nextx + ball.radius > theCanvas.width) {
          ball.velocityx = ball.velocityx * -1;
          ball.nextx = theCanvas.width - ball.radius;

        } else if (ball.nextx - ball.radius < 0) {
          ball.velocityx = ball.velocityx * -1;
          ball.nextx = ball.radius;

        } else if (ball.nexty + ball.radius > theCanvas.height) {
          ball.velocityy = ball.velocityy * -1;
          ball.nexty = theCanvas.height - ball.radius;

        } else if (ball.nexty - ball.radius < 0) {
          ball.velocityy = ball.velocityy * -1;
          ball.nexty = ball.radius;
        }

      }

    }

    function render() {
      let ball;
      context.fillStyle = "#000000";
      for (let i = 0; i < balls.length; i++) {
        ball = balls[i];
        ball.x = ball.nextx;
        ball.y = ball.nexty;

        context.beginPath();
        context.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2, true);
        context.closePath();
        context.fill();
      }

    }

    function collide() {
      let ball;
      let testBall;
      for (let i = 0; i < balls.length; i++) {
        ball = balls[i];
        for (let j = i + 1; j < balls.length; j++) {
          testBall = balls[j];
          if (hitTestCircle(ball, testBall)) {
            collideBalls(ball, testBall);
          }
        }
      }
    }

    function hitTestCircle(ball1, ball2) {
      let retval = false;
      let dx = ball1.nextx - ball2.nextx;
      let dy = ball1.nexty - ball2.nexty;
      let distance = (dx * dx + dy * dy);
      if (distance <= (ball1.radius + ball2.radius)
          * (ball1.radius + ball2.radius)) {
        retval = true;
      }
      return retval;
    }

    function collideBalls(ball1, ball2) {

      let dx = ball1.nextx - ball2.nextx;
      let dy = ball1.nexty - ball2.nexty;

      let collisionAngle = Math.atan2(dy, dx);

      let speed1 = Math.sqrt(ball1.velocityx * ball1.velocityx
          + ball1.velocityy * ball1.velocityy);
      let speed2 = Math.sqrt(ball2.velocityx * ball2.velocityx
          + ball2.velocityy * ball2.velocityy);

      let direction1 = Math.atan2(ball1.velocityy, ball1.velocityx);
      let direction2 = Math.atan2(ball2.velocityy, ball2.velocityx);

      let velocityx_1 = speed1 * Math.cos(direction1 - collisionAngle);
      let velocityy_1 = speed1 * Math.sin(direction1 - collisionAngle);
      let velocityx_2 = speed2 * Math.cos(direction2 - collisionAngle);
      let velocityy_2 = speed2 * Math.sin(direction2 - collisionAngle);

      let final_velocityx_1 = ((ball1.mass - ball2.mass) * velocityx_1 + (ball2.mass + ball2.mass)
          * velocityx_2)
          / (ball1.mass + ball2.mass);
      let final_velocityx_2 = ((ball1.mass + ball1.mass) * velocityx_1 + (ball2.mass - ball1.mass)
          * velocityx_2)
          / (ball1.mass + ball2.mass);

      let final_velocityy_1 = velocityy_1;
      let final_velocityy_2 = velocityy_2;

      ball1.velocityx = Math.cos(collisionAngle) * final_velocityx_1
          + Math.cos(collisionAngle + Math.PI / 2)
          * final_velocityy_1;
      ball1.velocityy = Math.sin(collisionAngle) * final_velocityx_1
          + Math.sin(collisionAngle + Math.PI / 2)
          * final_velocityy_1;
      ball2.velocityx = Math.cos(collisionAngle) * final_velocityx_2
          + Math.cos(collisionAngle + Math.PI / 2)
          * final_velocityy_2;
      ball2.velocityy = Math.sin(collisionAngle) * final_velocityx_2
          + Math.sin(collisionAngle + Math.PI / 2)
          * final_velocityy_2;

      ball1.nextx = (ball1.nextx += ball1.velocityx);
      ball1.nexty = (ball1.nexty += ball1.velocityy);
      ball2.nextx = (ball2.nextx += ball2.velocityx);
      ball2.nexty = (ball2.nexty += ball2.velocityy);
    }

    let numBalls = 100;
    let maxSize = 15;
    let minSize = 5;
    let maxSpeed = maxSize + 5;
    let balls = new Array();
    let tempBall;
    let tempX;
    let tempY;
    let tempSpeed;
    let tempAngle;
    let tempRadius;
    let tempRadians;
    let tempvelocityx;
    let tempvelocityy;

    theCanvas = document.getElementById('canvasOne');
    context = theCanvas.getContext('2d');

    for (let i = 0; i < numBalls; i++) {
      tempRadius = 5;
      let placeOK = false;
      while (!placeOK) {
        tempX = tempRadius
            * 3
            + (Math.floor(Math.random() * theCanvas.width) - tempRadius * 3);
        tempY = tempRadius
            * 3
            + (Math.floor(Math.random() * theCanvas.height) - tempRadius * 3);
        tempSpeed = 4;
        tempAngle = Math.floor(Math.random() * 360);
        tempRadians = tempAngle * Math.PI / 180;
        tempvelocityx = Math.cos(tempRadians) * tempSpeed;
        tempvelocityy = Math.sin(tempRadians) * tempSpeed;

        tempBall = {
          x : tempX,
          y : tempY,
          nextX : tempX,
          nextY : tempY,
          radius : tempRadius,
          speed : tempSpeed,
          angle : tempAngle,
          velocityx : tempvelocityx,
          velocityy : tempvelocityy,
          mass : tempRadius
        };
        placeOK = canStartHere(tempBall);
      }
      balls.push(tempBall);
    }

    function canStartHere(ball) {
      let retval = true;
      for (let i = 0; i < balls.length; i++) {
        if (hitTestCircle(ball, balls[i])) {
          retval = false;
        }
      }
      return retval;
    }
    function gameLoop() {
      window.setTimeout(gameLoop, 20);
      drawScreen()
    }

    gameLoop();
  </script>
</body>
</html>



PreviousNext

Related