JSFiddle - React, Tailwind, and code Playground

by Josh Pullen

HTML

<canvas id="game"></canvas>

Gravity field: &lt;
<input type="text" id="gravX" value="0" />,
<input type="text" id="gravY" value="-1" />
&gt;

<button id="run">Run</button>

CSS

#game {
  border: 1px solid black;
}

JavaScript

const canvas = document.querySelector("#game");
const ctx = canvas.getContext("2d");

const gravXInput = document.querySelector("#gravX");
const gravYInput = document.querySelector("#gravY");

const runButton = document.querySelector("#run");

canvas.width = 640;
canvas.height = 480;

const player = {
  position: [0, 0],
  velocity: [0, 0]
};

runButton.addEventListener("click", function() {
	player.position = [0, 0];
  player.velocity = [0, 0];
});

const level = {
  rects: [
    { top: -5, bottom: -6, left: -8, right: 8 },
    { top: 6, bottom: 5, left: -8, right: 8 },
    { top: 5, bottom: -5, left: -8, right: -7 },
    { top: 5, bottom: -5, left: 7, right: 8 },

    { top: 2, bottom: -3, left: 2, right: 5 },
    { top: -2, bottom: -5, left: -5, right: -2 }
  ]
};

function getGravity(x, y) {
	try {
    return [
    	eval(gravXInput.value) / 100,
      eval(gravYInput.value) / 100
    ];
  } catch (err) {
    return [0, 0];
  }
}

function render() {
  ctx.clearRect(0, 0, 640, 480);

  ctx.fillStyle = "blue";
  ctx.fillRect(
    320 + 40 * (player.position[0] - 0.5),
    240 - 40 * (player.position[1] - 0.5),
    40,
    40
  );

  ctx.fillStyle = "black";
  for (const rect of level.rects) {
    ctx.fillRect(
      320 + 40 * rect.left,
      240 - 40 * rect.top,
      40 * Math.abs(rect.right - rect.left),
      40 * Math.abs(rect.top - rect.bottom)
    );
  }
  
  for (let x = -8; x <= 8; x += 0.5) {
  	for (let y = -6; y <= 6; y += 0.5) {
      /* const gravity = getGravity(x, y) */;
      const gravity = [0, -1];
    	drawArrow(
      	320 + 40 * x,
        240 - 40 * y,
        5 * gravity[0],
        -5 * gravity[1]
      );
    }
  }
}

function drawArrow(x, y, dx, dy) {
	ctx.fillStyle = "blue";
  ctx.beginPath();
  ctx.arc(x, y, 1, 0, 2 * Math.PI);
  ctx.fill();

	ctx.strokeStyle = "blue";
  ctx.lineWidth = 1;
  
  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(x + dx, y + dy);
  ctx.stroke();
}

function update() {
  try {
    player.velocity =...