JSFiddle - React, Tailwind, and code Playground

by Piara Singh

HTML

<div id="ball"></div>
<div><label> FPS: <input type="range" value="30" min="5" max="60" id="fps"></label></div>
<div><button id="jump">Jump</button> <i>Jump in the air also works</i></div>

CSS

#ball {
  background: red;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  position: absolute;
  bottom: 0;
}

JavaScript

var jumpStartY = 0; // pixels
var jumpStartVelocity = 0; // pixels / millisecond
var jumpStartTime = NaN; // milliseconds
var gravity = 0.005; // pixels / millisecond^2

function getCurrentHeight(now) {
	var timeDiff = (now - jumpStartTime);
  var height = jumpStartY + (
  	jumpStartVelocity + getCurrentVelocity(now)
  ) / 2 * timeDiff;
  
  // Do not fall lower than the bottom edge.
  // Or you may want to trigger gameover, like in Flappy bird
  if (height >= 0) {
  	return height;
  } else {
  	return 0;
  }
}

function getCurrentVelocity(now) {
  var timeDiff = (now - jumpStartTime);
  return jumpStartVelocity - gravity * timeDiff;
}

var ball = document.getElementById('ball');

function jump() {
	var now = Date.now();
  jumpStartY = getCurrentHeight(now);
	jumpStartVelocity = 1.5;
  jumpStartTime = now;
}

function drawFrame() {
	var now = Date.now();
  ball.style.bottom = getCurrentHeight(now) + 'px';
}


// UI And helpers

jump();

document.getElementById('jump').addEventListener('click', jump, false);

var fpsInput = document.getElementById('fps');

(function nextFrame(){
	drawFrame();
  setTimeout(nextFrame, 1000 / fpsInput.value);
})();