Changed around line 1
+ class CellSimulation {
+ constructor() {
+ this.canvas = document.getElementById('cellCanvas');
+ this.ctx = this.canvas.getContext('2d');
+ this.organelles = [];
+ this.speed = 1;
+ this.selectedOrganelle = 'all';
+
+ this.resizeCanvas();
+ this.initializeOrganelles();
+ this.setupEventListeners();
+ this.animate();
+ }
+
+ resizeCanvas() {
+ this.canvas.width = 800;
+ this.canvas.height = 600;
+ }
+
+ initializeOrganelles() {
+ // Nucleus
+ this.organelles.push({
+ type: 'nucleus',
+ x: this.canvas.width / 2,
+ y: this.canvas.height / 2,
+ radius: 60,
+ color: '#2ecc71',
+ dx: 0,
+ dy: 0
+ });
+
+ // Mitochondria
+ for (let i = 0; i < 8; i++) {
+ this.organelles.push({
+ type: 'mitochondria',
+ x: Math.random() * this.canvas.width,
+ y: Math.random() * this.canvas.height,
+ width: 40,
+ height: 20,
+ color: '#e74c3c',
+ dx: (Math.random() - 0.5) * 2,
+ dy: (Math.random() - 0.5) * 2
+ });
+ }
+
+ // Endoplasmic Reticulum
+ for (let i = 0; i < 3; i++) {
+ this.organelles.push({
+ type: 'er',
+ points: this.generateERPoints(),
+ color: '#9b59b6',
+ dx: (Math.random() - 0.5),
+ dy: (Math.random() - 0.5)
+ });
+ }
+ }
+
+ generateERPoints() {
+ const points = [];
+ let x = Math.random() * this.canvas.width;
+ let y = Math.random() * this.canvas.height;
+
+ for (let i = 0; i < 5; i++) {
+ points.push({
+ x: x + Math.random() * 100 - 50,
+ y: y + Math.random() * 100 - 50
+ });
+ }
+ return points;
+ }
+
+ setupEventListeners() {
+ document.getElementById('speedControl').addEventListener('input', (e) => {
+ this.speed = parseFloat(e.target.value);
+ });
+
+ document.getElementById('organelleSelect').addEventListener('change', (e) => {
+ this.selectedOrganelle = e.target.value;
+ });
+
+ document.getElementById('resetButton').addEventListener('click', () => {
+ this.initializeOrganelles();
+ });
+ }
+
+ drawOrganelle(organelle) {
+ const ctx = this.ctx;
+ ctx.beginPath();
+
+ if (organelle.type === 'nucleus') {
+ ctx.arc(organelle.x, organelle.y, organelle.radius, 0, Math.PI * 2);
+ ctx.fillStyle = organelle.color;
+ ctx.fill();
+ } else if (organelle.type === 'mitochondria') {
+ ctx.ellipse(organelle.x, organelle.y, organelle.width, organelle.height, 0, 0, Math.PI * 2);
+ ctx.fillStyle = organelle.color;
+ ctx.fill();
+ } else if (organelle.type === 'er') {
+ ctx.moveTo(organelle.points[0].x, organelle.points[0].y);
+ for (let i = 1; i < organelle.points.length; i++) {
+ ctx.lineTo(organelle.points[i].x, organelle.points[i].y);
+ }
+ ctx.strokeStyle = organelle.color;
+ ctx.lineWidth = 3;
+ ctx.stroke();
+ }
+ }
+
+ updateOrganelle(organelle) {
+ if (organelle.type === 'nucleus') {
+ // Nucleus stays relatively central
+ organelle.x += Math.sin(Date.now() / 1000) * 0.5 * this.speed;
+ organelle.y += Math.cos(Date.now() / 1000) * 0.5 * this.speed;
+ } else if (organelle.type === 'mitochondria') {
+ organelle.x += organelle.dx * this.speed;
+ organelle.y += organelle.dy * this.speed;
+
+ if (organelle.x < 0 || organelle.x > this.canvas.width) organelle.dx *= -1;
+ if (organelle.y < 0 || organelle.y > this.canvas.height) organelle.dy *= -1;
+ } else if (organelle.type === 'er') {
+ organelle.points.forEach(point => {
+ point.x += organelle.dx * this.speed;
+ point.y += organelle.dy * this.speed;
+ });
+
+ const bounds = this.getERBounds(organelle);
+ if (bounds.left < 0 || bounds.right > this.canvas.width) organelle.dx *= -1;
+ if (bounds.top < 0 || bounds.bottom > this.canvas.height) organelle.dy *= -1;
+ }
+ }
+
+ getERBounds(er) {
+ const xs = er.points.map(p => p.x);
+ const ys = er.points.map(p => p.y);
+ return {
+ left: Math.min(...xs),
+ right: Math.max(...xs),
+ top: Math.min(...ys),
+ bottom: Math.max(...ys)
+ };
+ }
+
+ animate() {
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+
+ this.organelles.forEach(organelle => {
+ if (this.selectedOrganelle === 'all' || this.selectedOrganelle === organelle.type) {
+ this.updateOrganelle(organelle);
+ this.drawOrganelle(organelle);
+ }
+ });
+
+ requestAnimationFrame(() => this.animate());
+ }
+ }
+
+ document.addEventListener('DOMContentLoaded', () => {
+ new CellSimulation();
+ });