HTML5 Game - Friction to reduce velocity

Introduction

Adding Friction to reduce velocity

Demo

ResultView the demo in separate window

<!DOCTYPE html>

<html>
  <head>
    <style type="text/css">
#myCanvas {/*from w  ww  . jav a2 s  .c o m*/
  background: #001022;
}

#myButtons {
  bottom: 20px;
  left: 20px;
  position: absolute;
}

#myButtons button {
  padding: 5px;
}      
    </style>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <script type="text/javascript">
  
class Ball{
   constructor(x, y, radius, mass, vX, vY, aX, aY) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.mass = mass;
    
    this.vX = vX;
    this.vY = vY;
    this.aX = aX;
    this.aY = aY;
  }
}  
      
$(document).ready(function() {  
  let canvas = $("#myCanvas");
  let context = canvas.get(0).getContext("2d");
  
  let canvasWidth = canvas.width();
  let canvasHeight = canvas.height();
  
  $(window).resize(resizeCanvas);
  
  function resizeCanvas() {
    canvas.attr("width", $(window).get(0).innerWidth);
    canvas.attr("height", $(window).get(0).innerHeight);
    
    canvasWidth = canvas.width();
    canvasHeight = canvas.height();
  };
  
  resizeCanvas();
  
  let playAnimation = true;
  
  let startButton = $("#startAnimation");
  let stopButton = $("#stopAnimation");
  
  startButton.hide();
  startButton.click(function() {
    $(this).hide();
    stopButton.show();
    
    playAnimation = true;
    animate();
  });
  
  stopButton.click(function() {
    $(this).hide();
    startButton.show();
    
    playAnimation = false;
  });
  

  let balls = new Array();
  
  for (let i = 0; i < 10; i++) {
    let x = 20+(Math.random()*(canvasWidth-40));
    let y = 20+(Math.random()*(canvasHeight-40));
    
    let radius = 5+Math.random()*10;
    let mass = radius/2;
    
    let vX = Math.random()*4-2;
    let vY = Math.random()*4-2;
    let aX = 0;
    let aY = 0;
    
    balls.push(new Ball(x, y, radius, mass, vX, vY, aX, aY));
  };
  
  // Animation loop that does all the fun stuff
  function animate() {          
    // Clear
    context.clearRect(0, 0, canvasWidth, canvasHeight);
    
    context.fillStyle = "rgb(255, 255, 255)";
    
    // Loop through every ball
    let ballsLength = balls.length;
    for (let i = 0; i < ballsLength; i++) {
      let tmpBall = balls[i];
      
      for (let j = i+1; j < ballsLength; j++) {
        let tmpBallB = balls[j];
        
        let dX = tmpBallB.x - tmpBall.x;
        let dY = tmpBallB.y - tmpBall.y;
        let distance = Math.sqrt((dX*dX)+(dY*dY));
        
        if (distance < tmpBall.radius + tmpBallB.radius) {                
          let angle = Math.atan2(dY, dX);
          let sine = Math.sin(angle);
          let cosine = Math.cos(angle);
          
          // Rotate ball position
          let x = 0;
          let y = 0;
          
          // Rotate ballB position
          let xB = dX * cosine + dY * sine;
          let yB = dY * cosine - dX * sine;
            
          // Rotate ball velocity
          let vX = tmpBall.vX * cosine + tmpBall.vY * sine;
          let vY = tmpBall.vY * cosine - tmpBall.vX * sine;
          
          // Rotate ballB velocity
          let vXb = tmpBallB.vX * cosine + tmpBallB.vY * sine;
          let vYb = tmpBallB.vY * cosine - tmpBallB.vX * sine;
          
          // Reverse the velocities
          let vTotal = vX - vXb;
          vX = ((tmpBall.mass - tmpBallB.mass) * vX + 2 * tmpBallB.mass * vXb) / (tmpBall.mass + tmpBallB.mass);
          vXb = vTotal + vX;
          
          // Move balls apart
          xB = x + (tmpBall.radius + tmpBallB.radius);
          
          // Rotate ball positions back
          tmpBall.x = tmpBall.x + (x * cosine - y * sine);
          tmpBall.y = tmpBall.y + (y * cosine + x * sine);
          
          tmpBallB.x = tmpBall.x + (xB * cosine - yB * sine);
          tmpBallB.y = tmpBall.y + (yB * cosine + xB * sine);
          
          // Rotate ball velocities back
          tmpBall.vX = vX * cosine - vY * sine;
          tmpBall.vY = vY * cosine + vX * sine;
          
          tmpBallB.vX = vXb * cosine - vYb * sine;
          tmpBallB.vY = vYb * cosine + vXb * sine;
        };
      };
      
      tmpBall.x += tmpBall.vX;
      tmpBall.y += tmpBall.vY;
      
      if (Math.abs(tmpBall.vX) < 10) {
        tmpBall.vX += tmpBall.aX;
      }
      
      if (Math.abs(tmpBall.vY) < 10) {
        tmpBall.vY += tmpBall.aY;
      }
      
      if (Math.abs(tmpBall.vX) > 0.1) {
        tmpBall.vX *= 0.9;
      } else {
        tmpBall.vX = 0;
      };
      
      if (Math.abs(tmpBall.vY) > 0.1) {
        tmpBall.vY *= 0.9;
      } else {
        tmpBall.vY = 0;
      }
      if (tmpBall.x-tmpBall.radius < 0) {
        tmpBall.x = tmpBall.radius; 
        tmpBall.vX *= -1;
        tmpBall.aX *= -1;
      } else if (tmpBall.x+tmpBall.radius > canvasWidth) {
        tmpBall.x = canvasWidth-tmpBall.radius; 
        tmpBall.vX *= -1;
        tmpBall.aX *= -1;
      };
      
      if (tmpBall.y-tmpBall.radius < 0) {
        tmpBall.y = tmpBall.radius; 
        tmpBall.vY *= -1;
        tmpBall.aY *= -1;
      } else if (tmpBall.y+tmpBall.radius > canvasHeight) {
        tmpBall.y = canvasHeight-tmpBall.radius; // Move away from the edge
        tmpBall.vY *= -1;
        tmpBall.aY *= -1;
      };
      
      context.beginPath();
      context.arc(tmpBall.x, tmpBall.y, tmpBall.radius, 0, Math.PI*2);
      context.closePath();
      context.fill();
    };
    
    if (playAnimation) {
      setTimeout(animate, 40);
    };
  };
  animate();
});
      
    </script>
  </head>
  
  <body>
    <canvas id="myCanvas" width="500" height="500">
      <!-- Insert fallback content here -->
    </canvas>
    <div id="myButtons">
      <button id="startAnimation">Start</button>
      <button id="stopAnimation">Stop</button>
    </div>
  </body>
</html>

Related Topics