Home > Blockchain >  reverse gravity : how to reset the values to their default values?
reverse gravity : how to reset the values to their default values?

Time:02-12

I try to create reverse gravity, and I have an issue after I click several times on the button "physics" : it is supposed to restart with the default values, but after 10 times, the balls go too fast and I don't understand why. The function works fine the first time, but then it starts to accelerate each time you click on "physics".

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;
}

CodePudding user response:

I think the problem with your code is that you are requesting the animation frame every time that the button is clicked.

I tried fixing your code without success, that's why I coded this one. Try it:

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">

And see here what happens when the request animation frame is requested everytime the a button is clicked:

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">

  • Related