modified: index.html

modified:   js/game.js
	modified:   js/ui.js
	modified:   style.css
This commit is contained in:
xbl
2026-03-23 20:47:11 +01:00
parent b37a8192e4
commit b8b2f93d17
4 changed files with 84 additions and 109 deletions

View File

@ -72,6 +72,7 @@ a1.7 1.7 0 0 0-1.5 1z"></path>
<span id="massRate"></span> <span id="massRate"></span>
</div> </div>
<div id="global-tooltip"></div>
<div id="upgrade-panel"> <div id="upgrade-panel">
<div class="menu-title">Upgrades</div> <div class="menu-title">Upgrades</div>
<div id="total-level" class="stat-line"></div> <div id="total-level" class="stat-line"></div>

View File

@ -125,6 +125,47 @@ var Game = (function() {
e.preventDefault(); e.preventDefault();
} }
}); });
// Global tooltip
var globalTooltip = document.getElementById('global-tooltip');
document.addEventListener('mouseover', function(e) {
var trigger = e.target.closest('[data-tooltip]');
if (trigger) {
globalTooltip.innerHTML = trigger.getAttribute('data-tooltip');
globalTooltip.style.display = 'block';
}
});
document.addEventListener('mouseout', function(e) {
if (e.target.closest('[data-tooltip]')) {
globalTooltip.style.display = 'none';
}
});
document.addEventListener('mousemove', function(e) {
if (globalTooltip.style.display === 'block') {
var x = e.clientX + 18;
var y = e.clientY + 20;
var tipW = globalTooltip.offsetWidth;
var tipH = globalTooltip.offsetHeight;
// Flip left if overflowing right edge
if (x + tipW > window.innerWidth) {
x = e.clientX - tipW - 10;
}
// Flip above if overflowing bottom edge
if (y + tipH > window.innerHeight) {
y = e.clientY - tipH - 10;
}
// Clamp to left/top edges as a fallback
if (x < 0) x = 0;
if (y < 0) y = 0;
globalTooltip.style.left = x + 'px';
globalTooltip.style.top = y + 'px';
}
});
animate(currentTime); animate(currentTime);
UI.update(state, CONFIG); UI.update(state, CONFIG);

105
js/ui.js
View File

