solar_sys / index.html
broadfield-dev's picture
Update index.html
5a59d0c verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Balls in Rotating Hexagon</title>
<style>
canvas {
border: 1px solid black;
display: block;
margin: auto;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// Ball class
class Ball {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.vx = Math.random() * 2 - 1;
this.vy = Math.random() * 2 - 1;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
move() {
this.x += this.vx;
this.y += this.vy;
this.vy += 0.05; // gravity
}
collideWithWall(hexagon) {
const vertices = hexagon.vertices;
for (let i = 0; i < vertices.length; i++) {
const p1 = vertices[i];
const p2 = vertices[(i + 1) % vertices.length];
if (this.lineCircle(p1.x, p1.y, p2.x, p2.y, this.x, this.y, this.radius)) {
const normal = {x: p2.y - p1.y, y: p1.x - p2.x};
const distance = Math.sqrt(normal.x * normal.x + normal.y * normal.y);
normal.x /= distance;
normal.y /= distance;
const dotProduct = this.vx * normal.x + this.vy * normal.y;
this.vx -= 2 * dotProduct * normal.x;
this.vy -= 2 * dotProduct * normal.y;
// Move the ball outside the wall to avoid sticking
this.x += this.vx;
this.y += this.vy;
return;
}
}
}
lineCircle(x1, y1, x2, y2, cx, cy, r) {
const lineLength = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
const dot = (((cx - x1) * (x2 - x1)) + ((cy - y1) * (y2 - y1))) / Math.pow(lineLength, 2);
const closestX = x1 + (dot * (x2 - x1));
const closestY = y1 + (dot * (y2 - y1));
if (this.distance(closestX, closestY, x1, y1) > lineLength || this.distance(closestX, closestY, x2, y2) > lineLength) {
return false;
}
const distance = this.distance(closestX, closestY, cx, cy);
return distance <= r;
}
distance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
}
// Hexagon class
class Hexagon {
constructor(centerX, centerY, radius) {
this.centerX = centerX;
this.centerY = centerY;
this.radius = radius;
this.rotation = 0;
this.vertices = this.calculateVertices();
}
calculateVertices() {
const vertices = [];
for (let i = 0; i < 6; i++) {
const angle = Math.PI / 3 * i + this.rotation;
vertices.push({
x: this.centerX + this.radius * Math.cos(angle),
y: this.centerY + this.radius * Math.sin(angle)
});
}
return vertices;
}
draw() {
ctx.beginPath();
for (let vertex of this.vertices) {
ctx.lineTo(vertex.x, vertex.y);
}
ctx.closePath();
ctx.strokeStyle = "black";
ctx.stroke();
}
update() {
this.rotation += 0.01;
this.vertices = this.calculateVertices();
}
}
const hexagon = new Hexagon(canvas.width / 2, canvas.height / 2, 200);
const balls = [];
const colors = ["red", "blue", "green", "yellow", "purple", "orange", "pink", "brown", "cyan", "magenta"];
for (let i = 0; i < 10; i++) {
const x = canvas.width / 2 + Math.random() * 100 - 50;
const y = canvas.height / 2 + Math.random() * 100 - 50;
balls.push(new Ball(x, y, 10, colors[i]));
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
hexagon.update();
hexagon.draw();
for (let ball of balls) {
ball.move();
ball.collideWithWall(hexagon);
ball.draw();
}
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>