xxxxxxxxxx
142
// Circle class
class Circle {
constructor(x, y, radius, speed) {
this.x = x;
this.y = y;
this.radius = radius;
this.speed = speed;
this.dx = random(-speed, speed);
this.dy = random(-speed, speed);
this.color = color(128);
}
update() {
this.x += this.dx;
this.y += this.dy;
// Check for boundary collision
if (this.x - this.radius < 0 || this.x + this.radius > width) {
this.dx *= -1;
}
if (this.y - this.radius < 0 || this.y + this.radius > height) {
this.dy *= -1;
}
}
display() {
fill(this.color);
ellipse(this.x, this.y, this.radius * 2, this.radius * 2);
}
checkCollision(other) {
const distance = dist(this.x, this.y, other.x, other.y);
const combinedRadius = this.radius + other.radius;
if (distance < combinedRadius) {
this.color = color(255);
other.color = color(255);
} else {
this.color = color(128);
other.color = color(128);
}
}
}
// Spatial subdivision grid
class Grid {
constructor(cellSize) {
this.cellSize = cellSize;
this.cols = Math.ceil(width / cellSize);
this.rows = Math.ceil(height / cellSize);
this.cells = new Array(this.cols * this.rows);
this.circles = [];
}
getIndex(col, row) {
if (col < 0 || row < 0 || col >= this.cols || row >= this.rows) {
return -1;
}
return col + row * this.cols;
}
addToCell(circle) {
const col = Math.floor(circle.x / this.cellSize);
const row = Math.floor(circle.y / this.cellSize);
const index = this.getIndex(col, row);
if (index !== -1) {
if (!this.cells[index]) {
this.cells[index] = [];
}
this.cells[index].push(circle);
}
}
update() {
// Clear the grid
for (let i = 0; i < this.cells.length; i++) {
if (this.cells[i]) {
this.cells[i].length = 0;
}
}
// Add circles to cells
for (const circle of this.circles) {
this.addToCell(circle);
}
// Update and check collisions
for (const circle of this.circles) {
circle.update();
const col = Math.floor(circle.x / this.cellSize);
const row = Math.floor(circle.y / this.cellSize);
// Check collisions with neighboring cells
for (let colOffset = -1; colOffset <= 1; colOffset++) {
for (let rowOffset = -1; rowOffset <= 1; rowOffset++) {
const neighborIndex = this.getIndex(col + colOffset, row + rowOffset);
if (neighborIndex !== -1 && this.cells[neighborIndex]) {
for (const other of this.cells[neighborIndex]) {
if (circle !== other) {
circle.checkCollision(other);
}
}
}
}
}
}
}
display() {
for (const circle of this.circles) {
circle.display();
}
}
}
let grid;
const numCircles = 1000;
const cellSize = 800;
function setup() {
createCanvas(800, 800);
grid = new Grid(cellSize);
// Create circles
for (let i = 0; i < numCircles; i++) {
const x = random(width);
const y = random(height);
const radius = random(10, 40);
const speed = random(1, 3);
const circle = new Circle(x, y, radius, speed);
grid.circles.push(circle);
}
}
function draw() {
background(0);
grid.update();
grid.display();
print(frameRate());
}