(Javascript) 弹跳球夹在墙上

(Javascript) Bouncing balls clip into wall

document.addEventListener("DOMContentLoaded", function(event){
 var context,
  width = window.screen.availWidth - 120,
  height = window.screen.availHeight - 120,
  xTemp, 
  yTemp,
  x = [], 
  y = [], 
  dx = [0], 
  dy = [5], 
  gravity = [1],
  bounceTime = [1],
  canvas = document.getElementById("bouncingField"), 
  isSpawned = 0,
  image = new Image();
  
 document.getElementById("bouncingField").width = width;
 document.getElementById("bouncingField").height = height;
 
 //Image to use as ball texture
 image.src = "http://www.freeiconspng.com/uploads/soccer-ball-icon-14.png";
  
 //Run func init on page load
 window.onload = init;
 
 //Get 2d context and repaint every 10 milliseconds
 context = bouncingField.getContext('2d');
 setInterval(repaint, 10);
 
 canvas.onclick = function setSpawnTrue(){
  if(!isSpawned){
   x[0] = xTemp;
   y[0] = yTemp;
  } else{
   x.push(xTemp);
   y.push(yTemp);
   dx.push(0);
   dy.push(5);
   gravity.push(1);
   bounceTime.push(1);
  }
  
  isSpawned = 1;
 }
 
 //Draws the various entities
 function draw(){
  context = bouncingField.getContext('2d');
  for(var i = 0; i < x.length; i++){ 
   //context.beginPath();
   //context.fillStyle = "#00ccff";
   //Draw circles of r = 25 at coordinates x and y
   //context.arc(x[i], y[i], 25, 0, Math.PI*2, true);
   context.drawImage(image, x[i], y[i], 50, 50);
   //context.closePath();
   //context.fill();
  }
 }

 //Repaints entities, essentially animating them 
 function repaint(){
  for(var i = 0; i < x.length; i++){
   context.clearRect(0, 0, 2000, 2000);
   if(x[i] < 20 || x[i] > width) dx[i] *= -1;
   if(y[i] < 20 || y[i] > height) {
    dy[i] *= -1;
    //We add bounceTime to dy so that it gradually loses speed
    dy[i] += bounceTime[i];
    //Inverting graviy to slow down on rise
    gravity[i] *= -1;
   }
   
   x[i] += dx[i];
   //Gravity affects the ball bounce speed, that gradually slows down.
   y[i] += dy[i] + gravity[i];
   //bounceTime gradually reduces the amount of speed the ball has
   gravity[i] += 0.2 * bounceTime[i];
   bounceTime[i] += 0.01;
   if(isSpawned){
    draw();
   }
  }
 }
 
 //Initializes Event.MOUSEMOVE to capture cursor coordinates
 function init(){
  if(window.Event){
   document.captureEvents(Event.MOUSEMOVE);
  }
  document.onmousemove = getCoordinates;
 }
  
 //Gets mouse coordinates and puts them into xTemp and yTemp
 function getCoordinates(e){
  xTemp = (window.Event) ? e.pageX : event.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
  yTemp = (window.Event) ? e.pageY : event.clientY + (document.documentElement.scrollRight ? document.documentElement.scrollRight : document.body.scrollRight);
  xTemp -= 14;
  yTemp -= 14;
 }
});
body{
 background-color: #555555;
}

#bouncingField{
 border-style: solid;
 border-width: 10px;
 border-color: white;
}
<HTML>
 <HEAD>
  <TITLE>
   Wingin' it
  </TITLE>
  
  <script type="text/javascript" src="script.js"></script>
  
  <link href="style.css" rel="stylesheet" type="text/css">
 
 </HEAD>
 
 <BODY>
  <CANVAS id="bouncingField" width="0" height="0"></CANVAS>
 </BODY>
</HTML>

我正在做一个简单的 JavaScript 项目来创建模拟重力并从地板或墙壁反弹的弹跳球。问题是有时它们会夹在地板上 "spaz out" 直到它们从屏幕上消失。任何线索为什么?我一直试图通过在每次碰撞时添加一个微小的超时来解决这个问题,但是 JS 没有睡眠,所以我现在很困惑。

提前谢谢你:)

希望对您有所帮助。棘手的部分是制作令人信服的 "stop".

function getCoordinates(event) { return { x: event.offsetX, y: event.offsetY }; }

function spawnBall(coords, x, y, dx, dy){
    x.push(coords.x);
    y.push(coords.y);
    dx.push(0);
    dy.push(2);
}

// =========================
// Draws the various entities
// =========================
function draw(canvas, image, x, y, width, height) {
    var context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    for(var i = 0; i < x.length; i++){ context.drawImage(image, x[i], y[i], width, height); }
}
// =========================

// =========================
// At the moment all this is concerned with is the "floor"
// =========================
function move(x, y, dx, dy, gravity, bounciness, floor){
    for(var i = 0; i < x.length; i++){
      // =========================
      // Ball is close to the floor and not moving very fast, set it to rest
      // otherwise it bounces forever.
      // =========================
      if (y[i] >= floor - 10 && Math.abs(dy[i]) <= 2 * gravity) {
          dy[i] = 0;
          y[i] = floor;
          continue;
      }
      // =========================

      // =========================
      // Update the speed and position
      // =========================
      dy[i] += gravity;
      y[i] += dy[i];
      // =========================

      // =========================
      // Simulate a bounce if we "hit" the floor
      // =========================
      if(y[i] > floor) {
          y[i] = floor - (y[i] - floor);
          dy[i] = -1.0 * bounciness * dy[i];
      }
      // =========================
  }
}
// =========================

document.addEventListener("DOMContentLoaded", function(event){
    var canvas = document.getElementById("bouncingField");
    canvas.width = window.innerWidth - 50;
    canvas.height = window.innerHeight - 50;

    //Image to use as ball texture
    var image = new Image();
    image.src = "http://www.freeiconspng.com/uploads/soccer-ball-icon-14.png";

    var gravity = 1;
    var ballSize = 50;
    var ballBounciness = 0.8;
    var floor = canvas.height - ballSize;

    var x = [];
    var y = [];
    var dx = [];
    var dy = [];

    // =========================
    // This can be done via requestAnimationFrame()
    // https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
    // =========================
    var isSpawned = false;
    setInterval(function(){
        if(!isSpawned){ return; }
        move(x, y, dx, dy, gravity, ballBounciness, floor)
        draw(canvas, image, x, y, ballSize, ballSize);
    }, 10);
    // =========================

    // =========================
    // Add a ball
    // =========================
    canvas.onclick = function(event) {
        isSpawned = true;
        var coords = getCoordinates(event);
        spawnBall(coords, x, y, dx, dy);
    }
    // =========================
});
body {
  background-color: #555555;
}
#bouncingField {
  border-style: solid;
  border-width: 10px;
  border-color: white;
}
<canvas id="bouncingField"></canvas>