@ -227,16 +227,7 @@ var UI = {
const bhMassText = this.formatMass(state.blackHoleTotalMass, { forceSolarMass: true }); const bhMassText = this.formatMass(state.blackHoleTotalMass, { forceSolarMass: true });
const consumedText = this.formatMass(state.totalMassConsumedEver); const consumedText = this.formatMass(state.totalMassConsumedEver);
this.elements.totalMass.innerHTML = ` this.elements.totalMass.innerHTML = '<span class="tooltip-trigger" data-tooltip="The mass of your black hole in solar masses.<br>1 Solar Mass (M☉) ≈ 1.989 × 10³⁰ kg.<br><br>Total mass absorbed:<br>' + consumedText + '">' + 'Black Hole Mass: ' + bhMassText + '</span>';
<span class="tooltip-trigger">
Black Hole Mass: ${bhMassText}
<span class="tooltip">
The mass of your black hole in solar masses.<br>
1 Solar Mass (M☉) ≈ 1.989 × 10³⁰ kg.<br><br>
Total mass absorbed:<br>
${consumedText}
</span>
`;
}, },
updateRateDisplay: function(state, config) { updateRateDisplay: function(state, config) {
@ -348,13 +339,7 @@ var UI = {
gameState.ktypeUpgradeLevel + gameState.ktypeUpgradeLevel +
gameState.gtypeUpgradeLevel; gameState.gtypeUpgradeLevel;
el.innerHTML = el.innerHTML = '<span class="tooltip-trigger" data-tooltip="Sum of all upgrades.">' + 'Total Level: ' + totalLevel + '</span>';
'<span class="tooltip-trigger">' +
'Total Level: ' + totalLevel +
'<span class="tooltip">' +
'Sum of all upgrades.<br>' +
'</span>' +
'</span>';
var starBonusEl = document.getElementById('star-bonus'); var starBonusEl = document.getElementById('star-bonus');
if (!starBonusEl) return; if (!starBonusEl) return;
@ -379,11 +364,7 @@ var UI = {
starTooltip += 'G-Type: +' + gBonus.toFixed(0) + '%'; starTooltip += 'G-Type: +' + gBonus.toFixed(0) + '%';
} }
starBonusEl.innerHTML = starBonusEl.innerHTML = '<span class="tooltip-trigger" data-tooltip="' + starTooltip.replace(/"/g, '&quot;') + '">' + '<br><span style="color:#FC6;">Star Bonus: +' + totalStarBonus + '%</span>' + '</span>';
'<span class="tooltip-trigger">' +
'<br><span style="color:#FC6;">Star Bonus: +' + totalStarBonus + '%</span>' +
'<span class="tooltip">' + starTooltip + '</span>' +
'</span>';
}, },
updateActiveObjects: function() { updateActiveObjects: function() {
@ -423,15 +404,9 @@ var UI = {
var tooltipText = 'Asteroids are rocky, airless bodies that range in size from tiny pebbles to hundreds of kilometers across. Some asteroids have moons or even binary companions.<br><br>Rate: ' + rate + '/sec<br>Bonus: ' + bonusPercent + '%'; var tooltipText = 'Asteroids are rocky, airless bodies that range in size from tiny pebbles to hundreds of kilometers across. Some asteroids have moons or even binary companions.<br><br>Rate: ' + rate + '/sec<br>Bonus: ' + bonusPercent + '%';
if (!gameState.cometUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks Comets at level 20</span>'; if (!gameState.cometUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks Comets at level 20</span>';
this.elements.asteroidLevel.innerHTML = '<span class="tooltip-trigger">Asteroids: Level ' + this.elements.asteroidLevel.innerHTML = '<span class="tooltip-trigger" data-tooltip="' + tooltipText.replace(/"/g, '&quot;') + '">Asteroids: Level ' + gameState.asteroidUpgradeLevel + '</span>';
gameState.asteroidUpgradeLevel + this.elements.asteroidUpgradeBtn.textContent = 'Upgrade (Cost: ' + this.formatMass(gameState.asteroidUpgradeCost) + ')';
'<span class="tooltip">' + tooltipText + '</span></span>'; this.elements.asteroidUpgradeBtn.disabled = gameState.totalMassConsumed < gameState.asteroidUpgradeCost;
this.elements.asteroidUpgradeBtn.textContent =
'Upgrade (Cost: ' + this.formatMass(gameState.asteroidUpgradeCost) + ')';
this.elements.asteroidUpgradeBtn.disabled =
gameState.totalMassConsumed < gameState.asteroidUpgradeCost;
}, },
updateCometUpgrade: function(gameState) { updateCometUpgrade: function(gameState) {
@ -440,15 +415,9 @@ var UI = {
var tooltipText = 'Comets are small icy bodies that typically release gas and dust, forming a glowing coma and often a tail. They are composed mainly of ice, rock, and organic compounds.<br><br>Rate: ' + rate + '/min<br>Bonus: ' + bonusPercent + '%'; var tooltipText = 'Comets are small icy bodies that typically release gas and dust, forming a glowing coma and often a tail. They are composed mainly of ice, rock, and organic compounds.<br><br>Rate: ' + rate + '/min<br>Bonus: ' + bonusPercent + '%';
if (!gameState.planetUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks Planets at level 15</span>'; if (!gameState.planetUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks Planets at level 15</span>';
this.elements.cometLevel.innerHTML = '<span class="tooltip-trigger">Comets: Level ' + this.elements.cometLevel.innerHTML = '<span class="tooltip-trigger" data-tooltip="' + tooltipText.replace(/"/g, '&quot;') + '">Comets: Level ' + gameState.cometUpgradeLevel + '</span>';
gameState.cometUpgradeLevel + this.elements.cometUpgradeBtn.textContent = 'Upgrade (Cost: ' + this.formatMass(gameState.cometUpgradeCost) + ')';
'<span class="tooltip">' + tooltipText + '</span></span>'; this.elements.cometUpgradeBtn.disabled = gameState.totalMassConsumed < gameState.cometUpgradeCost;
this.elements.cometUpgradeBtn.textContent =
'Upgrade (Cost: ' + this.formatMass(gameState.cometUpgradeCost) + ')';
this.elements.cometUpgradeBtn.disabled =
gameState.totalMassConsumed < gameState.cometUpgradeCost;
}, },
updatePlanetUpgrade: function(gameState) { updatePlanetUpgrade: function(gameState) {
@ -457,15 +426,9 @@ var UI = {
var tooltipText = 'Planets are roughly spherical accumulations of rock and metal, with solid surfaces and relatively thin atmospheres. Local examples include Mercury, Earth, and Pluto. They may vary greatly in size.<br><br>Rate: ' + rate + '/hour<br>Bonus: ' + bonusPercent + '%'; var tooltipText = 'Planets are roughly spherical accumulations of rock and metal, with solid surfaces and relatively thin atmospheres. Local examples include Mercury, Earth, and Pluto. They may vary greatly in size.<br><br>Rate: ' + rate + '/hour<br>Bonus: ' + bonusPercent + '%';
if (!gameState.giantUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks Giants at level 10</span>'; if (!gameState.giantUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks Giants at level 10</span>';
this.elements.planetLevel.innerHTML = '<span class="tooltip-trigger">Planets: Level ' + this.elements.planetLevel.innerHTML = '<span class="tooltip-trigger" data-tooltip="' + tooltipText.replace(/"/g, '&quot;') + '">Planets: Level ' + gameState.planetUpgradeLevel + '</span>';
gameState.planetUpgradeLevel + this.elements.planetUpgradeBtn.textContent = 'Upgrade (Cost: ' + this.formatMass(gameState.planetUpgradeCost) + ')';
'<span class="tooltip">' + tooltipText + '</span></span>'; this.elements.planetUpgradeBtn.disabled = gameState.totalMassConsumed < gameState.planetUpgradeCost;
this.elements.planetUpgradeBtn.textContent =
'Upgrade (Cost: ' + this.formatMass(gameState.planetUpgradeCost) + ')';
this.elements.planetUpgradeBtn.disabled =
gameState.totalMassConsumed < gameState.planetUpgradeCost;
}, },
updateGiantUpgrade: function(gameState) { updateGiantUpgrade: function(gameState) {
@ -474,15 +437,9 @@ var UI = {
var tooltipText = 'Gas giants are large planets made mostly of hydrogen and helium, with thick atmospheres and no solid surface.<br>Ice giants are similar but contain higher amounts of frozen materials like water, ammonia, and methane in their atmospheres.<br>Local examples include Jupiter and Neptune.<br><br>Rate: ' + rate + '/6hours<br>Bonus: ' + bonusPercent + '%'; var tooltipText = 'Gas giants are large planets made mostly of hydrogen and helium, with thick atmospheres and no solid surface.<br>Ice giants are similar but contain higher amounts of frozen materials like water, ammonia, and methane in their atmospheres.<br>Local examples include Jupiter and Neptune.<br><br>Rate: ' + rate + '/6hours<br>Bonus: ' + bonusPercent + '%';
if (!gameState.mtypeUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks M-Type at level 5</span>'; if (!gameState.mtypeUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks M-Type at level 5</span>';
this.elements.giantLevel.innerHTML = '<span class="tooltip-trigger">Giants: Level ' + this.elements.giantLevel.innerHTML = '<span class="tooltip-trigger" data-tooltip="' + tooltipText.replace(/"/g, '&quot;') + '">Giants: Level ' + gameState.giantUpgradeLevel + '</span>';
gameState.giantUpgradeLevel + this.elements.giantUpgradeBtn.textContent = 'Upgrade (Cost: ' + this.formatMass(gameState.giantUpgradeCost) + ')';
'<span class="tooltip">' + tooltipText + '</span></span>'; this.elements.giantUpgradeBtn.disabled = gameState.totalMassConsumed < gameState.giantUpgradeCost;
this.elements.giantUpgradeBtn.textContent =
'Upgrade (Cost: ' + this.formatMass(gameState.giantUpgradeCost) + ')';
this.elements.giantUpgradeBtn.disabled =
gameState.totalMassConsumed < gameState.giantUpgradeCost;
}, },
updateMtypeUpgrade: function(gameState) { updateMtypeUpgrade: function(gameState) {
@ -491,13 +448,9 @@ var UI = {
var tooltipText = 'M-types, also known as red dwarfs, are the smallest and coolest stars with masses ranging from about 0.08 to 0.45 M☉.<br>They are the most common star in the universe, making up roughly three quarters of all main-sequence stars, but are not easily visible due to their low luminosity.<br><br>Rate: ' + rate + '/day<br>Bonus: ' + bonusPercent + '%'; var tooltipText = 'M-types, also known as red dwarfs, are the smallest and coolest stars with masses ranging from about 0.08 to 0.45 M☉.<br>They are the most common star in the universe, making up roughly three quarters of all main-sequence stars, but are not easily visible due to their low luminosity.<br><br>Rate: ' + rate + '/day<br>Bonus: ' + bonusPercent + '%';
if (!gameState.ktypeUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks K-Type at level 5</span>'; if (!gameState.ktypeUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks K-Type at level 5</span>';
this.elements.mtypeLevel.innerHTML = '<span class="tooltip-trigger">M-Type: Level ' + this.elements.mtypeLevel.innerHTML = '<span class="tooltip-trigger" data-tooltip="' + tooltipText.replace(/"/g, '&quot;') + '">M-Type: Level ' + gameState.mtypeUpgradeLevel + '</span>';
gameState.mtypeUpgradeLevel + this.elements.mtypeUpgradeBtn.textContent = 'Upgrade (Cost: ' + this.formatMass(gameState.mtypeUpgradeCost) + ')';
'<span class="tooltip">' + tooltipText + '</span></span>'; this.elements.mtypeUpgradeBtn.disabled = gameState.totalMassConsumed < gameState.mtypeUpgradeCost;
this.elements.mtypeUpgradeBtn.textContent =
'Upgrade (Cost: ' + this.formatMass(gameState.mtypeUpgradeCost) + ')';
this.elements.mtypeUpgradeBtn.disabled =
gameState.totalMassConsumed < gameState.mtypeUpgradeCost;
}, },
updateKtypeUpgrade: function(gameState) { updateKtypeUpgrade: function(gameState) {
@ -506,27 +459,19 @@ var UI = {
var tooltipText = 'K-types, also known as orange dwarfs, are medium-sized stars that are cooler than the Sun, with masses ranging from about 0.45 to 0.8 M☉. They are known for their stability and long lifespans (20 to 70 billion years), making them potential candidates for supporting inhabited planets.<br><br>Rate: ' + rate + '/2days<br>Bonus: ' + bonusPercent + '%'; var tooltipText = 'K-types, also known as orange dwarfs, are medium-sized stars that are cooler than the Sun, with masses ranging from about 0.45 to 0.8 M☉. They are known for their stability and long lifespans (20 to 70 billion years), making them potential candidates for supporting inhabited planets.<br><br>Rate: ' + rate + '/2days<br>Bonus: ' + bonusPercent + '%';
if (!gameState.gtypeUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks G-Type at level 5</span>'; if (!gameState.gtypeUnlocked) tooltipText += '<br><span style="color:#0FF;">Unlocks G-Type at level 5</span>';
this.elements.ktypeLevel.innerHTML = '<span class="tooltip-trigger">K-Type: Level ' + this.elements.ktypeLevel.innerHTML = '<span class="tooltip-trigger" data-tooltip="' + tooltipText.replace(/"/g, '&quot;') + '">K-Type: Level ' + gameState.ktypeUpgradeLevel + '</span>';
gameState.ktypeUpgradeLevel + this.elements.ktypeUpgradeBtn.textContent = 'Upgrade (Cost: ' + this.formatMass(gameState.ktypeUpgradeCost) + ')';
'<span class="tooltip">' + tooltipText + '</span></span>'; this.elements.ktypeUpgradeBtn.disabled = gameState.totalMassConsumed < gameState.ktypeUpgradeCost;
this.elements.ktypeUpgradeBtn.textContent =
'Upgrade (Cost: ' + this.formatMass(gameState.ktypeUpgradeCost) + ')';
this.elements.ktypeUpgradeBtn.disabled =
gameState.totalMassConsumed < gameState.ktypeUpgradeCost;
}, },
updateGtypeUpgrade: function(gameState) { updateGtypeUpgrade: function(gameState) {
var rate = (CONFIG.BASE_GTYPE_SPAWN_INTERVAL / gameState.currentGtypeSpawnInterval).toFixed(2); var rate = (CONFIG.BASE_GTYPE_SPAWN_INTERVAL / gameState.currentGtypeSpawnInterval).toFixed(2);
var bonusPercent = (gameState.gtypeUpgradeLevel * CONFIG.UPGRADE_BONUS_PER_LEVEL_GTYPE * 100).toFixed(0); var bonusPercent = (gameState.gtypeUpgradeLevel * CONFIG.UPGRADE_BONUS_PER_LEVEL_GTYPE * 100).toFixed(0);
var tooltipText = 'G-Types, also known as yellow dwarfs, are medium-sized stars that are about the size of our Sun (~1 M☉). The term yellow dwarf is a misnomer, as most G-Types (including the Sun) are in fact white. These stars are stable and long-lived, making them strong candidates for hosting habitable planets.<br><br>Rate: ' + rate + '/3days<br>Bonus: ' + bonusPercent + '%'; var tooltipText = 'G-Types, also known as yellow dwarfs, are medium-sized stars that are about the size of our Sun (~1 M☉). The term yellow dwarf is a misnomer, as most G-Types (including the Sun) are in fact white. These stars are stable and long-lived, making them strong candidates for hosting habitable planets.<br><br>Rate: ' + rate + '/3days<br>Bonus: ' + bonusPercent + '%';
this.elements.gtypeLevel.innerHTML = '<span class="tooltip-trigger">G-Type: Level ' + this.elements.gtypeLevel.innerHTML = '<span class="tooltip-trigger" data-tooltip="' + tooltipText.replace(/"/g, '&quot;') + '">G-Type: Level ' + gameState.gtypeUpgradeLevel + '</span>';
gameState.gtypeUpgradeLevel + this.elements.gtypeUpgradeBtn.textContent = 'Upgrade (Cost: ' + this.formatMass(gameState.gtypeUpgradeCost) + ')';
'<span class="tooltip">' + tooltipText + '</span></span>'; this.elements.gtypeUpgradeBtn.disabled = gameState.totalMassConsumed < gameState.gtypeUpgradeCost;
this.elements.gtypeUpgradeBtn.textContent =
'Upgrade (Cost: ' + this.formatMass(gameState.gtypeUpgradeCost) + ')';
this.elements.gtypeUpgradeBtn.disabled =
gameState.totalMassConsumed < gameState.gtypeUpgradeCost;
}, },
formatMass: function(massKg, options = {}) { formatMass: function(massKg, options = {}) {

View File

@ -37,35 +37,6 @@ canvas {
line-height: 1.6; line-height: 1.6;
} }
.tooltip-trigger {
cursor: help;
pointer-events: auto;
border-bottom: 1px dotted rgba(255, 255, 255, 0.3);
position: relative;
}
.tooltip {
display: none;
position: absolute;
background: rgba(20, 20, 30, 0.69);
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.2);
padding: 8px 12px;
border-radius: 4px;
font-size: 11px;
color: rgba(255, 255, 255, 0.7);
width: 200px;
z-index: 1000;
line-height: 1.4;
left: 0;
top: 100%;
margin-top: 5px;
}
.tooltip-trigger:hover .tooltip {
display: block;
}
.rate-up { .rate-up {
color: rgba(100, 255, 100, 0.9); color: rgba(100, 255, 100, 0.9);
transition: color 0.5s ease; transition: color 0.5s ease;
@ -537,3 +508,20 @@ canvas {
outline: none; outline: none;
border-color: rgba(0, 255, 255, 0.42); border-color: rgba(0, 255, 255, 0.42);
} }
#global-tooltip {
position: fixed;
z-index: 9999;
background: rgba(20, 20, 30, 0.69);
border: 1px solid rgba(255, 255, 255, 0.25);
backdrop-filter: blur(5px);
color: rgba(255, 255, 255, 0.85);
font-size: 11px;
font-family: 'Courier New', monospace;
padding: 8px 10px;
border-radius: 4px;
max-width: 256px;
pointer-events: none;
display: none;
line-height: 1.5;
}