← back to Model Arena

data/artifacts/0e969e848172/hf-qwen-coder-32b.html

101 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2D Gravity Sandbox</title>
<style>
  body { margin: 0; overflow: hidden; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #000; color: white; }
  canvas { border: 1px solid white; cursor: crosshair; }
  button, input { position: absolute; top: 10px; background-color: #333; color: white; border: none; padding: 5px 10px; cursor: pointer; }
  button:hover, input:hover { background-color: #555; }
  input { left: 120px; }
</style>
</head>
<body>
<canvas id="sandbox"></canvas>
<button onclick="clearCanvas()">Clear</button>
<input type="checkbox" id="trailToggle" checked> Trails
<script>
const canvas = document.getElementById('sandbox');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let bodies = [];
let showTrails = true;

function Body(x, y, mass) {
  this.x = x;
  this.y = y;
  this.mass = mass;
  this.vx = 0;
  this.vy = 0;
  this.trail = [];
}

Body.prototype.updateVelocity = function(bodies) {
  for (let body of bodies) {
    if (body === this) continue;
    let dx = body.x - this.x;
    let dy = body.y - this.y;
    let distance = Math.sqrt(dx * dx + dy * dy);
    let force = (this.mass * body.mass) / (distance * distance);
    let angle = Math.atan2(dy, dx);
    this.vx += force * Math.cos(angle) / this.mass;
    this.vy += force * Math.sin(angle) / this.mass;
  }
};

Body.prototype.updatePosition = function() {
  this.x += this.vx;
  this.y += this.vy;
  if (showTrails) {
    this.trail.push({x: this.x, y: this.y});
    if (this.trail.length > 100) this.trail.shift();
  }
};

Body.prototype.draw = function() {
  ctx.beginPath();
  ctx.arc(this.x, this.y, Math.log2(this.mass), 0, Math.PI * 2);
  ctx.fillStyle = 'white';
  ctx.fill();
  if (showTrails) {
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
    ctx.beginPath();
    ctx.moveTo(this.trail[0].x, this.trail[0].y);
    for (let point of this.trail) {
      ctx.lineTo(point.x, point.y);
    }
    ctx.stroke();
  }
};

function animate() {
  if (!showTrails) clearCanvas();
  bodies.forEach(body => body.updateVelocity(bodies));
  bodies.forEach(body => body.updatePosition());
  bodies.forEach(body => body.draw());
  requestAnimationFrame(animate);
}

canvas.addEventListener('click', function(event) {
  let rect = canvas.getBoundingClientRect();
  let x = event.clientX - rect.left;
  let y = event.clientY - rect.top;
  bodies.push(new Body(x, y, Math.random() * 100 + 10));
});

function clearCanvas() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  if (!showTrails) bodies.forEach(body => body.trail = []);
}

document.getElementById('trailToggle').addEventListener('change', function(event) {
  showTrails = event.target.checked;
});

animate();
</script>
</body>
</html>