反向重力:如何将值重置为默认值?

reverse gravity : how to reset the values to their default values?

我尝试创建反向重力,但在我多次单击“物理”按钮后出现问题:它应该以默认值重新启动,但在 10 次之后,球移动得太快并且我不明白为什么。该函数第一次运行良好,但随后每次单击“物理”时它开始加速。

https://codepen.io/Arthur222/pen/QWOgMXq

let isOn = 0;
let canvas = document.getElementById("canvas");
if (canvas.getContext('2d') == null ) alert("erreur javascript");
let ctx = canvas.getContext('2d');
let velocity=1, force=1, mass = 1, radius=30;
let lastTs;

//FCN


window.addEventListener('load', ()=>{
    resize();
    window.addEventListener('resize', resize);
    createBalls();
    drawBalls();
});

// PHYSICS


let balls = [];
function createBalls(){
  for ( let i=0; i<6; i++){
    let x = radius+(i*radius*2);
    if (i>0) x = radius+(i*(radius+10)*2);
    let vel = Math.random();
    let ball = {x:x, y:250, xBase:x, yBase:250, velocity:vel, velocityBase:vel, radius:30, active:true}
    balls.push(ball);
  }
}


function startPhy1(){

  if (isOn == 1){
    console.log("canvas.width, canvas.height : "+canvas.width, canvas.height);
    ctx.clearRect(0,0,canvas.width, canvas.height);
    balls.forEach(element => {
      element.y = element.yBase;
      element.active = true;
      element.velocity = element.velocityBase;
    });
  }

  isOn = 1;
  lastTs = getTimestamp();
  runPhy();
  draw();
} 

function runPhy(){
  let t = (getTimestamp() - lastTs)/1000;

  balls.forEach(element => {
    if ( element.active ){ //still below
      element.y -= element.velocity * t;
      element.velocity += ( force / mass ) * t;
      if ( element.y <= element.radius+10 ){//already on top
        element.active = false;
        element.y = element.radius;//stay on top
      }
    }
  });
  requestAnimationFrame(runPhy);
  
}

function getTimestamp() {
  return new Date().getTime();
}
// DRAW 

function draw(){
  drawBalls();
  requestAnimationFrame(draw);
}

function drawBalls(){
  ctx.clearRect(0,0,canvas.width, canvas.height);
  for (let i=0; i< balls.length; i++){

    
    ctx.beginPath();
    ctx.arc(balls[i].x, balls[i].y, balls[i].radius, 0, 2 * Math.PI, false);
    ctx.strokeStyle = "green";
    ctx.lineWidth = 2;
    ctx.stroke();
  }
  
}


function resize(){
  ctx.canvas.width = window.innerWidth*0.7;
  ctx.canvas.height = window.innerHeight*0.9;
}

我认为您的代码存在问题,每次单击按钮时您都在请求动画帧。

我尝试修复您的代码但没有成功,这就是我编写此代码的原因。试一试:

const canvas = document.getElementById('root')
const btn = document.getElementById('btn')
const ctx = canvas.getContext('2d')
const circleImage = new Image()
      
circleImage.src = 'https://i.stack.imgur.com/CdziF.png'

var piece = {
  image: circleImage,
  x: 100,
  y: 250,
  width: 50
}
     
var speed = 0    
var max = 10   
    
function gameLoop(){ 
  ctx.clearRect(0, 0, canvas.width, canvas.height) 
  ctx.drawImage(piece.image, piece.x, piece.y)    
  
  speed < max ? speed += 0.1 : null
  
  if(piece.y > 0){
    piece.y -= speed
    piece.y < 0 ? piece.y = 0 : null // Position correction
  }
  window.requestAnimationFrame(gameLoop)   // Needed to keep looping
}

function start(){
  if(btn.value === 'start'){
    btn.value = 'restart'   
    circleImage.onload = window.requestAnimationFrame(gameLoop)  // Start gameLoop()
  }
  if(btn.value === 'restart'){
    speed = 0  
    piece.y = 250
  }
}

btn.addEventListener('click', start) // When btn is clicked execute start()
<input id="btn" type="button" value="start" />
<p>
<canvas id="root" height="300" width="300" style="border:1px solid grey">

并在此处查看每次单击 a 按钮时请求请求动画帧时发生的情况:

const canvas = document.getElementById('root')
const btn = document.getElementById('btn')
const ctx = canvas.getContext('2d')
const circleImage = new Image()
      
circleImage.src = 'https://i.stack.imgur.com/CdziF.png'

var piece = {
  image: circleImage,
  x: 100,
  y: 250,
  width: 50
}
     
var speed = 0    
var max = 10   
    
function gameLoop(){ 
  ctx.clearRect(0, 0, canvas.width, canvas.height) 
  ctx.drawImage(piece.image, piece.x, piece.y)    
  
  speed < max ? speed += 0.1 : null
  
  if(piece.y > 0){
    piece.y -= speed
    piece.y < 0 ? piece.y = 0 : null // Position correction
  }
  window.requestAnimationFrame(gameLoop)   // Needed to keep looping
}

function start(){
  if(btn.value === 'start'){
    speed = 0  
    piece.y = 250
    circleImage.onload = window.requestAnimationFrame(gameLoop)  // Start gameLoop()
  }
}

btn.addEventListener('click', start) // When btn is clicked execute start()
<input id="btn" type="button" value="start" />
<p>
<canvas id="root" height="300" width="300" style="border:1px solid grey">