← 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>