Meteors have been updated to be smoother and better looking

This commit is contained in:
sageTheDM 2025-10-22 08:47:23 +02:00
commit 226f5282ea
2 changed files with 324 additions and 281 deletions

View file

@ -3,6 +3,32 @@ import Meteor from "./Meteor.js";
const starInstances = [];
const meteorInstances = [];
let lastTime = performance.now();
let isTabVisible = true;
let animationFrameId = null;
// Track tab visibility to prevent spawning when hidden
document.addEventListener("visibilitychange", () => {
isTabVisible = !document.hidden;
// If tab becomes visible after being hidden, clean up excess meteors
if (isTabVisible && meteorInstances.length > 3) {
// Remove excess meteors
const excess = meteorInstances.length - 3;
for (let i = 0; i < excess; i++) {
if (meteorInstances[i]) {
meteorInstances[i].remove();
}
}
meteorInstances.splice(0, excess);
}
// Resume animation loop if it stopped
if (isTabVisible && !animationFrameId) {
lastTime = performance.now();
animate();
}
});
function createStars() {
const stars = document.getElementById("stars");
@ -34,7 +60,12 @@ function injectStarCSS() {
}
function trySpawnMeteor() {
const spawnChance = 0.12;
// Only spawn if tab is visible and not too many meteors
if (!isTabVisible || meteorInstances.length >= 2) {
return;
}
const spawnChance = 0.15;
if (Math.random() < spawnChance) {
const stars = document.getElementById("stars");
const newMeteor = new Meteor(stars);
@ -42,40 +73,89 @@ function trySpawnMeteor() {
}
}
function animateStars() {
function animate() {
const currentTime = performance.now();
const deltaTime = currentTime - lastTime;
lastTime = currentTime;
// Cap deltaTime to prevent huge jumps when tab is hidden
const cappedDelta = Math.min(deltaTime, 100);
// Update stars with delta time
starInstances.forEach((star) => star.update());
// Update meteors and remove dead ones
for (let i = meteorInstances.length - 1; i >= 0; i--) {
if (!meteorInstances[i].update()) {
if (!meteorInstances[i].update(cappedDelta)) {
meteorInstances.splice(i, 1);
}
}
requestAnimationFrame(animateStars);
animationFrameId = requestAnimationFrame(animate);
}
function createMeteorBurst() {
for (let i = 0; i < 3; i++) {
// Only burst if tab is visible
if (!isTabVisible) return;
// Limit burst size
const burstSize = Math.min(2, 3 - meteorInstances.length);
for (let i = 0; i < burstSize; i++) {
setTimeout(() => {
const stars = document.getElementById("stars");
const newMeteor = new Meteor(stars);
meteorInstances.push(newMeteor);
}, i * 200);
if (isTabVisible && meteorInstances.length < 3) {
const stars = document.getElementById("stars");
const newMeteor = new Meteor(stars);
meteorInstances.push(newMeteor);
}
}, i * 300);
}
}
let spawnInterval = null;
let burstInterval = null;
function init() {
injectStarCSS();
createStars();
animateStars();
lastTime = performance.now();
animate();
setInterval(trySpawnMeteor, 2000);
setInterval(createMeteorBurst, 15000);
// Longer interval for spawning
spawnInterval = setInterval(() => {
if (isTabVisible) {
trySpawnMeteor();
}
}, 3000); // Every 3 seconds instead of 2
// Longer interval for bursts
burstInterval = setInterval(() => {
if (isTabVisible) {
createMeteorBurst();
}
}, 20000); // Every 20 seconds instead of 15
}
// Cleanup function
function cleanup() {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
}
if (spawnInterval) {
clearInterval(spawnInterval);
}
if (burstInterval) {
clearInterval(burstInterval);
}
}
// Handle page unload
window.addEventListener("beforeunload", cleanup);
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
export { cleanup };