JSFiddle - React, Tailwind, and code Playground

by moritzkobrna

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.5/dat.gui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/victor/1.1.0/victor.js"></script>
<canvas id="canvas" width="800" height="800"></canvas>

<button onClick={window.doStep()}>Step</button>

JavaScript 1.7

const Vector = Victor;
const gui = new dat.GUI();

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

const MAX_STEP_LENGTH = 3;

const planets = [
	{
  	position: [180, 140],
    radius: 10,
  },
  {
  	position: [300, 300],
    radius: 10,
  },
];

const emitters = [
	{
  	position: [101, 101],
    angle: -80,
    velocity: 40,
  },
];

let bullets = [];

const calcForceVector = (bullet, lastX, lastY, planets) => {
  let totalForceVector = new Vector(0, 0);
  planets.forEach(({ position: [x, y], radius }) => {
    const dist = (new Vector(lastX, lastY).distance(new Vector(x, y)));
    const force = (1 / Math.pow(dist, 1)) * radius * 5;
      
    if (dist <= radius) return bullet.alive = false;
      
    const forceDirection = new Vector(x, y).subtract(new Vector(lastX, lastY)).normalize();
    const forceVector = forceDirection.multiply(new Vector(force, force));
    totalForceVector.add(forceVector);
  });
  return totalForceVector;
};

const step = (frame, ctx) => {
  bullets.filter((b) => b.alive).forEach((bullet) => {
  	const { path, vector } = bullet;
  	const [lastX, lastY] = path[path.length - 1];
		
    const forceVector = calcForceVector(bullet, lastX, lastY, planets);
    let newBulletVector = bullet.vector.clone().add(forceVector);
    const length = newBulletVector.length();
    if (length < MAX_STEP_LENGTH) {
	    bullet.vector = newBulletVector;    

      ctx.save();
      ctx.beginPath();
      ctx.moveTo(lastX, lastY);
      ctx.lineTo(lastX + (forceVector.x * 100), lastY + (forceVector.y * 100));
      ctx.strokeStyle = "rgba(0, 0, 255, 0.2)";
      ctx.stroke();
      ctx.restore();
        
			path.push([lastX + bullet.vector.x, lastY + bullet.vector.y]);
    } else {
    	newBulletVector = new Vector(0, 0);
    	const numSubSteps = Math.ceil(length / MAX_STEP_LENGTH);
      const subStepLength = length / numSubSteps;
      let subLastX = lastX;
      let subLastY = lastY;
      for (let i = 0; i <...