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 options = {
fieldSize: {w: 800, h: 800},
forceFieldResolution: 5,
forceFieldVectorScale: 50,
gravitationalConstant: 0.01,
maxStepLength: 5,
showForceField: true,
};
const planets = [
{
position: [180, 140],
radius: 30,
},
{
position: [350, 300],
radius: 25,
},
{
position: [220, 250],
radius: 20,
},
{
position: [100, 330],
radius: 40,
},
];
const emitters = [
{
position: [110, 80],
angle: -90,
velocity: 6,
},
];
let bullets = [];
const forceField = [];
const calcForceFieldVector = (x, y, bullet) => {
let forceVector = new Vector(0, 0);
planets.forEach(({ position: [x2, y2], radius }) => {
const vector = new Vector(x2 - x, y2 - y);
const dist = vector.length();
if (dist < radius) {
if (bullet) bullet.alive = false;
return;
}
const force = (1 / Math.pow(dist, 1)) * radius * radius * options.gravitationalConstant;
vector.normalize().multiply(new Vector(force, force));
forceVector.add(vector);
});
return forceVector;
}
const calcForceField = (resolution) => {
for (let x = 0; x < options.fieldSize.w; x += options.forceFieldResolution) {
forceField[x] = [];
for (let y = 0; y < options.fieldSize.h; y += options.forceFieldResolution) {
forceField[x][y] = calcForceFieldVector(x, y);
}
}
}
const step = (frame, ctx) => {
bullets.filter((b) => b.alive).forEach((bullet) => {
const { path, vector } = bullet;
const [lastX, lastY] = path[path.length - 1];
const forceVector = calcForceFieldVector(lastX, lastY, bullet);
let newBulletVector = bullet.vector.clone().add(forceVector);
const length = newBulletVector.length();
if (length < options.maxStepLength) {
bullet.vector = newBulletVector;
ctx.save();
ctx.beginPath();
ctx.moveTo(lastX, lastY);
...