157 lines
No EOL
4.9 KiB
JavaScript
157 lines
No EOL
4.9 KiB
JavaScript
const gameArea = document.querySelector('.game-area');
|
|
const dotCountDisplay = document.getElementById('dotCount');
|
|
const message = document.querySelector('.message');
|
|
|
|
let dots = [];
|
|
let lastMouseX = 0;
|
|
let lastMouseY = 0;
|
|
let lastMouseTime = 0;
|
|
let mouseVelocityX = 0;
|
|
let mouseVelocityY = 0;
|
|
|
|
class Dot {
|
|
constructor(x, y) {
|
|
this.element = document.createElement('div');
|
|
this.element.className = 'dot';
|
|
this.x = x;
|
|
this.y = y;
|
|
this.velocityX = (Math.random() - 0.5) * 200;
|
|
this.velocityY = (Math.random() - 0.5) * 200;
|
|
this.lastDuplication = Date.now();
|
|
this.acceleration = 0;
|
|
gameArea.appendChild(this.element);
|
|
this.updatePosition();
|
|
}
|
|
|
|
updatePosition() {
|
|
this.element.style.left = `${this.x}px`;
|
|
this.element.style.top = `${this.y}px`;
|
|
}
|
|
|
|
move() {
|
|
this.velocityX += (Math.random() - 0.5) * 20;
|
|
this.velocityY += (Math.random() - 0.5) * 20;
|
|
|
|
this.x += this.velocityX * 0.016;
|
|
this.y += this.velocityY * 0.016;
|
|
|
|
if (this.x < 0) {
|
|
this.x = window.innerWidth;
|
|
} else if (this.x > window.innerWidth) {
|
|
this.x = 0;
|
|
}
|
|
|
|
if (this.y < 0) {
|
|
this.y = window.innerHeight;
|
|
} else if (this.y > window.innerHeight) {
|
|
this.y = 0;
|
|
}
|
|
|
|
this.velocityX *= 0.98;
|
|
this.velocityY *= 0.98;
|
|
|
|
const currentSpeed = Math.sqrt(this.velocityX * this.velocityX + this.velocityY * this.velocityY);
|
|
if (currentSpeed < 100) {
|
|
const angle = Math.atan2(this.velocityY, this.velocityX);
|
|
this.velocityX = Math.cos(angle) * 100;
|
|
this.velocityY = Math.sin(angle) * 100;
|
|
}
|
|
|
|
if (currentSpeed > 400) {
|
|
const angle = Math.atan2(this.velocityY, this.velocityX);
|
|
this.velocityX = Math.cos(angle) * 400;
|
|
this.velocityY = Math.sin(angle) * 400;
|
|
}
|
|
|
|
this.updatePosition();
|
|
|
|
const now = Date.now();
|
|
if (now - this.lastDuplication > 3000 && Math.random() < 0.002) {
|
|
this.duplicate();
|
|
this.lastDuplication = now;
|
|
}
|
|
}
|
|
|
|
duplicate() {
|
|
if (dots.length < 8) {
|
|
const newDot = new Dot(this.x, this.y);
|
|
newDot.velocityX = this.velocityX * 1.2;
|
|
newDot.velocityY = this.velocityY * 1.2;
|
|
dots.push(newDot);
|
|
updateDotCount();
|
|
}
|
|
}
|
|
|
|
avoidMouse(mouseX, mouseY, mouseVelX, mouseVelY) {
|
|
const dx = this.x - mouseX;
|
|
const dy = this.y - mouseY;
|
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
if (distance < 300) {
|
|
const speed = 300;
|
|
const mouseSpeed = Math.sqrt(mouseVelX * mouseVelX + mouseVelY * mouseVelY);
|
|
|
|
const dotToMouseAngle = Math.atan2(dy, dx);
|
|
const mouseMovementAngle = Math.atan2(mouseVelY, mouseVelX);
|
|
const angleDiff = Math.abs(dotToMouseAngle - mouseMovementAngle);
|
|
|
|
const distanceFactor = Math.min(1, (300 - distance) / 300);
|
|
|
|
if (angleDiff < Math.PI / 2) {
|
|
const targetSpeed = speed + mouseSpeed * 800 * distanceFactor;
|
|
const currentSpeed = Math.sqrt(this.velocityX * this.velocityX + this.velocityY * this.velocityY);
|
|
const acceleration = Math.min(0.2, (targetSpeed - currentSpeed) / 1000);
|
|
|
|
this.velocityX = this.velocityX * (1 - acceleration) + Math.cos(dotToMouseAngle) * targetSpeed * acceleration;
|
|
this.velocityY = this.velocityY * (1 - acceleration) + Math.sin(dotToMouseAngle) * targetSpeed * acceleration;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateDotCount() {
|
|
dotCountDisplay.textContent = dots.length;
|
|
}
|
|
|
|
function initializeGame() {
|
|
const firstDot = new Dot(
|
|
Math.random() * window.innerWidth,
|
|
Math.random() * window.innerHeight
|
|
);
|
|
dots.push(firstDot);
|
|
updateDotCount();
|
|
}
|
|
|
|
function moveDot(event) {
|
|
const currentTime = Date.now();
|
|
const timeDiff = currentTime - lastMouseTime;
|
|
|
|
if (lastMouseTime !== 0) {
|
|
mouseVelocityX = (event.clientX - lastMouseX) / timeDiff;
|
|
mouseVelocityY = (event.clientY - lastMouseY) / timeDiff;
|
|
}
|
|
|
|
lastMouseX = event.clientX;
|
|
lastMouseY = event.clientY;
|
|
lastMouseTime = currentTime;
|
|
|
|
dots.forEach(dot => dot.avoidMouse(event.clientX, event.clientY, mouseVelocityX, mouseVelocityY));
|
|
}
|
|
|
|
function updateDots() {
|
|
dots.forEach(dot => dot.move());
|
|
requestAnimationFrame(updateDots);
|
|
}
|
|
|
|
gameArea.addEventListener('mousemove', moveDot);
|
|
|
|
initializeGame();
|
|
updateDots();
|
|
|
|
window.addEventListener('resize', () => {
|
|
dots.forEach(dot => {
|
|
dot.x = Math.min(dot.x, window.innerWidth);
|
|
dot.y = Math.min(dot.y, window.innerHeight);
|
|
dot.updatePosition();
|
|
});
|
|
});
|