function animation1() {
const f = [],
i = [],
stars = [];
let t = 0;
class S {
constructor() {
this.s = 20;
this.x = m.random() * (c.width / 2 - 100) + 50;
this.y = m.random() * (c.height / 2 - 100) + 50;
this.a = m.random() * m.PI * 2;
this.c = `hsl(${m.random() * 360},100%,50%)`;
this.m = 2 + m.random() * 1;
this.ac = 0.1;
this.t = 0.06;
this.av = 0.05;
this.e = 50;
this.n = 20 + m.random() * 10;
this.z = 0.5;
this.b = 0.05;
this.vx = m.cos(this.a) * this.m;
this.vy = m.sin(this.a) * this.m;
this.p = [];
for (let j = 0; j < this.s; j++) {
this.p.push({
x: this.x - this.vx * j * 0.25,
y: this.y - this.vy * j * 0.25
});
}
this.g = null;
}
u(asteroids, spaceships) {
const energyDrain = this.b * m.pow(this.z, 2);
this.n -= energyDrain;
if (this.n < 0) this.n = 0;
this.z = 0.25 + (this.n / 100) * 0.75;
let target = null,
maxInfluence = -Infinity;
for let asteroid of asteroids {
const dx = asteroid.x - this.x;
const dy = asteroid.y - this.y;
const distance = m.hypot(dx, dy);
const influence = asteroid.n / distance;
if (influence > maxInfluence) {
maxInfluence = influence;
target = asteroid;
}
}
let targetAngle = this.a;
if (target) {
this.g = target;
targetAngle = m.atan2(target.y - this.y, target.x - this.x);
}
const boundaryAvoidanceAngle = this.ga();
if (boundaryAvoidanceAngle !== null) {
targetAngle = targetAngle * 0.2 + boundaryAvoidanceAngle * 0.8;
}
const alignmentAngle = this.aa(spaceships);
if (alignmentAngle !== null) {
targetAngle = targetAngle * 0.8 + alignmentAngle * 0.2;
}
let angularDifference = targetAngle - this.a;
angularDifference = ((angularDifference + m.PI) % (m*2) - m.PI);
this.a += angularDifference * this.t;
const targetVx = m.cos(this.a) * this.m * this.z;
const targetVy = m.sin(this.a) * this.m * this.z;
this.vx += (targetVx - this.vx) * this.ac;
this.vy += (targetVy - this.vy) * this.ac;
this.x += this.vx;
this.y += this.vy;
if (
this.x < 0 ||
this.x > c.width / 2 ||
this.y < 0 ||
this.y > c.height / 2
) {
this.n -= 10;
if (this.n < 0) this.n = 0;
this.x = m.max(0, m.min(this.x, c.width / 2));
this.y = m.max(0, m.min(this.y, c.height / 2));
}
for (let j = 0; j < this.s; j++) {
if (j === 0) {
this.p[j] = { x: this.x, y: this.y };
} else {
const previousPoint = this.p[j-1];
const currentPoint = this.p[j];
const dx = previousPoint.x - currentPoint.x;
const dy = previousPoint.y - currentPoint.y;
const distance = m.hypot(dx, dy);
const trailDistance = 10 * this.z;
if (distance > trailDistance) {
currentPoint.x += dx * 0.2;
currentPoint.y += dy * 0.2;
}
}
}
if (this.g) {
const dx = this.g.x - this.x;
const dy = this.g.y - this.y;
const distance = m.hypot(dx, dy);
if (distance < 15 * this.z) {
this.n += this.g.n;
if (this.n > 200) this.n = 200;
return this.g;
}
}
return null;
}
ga() {
let dx = 0,
dy = 0;
if (this.x < this.e) dx = 1;
else if (this.x > c.width / 2 - this.e) dx = -1;
if (this.y < this.e) dy = 1;
else if (this.y > c.height / 2 - this.e) dy = -1;
return dx !== 0 || dy !== 0 ? m.atan2(dy, dx) : null;
}
aa(spaceships) {
let dx = 0,
dy = 0;
for (let ship of spaceships) {
if (ship === this) continue;
const deltaX = this.x - ship.x;
const deltaY = this.y - ship.y;
const distance = m.hypot(deltaX, deltaY);
if (distance < 50) {
dx += deltaX / distance;
dy += deltaY / distance;
}
}
return dx !== 0 || dy !== 0 ? m.atan2(dy, dx) : null;
}
d() {
x.save();
x.translate(this.x, this.y);
x.rotate(this.a);
x.beginPath();
x.moveTo(30 * this.z, 0);
x.lineTo(-30 * this.z, 15 * this.z);
x.lineTo(-30 * this.z, -15 * this.z);
x.closePath();
x.fillStyle = this.c;
x.fill();
x.restore();
}
}
class A {
constructor() {
this.x = (m.random() * c.width) / 2;
this.y = (m.random() * c.height) / 2;
this.z = 3 + m.random() * 5;
this.vx = (m.random() - 0.5) * 2;
this.vy = (m.random() - 0.5) * 2;
this.c = `rgb(${100 + m.random() * 155},${100 + m.random() * 155},${100 + m.random() * 155})`;
this.n = this.z * 10;
}
u() {
this.x += this.vx;
this.y += this.vy;
if (this.x < 0 || this.x > c.width / 2) this.vx *= -1;
if (this.y < 0 || this.y > c.height / 2) this.vy *= -1;
}
d() {
x.save();
x.translate(this.x, this.y);
x.beginPath();
x.arc(0, 0, this.z, 0, 2 * m.PI);
x.fill();
x.restore();
}
}
class Star {
constructor() {
this.x = (m.random() * c.width) / 2;
this.y = (m.random() * c.height) / 2;
this.size = 0.5 + m.random() * 2;
this.color = `rgba(255, 255, 255, 0.7)`;
}
update() {
this.y += 0.5;
if (this.y > c.height / 2) {
this.y = 0;
this.x = m.random() * c.width;
}
}
draw() {
x.fillStyle = this.color;
x.beginPath();
x.arc(this.x, this.y, this.size, 0, 2 * m.PI);
x.fill();
}
}
function init() {
resizeCanvas();
for (let j = 0; j < 20; j++) {
f.push(new S());
}
for (let j = 0; j < 50; j++) {
i.push(new A());
}
for (let j = 0; j < 200; j++) {
stars.push(new Star());
}
}
function a() {
x.clearRect(0, 0, c.width, c.height);
stars.forEach((star) => {
star.update();
star.draw();
});
f.forEach((ship) => {
let g = ship.u(i, f);
if (g) {
let j = i.indexOf(g);
if (j > -1) i.splice(j, 1);
}
ship.d();
});
i.forEach((asteroid) => {
asteroid.u();
asteroid.d();
});
animationFrame = requestAnimationFrame(a());
}
init();
a();
}