카테고리 없음

html canvas - 움직이는 공 5개

OJR 2023. 3. 31. 23:04

 

 

 

 

<canvas id="myCanvas" width="600" height="600"></canvas>

<script>
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");

// Define a Ball class to represent the balls in the canvas
class Ball {
  constructor(x, y, dx, dy, radius, color) {
    this.x = x;
    this.y = y;
    this.dx = dx;
    this.dy = dy;
    this.radius = radius;
    this.color = color;
  }
  
  // Define a draw() method to draw the ball on the canvas
  draw() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.closePath();
  }
  
  // Define an update() method to update the position of the ball
  update() {
    this.x += this.dx;
    this.y += this.dy;
    
    // Reverse direction if the ball hits the canvas edge
    if (this.x + this.radius > canvas.width || this.x - this.radius < 0) {
      this.dx = -this.dx;
    }
    if (this.y + this.radius > canvas.height || this.y - this.radius < 0) {
      this.dy = -this.dy;
    }
  }
  
  // Define a collisionDetection() method to detect collisions between balls
  collisionDetection(balls) {
    for (let i = 0; i < balls.length; i++) {
      if (this === balls[i]) continue;
      if (getDistance(this.x, this.y, balls[i].x, balls[i].y) < this.radius + balls[i].radius) {
        resolveCollision(this, balls[i]);
      }
    }
  }
}

// Define a function to generate a random integer within a range
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

// Define a function to get the distance between two points
function getDistance(x1, y1, x2, y2) {
  const xDistance = x2 - x1;
  const yDistance = y2 - y1;
  return Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2));
}

function resolveCollision(ball1, ball2) {
  // Calculate the velocities and distances between the balls
  const xVelocityDiff = ball1.dx - ball2.dx;
  const yVelocityDiff = ball1.dy - ball2.dy;
  const xDist = ball2.x - ball1.x;
  const yDist = ball2.y - ball1.y;
  
  // Check if the balls are moving towards each other
  if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0) {
    // Calculate the angle between the balls
    const angle = -Math.atan2(yDist, xDist);
    
    // Calculate the mass and velocity vectors for each ball
    const m1 = ball1.radius;
    const m2 = ball2.radius;
    const u1 = rotate(ball1.dx, ball1.dy, angle);
    const u2 = rotate(ball2.dx, ball2.dy, angle);
    
    // Calculate the new velocity vectors for each ball
    const v1 = { x: u1.x * (m1 - m2) / (m1 + m2) + u2.x * 2 * m2 / (m1 + m2), y: u1.y };
    const v2 = { x: u2.x * (m1 - m2) / (m1 + m2) + u1.x * 2 * m1 / (m1 + m2), y: u2.y };
    
    // Rotate the velocity vectors back to the original coordinate system
    const vFinal1 = rotate(v1.x, v1.y, -angle);
    const vFinal2 = rotate(v2.x, v2.y, -angle);
    
    // Update the velocity vectors and positions of the balls
    ball1.dx = vFinal1.x;
    ball1.dy = vFinal1.y;
    ball2.dx = vFinal2.x;
    ball2.dy = vFinal2.y;
    ball1.x += ball1.dx;
    ball1.y += ball1.dy;
    ball2.x += ball2.dx;
    ball2.y += ball2.dy;
  }
}

// Define a helper function to rotate a vector by an angle
function rotate(dx, dy, angle) {
  const rotated = {
    x: dx * Math.cos(angle) - dy * Math.sin(angle),
    y: dx * Math.sin(angle) + dy * Math.cos(angle)
  };
  return rotated;
}

const balls = [];

// Create five balls with random properties
for (let i = 0; i < 5; i++) {
  const x = getRandomInt(30, canvas.width-30);
  const y = getRandomInt(30, canvas.height-30);
  const dx = getRandomInt(-5, 5);
  const dy = getRandomInt(-5, 5);
  const radius = getRandomInt(10, 30);
  const color = `rgb(${getRandomInt(0, 255)}, ${getRandomInt(0, 255)}, ${getRandomInt(0, 255)})`;
  balls.push(new Ball(x, y, dx, dy, radius, color));
}

// Draw each ball on the canvas
//balls.forEach(ball => ball.draw());


function animate() {
  // Clear the canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // Update the position of each ball and redraw it on the canvas
  balls.forEach(ball => {
    ball.update();
    ball.draw();
    ball.collisionDetection(balls);
  });

  // Request the next animation frame
  requestAnimationFrame(animate);
}

// Start the animation
animate();


</script>