LejobuildYT's picture
🐳 04/03 - 15:53 - bei games wo too expensive steht sollte auch der preis stehen, aber dann der kauf button nicht blau sein sondern ausgegraut, damit der spieler direkt weiß dass man dies noch nicht k
5e582f9 verified
// Computer Evolution Idle Game
class ComputerEvolution {
constructor() {
this.money = 50;
this.totalEarned = 0;
this.investors = 0;
this.soundEnabled = true;
this.lastSave = Date.now();
// Prestige system
this.prestigeMultiplier = 1;
this.totalPrestiges = 0;
this.prestigeThreshold = 10; // Minimum 10% investors to prestige
// Hardware
this.hardware = {
hdd: {
quantity: 1,
capacity: 12, // MB
used: 0,
baseCost: { quantity: 2.5, capacity: 1.9 },
costMultiplier: 1.5
},
cpu: {
cores: 1,
speed: 38.7, // MHz
used: 0,
baseCost: { cores: 50, speed: 23 },
costMultiplier: 1.6
},
ram: {
quantity: 1,
capacity: 31.3, // MB
used: 0,
baseCost: { quantity: 50, capacity: 23 },
costMultiplier: 1.5
},
motherboard: {
level: 1,
maxOS: 2,
baseCost: 11.5,
costMultiplier: 2.5
}
};
// OS Levels
this.osLevels = [
{ name: "Sixtem 1.0", multiplier: 1, reqMotherboard: 1 },
{ name: "Sixtem 2.0", multiplier: 1.5, reqMotherboard: 1 },
{ name: "Sixtem 3.0", multiplier: 2.5, reqMotherboard: 2 },
{ name: "Sixtem Pro", multiplier: 4, reqMotherboard: 3 },
{ name: "Sixtem Ultra", multiplier: 7, reqMotherboard: 4 },
{ name: "Quantum OS", multiplier: 12, reqMotherboard: 5 }
];
this.currentOS = 1; // Index
// Apps
this.availableApps = [
{ id: 'terminal', name: 'Terminal', icon: 'terminal', cost: 0, income: 0.5, storage: 2, ram: 1, color: 'bg-gray-800', installed: true },
{ id: 'loserar', name: 'Loserar', icon: 'file-archive', cost: 100, income: 2, storage: 4, ram: 2, color: 'bg-pink-500', installed: false },
{ id: 'landbrush', name: 'Landbrush', icon: 'paintbrush', cost: 500, income: 5, storage: 8, ram: 4, color: 'bg-purple-500', installed: false },
{ id: 'webnav', name: 'WebNav', icon: 'globe', cost: 2000, income: 12, storage: 16, ram: 8, color: 'bg-blue-500', installed: false },
{ id: 'mailer', name: 'Mailer', icon: 'mail', cost: 8000, income: 30, storage: 32, ram: 16, color: 'bg-yellow-500', installed: false },
{ id: 'musicbox', name: 'MusicBox', icon: 'music', cost: 25000, income: 80, storage: 64, ram: 32, color: 'bg-red-500', installed: false },
{ id: 'videocut', name: 'VideoCut', icon: 'video', cost: 100000, income: 200, storage: 128, ram: 64, color: 'bg-indigo-500', installed: false },
{ id: 'gamedev', name: 'GameDev', icon: 'gamepad-2', cost: 500000, income: 600, storage: 256, ram: 128, color: 'bg-green-500', installed: false }
];
this.installedApps = ['terminal'];
this.init();
}
init() {
this.loadGame();
this.updateUI();
this.renderApps();
// Game loop
setInterval(() => this.gameLoop(), 100);
setInterval(() => this.saveGame(), 30000); // Auto-save every 30s
// Update UI every 100ms for smooth progress bars
setInterval(() => this.updateProgressBars(), 100);
}
gameLoop() {
const income = this.calculateIncome();
this.money += income / 10; // Divide by 10 because we run 10 times per second
this.totalEarned += income / 10;
// Update investors based on total earned
this.investors = Math.min(100, (this.totalEarned / 1000000) * 100);
this.updateUI();
}
calculateIncome() {
let baseIncome = 1.6; // Base OS income
// Add app incomes
this.installedApps.forEach(appId => {
const app = this.availableApps.find(a => a.id === appId);
if (app) baseIncome += app.income;
});
// Apply CPU speed multiplier
const cpuMultiplier = 1 + (this.hardware.cpu.speed / 100);
// Apply OS multiplier
const osMultiplier = this.osLevels[this.currentOS].multiplier;
// Apply Prestige multiplier
// Formula: 1 + (investors% / 100) * 0.5 at 10%, up to 1 + (100/100) * 2 = 3x at 100%
// But we use the stored prestigeMultiplier which is calculated at prestige time
return baseIncome * cpuMultiplier * osMultiplier * this.prestigeMultiplier;
}
calculatePrestigeBoost() {
// Calculate potential boost based on current investors
// At 10%: 1.1x boost (10% increase)
// At 50%: 1.5x boost (50% increase)
// At 100%: 2.5x boost (150% increase)
if (this.investors < this.prestigeThreshold) return 0;
// Formula: 1 + (investors / 100) * 1.5
// 10% = 1.15x, 100% = 2.5x
const boost = 1 + (this.investors / 100) * 1.5;
return boost;
}
canPrestige() {
return this.investors >= this.prestigeThreshold;
}
prestige() {
if (!this.canPrestige()) {
this.showToast('Cannot Prestige', `You need at least ${this.prestigeThreshold}% investors!`);
return;
}
const boost = this.calculatePrestigeBoost();
const oldMultiplier = this.prestigeMultiplier;
this.prestigeMultiplier *= boost;
this.totalPrestiges++;
// Reset game progress
this.money = 50;
this.totalEarned = 0;
this.investors = 0;
// Reset hardware
this.hardware = {
hdd: {
quantity: 1,
capacity: 12,
used: 0,
baseCost: { quantity: 2.5, capacity: 1.9 },
costMultiplier: 1.5
},
cpu: {
cores: 1,
speed: 38.7,
used: 0,
baseCost: { cores: 50, speed: 23 },
costMultiplier: 1.6
},
ram: {
quantity: 1,
capacity: 31.3,
used: 0,
baseCost: { quantity: 50, capacity: 23 },
costMultiplier: 1.5
},
motherboard: {
level: 1,
maxOS: 2,
baseCost: 11.5,
costMultiplier: 2.5
}
};
// Reset OS
this.currentOS = 1;
// Reset apps
this.installedApps = ['terminal'];
this.availableApps.forEach(app => {
app.installed = app.id === 'terminal';
});
// Close modal if open
this.toggleSettings();
this.showToast('Prestige Complete!',
`Boost: ${boost.toFixed(2)}x\nTotal Multiplier: ${oldMultiplier.toFixed(2)}x → ${this.prestigeMultiplier.toFixed(2)}x`,
5000);
this.updateUI();
this.renderApps();
this.saveGame();
}
calculateUsage() {
let storageUsed = 0;
let ramUsed = 0;
let cpuUsed = 0;
this.installedApps.forEach(appId => {
const app = this.availableApps.find(a => a.id === appId);
if (app) {
storageUsed += app.storage;
ramUsed += app.ram;
cpuUsed += app.income; // Higher income apps use more CPU
}
});
return { storage: storageUsed, ram: ramUsed, cpu: cpuUsed };
}
formatMoney(amount) {
if (amount >= 1e12) return '$' + (amount / 1e12).toFixed(2) + 'T';
if (amount >= 1e9) return '$' + (amount / 1e9).toFixed(2) + 'B';
if (amount >= 1e6) return '$' + (amount / 1e6).toFixed(2) + 'M';
if (amount >= 1e3) return '$' + (amount / 1e3).toFixed(2) + 'K';
return '$' + amount.toFixed(2);
}
formatBytes(mb) {
if (mb >= 1024) return (mb / 1024).toFixed(2) + 'GB';
if (mb >= 1) return mb.toFixed(2) + 'MB';
return (mb * 1024).toFixed(0) + 'kB';
}
formatFreq(mhz) {
if (mhz >= 1000) return (mhz / 1000).toFixed(2) + 'GHz';
return mhz.toFixed(2) + 'MHz';
}
getUpgradeCost(component, type) {
const hw = this.hardware[component];
const currentLevel = hw[type];
return hw.baseCost[type] * Math.pow(hw.costMultiplier, currentLevel - 1);
}
getMotherboardCost() {
const mb = this.hardware.motherboard;
return mb.baseCost * Math.pow(mb.costMultiplier, mb.level - 1);
}
upgrade(component, type) {
const cost = this.getUpgradeCost(component, type);
if (this.money >= cost) {
this.money -= cost;
this.hardware[component][type]++;
this.updateUI();
this.showToast('Upgrade Complete', `${component.toUpperCase()} ${type} upgraded!`);
}
}
upgradeMotherboard() {
const cost = this.getMotherboardCost();
if (this.money >= cost) {
this.money -= cost;
this.hardware.motherboard.level++;
this.hardware.motherboard.maxOS = this.hardware.motherboard.level + 1;
this.checkOSUpgrade();
this.updateUI();
this.showToast('Motherboard Upgraded', 'You can now install better OS versions!');
}
}
checkOSUpgrade() {
// Auto-upgrade OS if possible
for (let i = this.osLevels.length - 1; i >= 0; i--) {
if (this.hardware.motherboard.level >= this.osLevels[i].reqMotherboard && i > this.currentOS) {
this.currentOS = i;
this.showToast('OS Upgraded', `Welcome to ${this.osLevels[i].name}!`);
break;
}
}
}
installApp(appId) {
const app = this.availableApps.find(a => a.id === appId);
if (!app || app.installed) return;
const usage = this.calculateUsage();
const maxStorage = this.hardware.hdd.capacity * this.hardware.hdd.quantity;
const maxRam = this.hardware.ram.capacity * this.hardware.ram.quantity;
if (usage.storage + app.storage > maxStorage) {
this.showToast('Error', 'Not enough storage space!');
return;
}
if (usage.ram + app.ram > maxRam) {
this.showToast('Error', 'Not enough RAM!');
return;
}
if (this.money < app.cost) {
this.showToast('Error', 'Not enough money!');
return;
}
this.money -= app.cost;
app.installed = true;
this.installedApps.push(appId);
this.renderApps();
this.updateUI();
this.closeAppStore();
this.showToast('App Installed', `${app.name} has been installed!`);
}
manualClick(event) {
const amount = 1 + (this.hardware.cpu.cores * 0.5);
this.money += amount;
this.totalEarned += amount;
// Visual feedback
const floatEl = document.createElement('div');
floatEl.className = 'fixed pointer-events-none text-green-600 font-bold text-xl money-animation z-50';
floatEl.textContent = '+' + this.formatMoney(amount);
floatEl.style.left = event.clientX + 'px';
floatEl.style.top = event.clientY + 'px';
document.body.appendChild(floatEl);
setTimeout(() => floatEl.remove(), 1000);
this.updateUI();
}
updateUI() {
// Header
document.getElementById('balance-display').textContent = this.formatMoney(this.money);
document.getElementById('income-display').textContent = this.formatMoney(this.calculateIncome());
document.getElementById('investors-display').textContent = this.investors.toFixed(1) + '%';
// Update prestige display
const prestigeDisplay = document.getElementById('prestige-display');
const prestigeBtn = document.getElementById('prestige-btn');
const currentMultiplierEl = document.getElementById('current-prestige-multiplier');
const totalPrestigesEl = document.getElementById('total-prestiges');
if (prestigeDisplay) {
prestigeDisplay.textContent = this.prestigeMultiplier.toFixed(2) + 'x';
}
if (currentMultiplierEl) {
currentMultiplierEl.textContent = this.prestigeMultiplier.toFixed(2) + 'x';
}
if (totalPrestigesEl) {
totalPrestigesEl.textContent = this.totalPrestiges;
}
// Update prestige button state
if (prestigeBtn) {
if (this.canPrestige()) {
const potentialBoost = this.calculatePrestigeBoost();
const potentialMultiplier = this.prestigeMultiplier * potentialBoost;
prestigeBtn.innerHTML = `
<div class="flex flex-col items-center">
<span class="font-bold">PRESTIGE NOW</span>
<span class="text-xs opacity-90">+${potentialBoost.toFixed(2)}x boost (${this.investors.toFixed(1)}% investors)</span>
<span class="text-xs opacity-75">New total: ${potentialMultiplier.toFixed(2)}x</span>
</div>
`;
prestigeBtn.classList.remove('opacity-50', 'cursor-not-allowed');
prestigeBtn.classList.add('animate-pulse');
} else {
prestigeBtn.innerHTML = `
<div class="flex flex-col items-center">
<span class="font-bold">PRESTIGE LOCKED</span>
<span class="text-xs opacity-75">Need ${this.prestigeThreshold}% investors (${(this.prestigeThreshold - this.investors).toFixed(1)}% more)</span>
</div>
`;
prestigeBtn.classList.add('opacity-50', 'cursor-not-allowed');
prestigeBtn.classList.remove('animate-pulse');
}
}
// HDD
const maxStorage = this.hardware.hdd.capacity * this.hardware.hdd.quantity;
const usage = this.calculateUsage();
const storagePercent = (usage.storage / maxStorage) * 100;
document.getElementById('hdd-quantity').textContent = this.hardware.hdd.quantity;
document.getElementById('hdd-capacity').textContent = this.formatBytes(this.hardware.hdd.capacity);
document.getElementById('hdd-usage-text').textContent = `${this.formatBytes(maxStorage - usage.storage)} free of ${this.formatBytes(maxStorage)}`;
document.getElementById('hdd-percent').textContent = storagePercent.toFixed(0) + '%';
document.getElementById('hdd-bar').style.width = storagePercent + '%';
document.getElementById('hdd-quantity-cost').textContent = this.formatMoney(this.getUpgradeCost('hdd', 'quantity'));
document.getElementById('hdd-capacity-cost').textContent = this.formatMoney(this.getUpgradeCost('hdd', 'capacity'));
// CPU
const maxCpu = this.hardware.cpu.speed * this.hardware.cpu.cores;
const cpuPercent = Math.min(100, (usage.cpu / maxCpu) * 100);
document.getElementById('cpu-cores').textContent = this.hardware.cpu.cores;
document.getElementById('cpu-speed').textContent = this.formatFreq(this.hardware.cpu.speed);
document.getElementById('cpu-usage-text').textContent = `${this.formatFreq(maxCpu - usage.cpu)} free of ${this.formatFreq(maxCpu)}`;
document.getElementById('cpu-percent').textContent = cpuPercent.toFixed(0) + '%';
document.getElementById('cpu-bar').style.width = cpuPercent + '%';
document.getElementById('cpu-cores-cost').textContent = this.formatMoney(this.getUpgradeCost('cpu', 'cores'));
document.getElementById('cpu-speed-cost').textContent = this.formatMoney(this.getUpgradeCost('cpu', 'speed'));
// RAM
const maxRam = this.hardware.ram.capacity * this.hardware.ram.quantity;
const ramPercent = (usage.ram / maxRam) * 100;
document.getElementById('ram-quantity').textContent = this.hardware.ram.quantity;
document.getElementById('ram-capacity').textContent = this.formatBytes(this.hardware.ram.capacity);
document.getElementById('ram-usage-text').textContent = `${this.formatBytes(maxRam - usage.ram)} free of ${this.formatBytes(maxRam)}`;
document.getElementById('ram-percent').textContent = ramPercent.toFixed(0) + '%';
document.getElementById('ram-bar').style.width = ramPercent + '%';
document.getElementById('ram-quantity-cost').textContent = this.formatMoney(this.getUpgradeCost('ram', 'quantity'));
document.getElementById('ram-capacity-cost').textContent = this.formatMoney(this.getUpgradeCost('ram', 'capacity'));
// Motherboard
document.getElementById('supported-os').textContent = this.osLevels[Math.min(this.osLevels.length - 1, this.hardware.motherboard.maxOS - 1)].name;
document.getElementById('motherboard-cost').textContent = this.formatMoney(this.getMotherboardCost());
// OS Panel
const os = this.osLevels[this.currentOS];
document.getElementById('os-name').textContent = os.name;
document.getElementById('os-income').textContent = this.formatMoney(this.calculateIncome()) + '/s';
document.getElementById('os-storage').textContent = this.formatBytes(usage.storage);
document.getElementById('os-cpu').textContent = this.formatFreq(usage.cpu);
document.getElementById('os-ram').textContent = this.formatBytes(usage.ram);
// Click value
document.getElementById('click-value').textContent = this.formatMoney(1 + (this.hardware.cpu.cores * 0.5));
// Update button states
this.updateButtonStates();
}
updateButtonStates() {
// Disable buttons if not enough money
const components = ['hdd', 'cpu', 'ram'];
const types = { hdd: ['quantity', 'capacity'], cpu: ['cores', 'speed'], ram: ['quantity', 'capacity'] };
components.forEach(comp => {
types[comp].forEach(type => {
const btn = document.getElementById(`btn-${comp}-${type}`);
if (btn) {
btn.disabled = this.money < this.getUpgradeCost(comp, type);
}
});
});
const mbBtn = document.getElementById('btn-motherboard');
if (mbBtn) mbBtn.disabled = this.money < this.getMotherboardCost();
}
updateProgressBars() {
// Smooth updates for progress bars are handled in updateUI
}
renderApps() {
const grid = document.getElementById('apps-grid');
grid.innerHTML = '';
this.installedApps.forEach(appId => {
const app = this.availableApps.find(a => a.id === appId);
if (app) {
const div = document.createElement('div');
div.className = `app-card ${app.color} rounded-lg p-3 text-white shadow-md cursor-pointer aspect-square flex flex-col items-center justify-center gap-2`;
div.innerHTML = `
<i data-lucide="${app.icon}" class="w-8 h-8"></i>
<span class="text-xs font-semibold text-center">${app.name}</span>
<span class="text-xs opacity-75">+${this.formatMoney(app.income)}/s</span>
`;
grid.appendChild(div);
}
});
lucide.createIcons();
}
openAppStore() {
const modal = document.getElementById('app-store-modal');
const content = document.getElementById('app-store-content');
content.innerHTML = '';
this.availableApps.filter(app => !app.installed).forEach(app => {
const div = document.createElement('div');
div.className = 'flex items-center justify-between p-4 border border-gray-200 rounded-lg mb-3 hover:bg-gray-50 transition';
const canAfford = this.money >= app.cost;
const usage = this.calculateUsage();
const maxStorage = this.hardware.hdd.capacity * this.hardware.hdd.quantity;
const maxRam = this.hardware.ram.capacity * this.hardware.ram.quantity;
const hasSpace = usage.storage + app.storage <= maxStorage && usage.ram + app.ram <= maxRam;
div.innerHTML = `
<div class="flex items-center gap-4">
<div class="${app.color} w-12 h-12 rounded-lg flex items-center justify-center text-white">
<i data-lucide="${app.icon}" class="w-6 h-6"></i>
</div>
<div>
<h4 class="font-bold text-gray-800">${app.name}</h4>
<p class="text-sm text-gray-600">Income: +${this.formatMoney(app.income)}/s</p>
<p class="text-xs text-gray-500">Uses: ${this.formatBytes(app.storage)} storage, ${this.formatBytes(app.ram)} RAM</p>
</div>
</div>
<button onclick="game.installApp('${app.id}')"
class="px-4 py-2 rounded font-semibold text-sm transition ${canAfford && hasSpace ? 'bg-blue-500 hover:bg-blue-600 text-white' : 'bg-gray-300 text-gray-500 cursor-not-allowed'}"
${!canAfford || !hasSpace ? 'disabled' : ''}>
${this.formatMoney(app.cost)}
</button>
`;
content.appendChild(div);
});
if (content.innerHTML === '') {
content.innerHTML = '<p class="text-center text-gray-500 py-8">All apps installed! Check back later for updates.</p>';
}
modal.classList.remove('hidden');
lucide.createIcons();
}
closeAppStore() {
document.getElementById('app-store-modal').classList.add('hidden');
}
toggleSettings() {
const modal = document.getElementById('settings-modal');
modal.classList.toggle('hidden');
}
toggleSound() {
this.soundEnabled = !this.soundEnabled;
document.getElementById('sound-text').textContent = this.soundEnabled ? 'Sound' : 'Muted';
document.getElementById('sound-btn').classList.toggle('bg-emerald-600');
document.getElementById('sound-btn').classList.toggle('bg-gray-600');
}
showInfo(component) {
const info = {
hdd: { title: 'Hard Drive', text: 'Stores your applications. Upgrade capacity to install more apps, or quantity for redundancy.' },
cpu: { title: 'Processor', text: 'Processes data. More cores and speed increases your income multiplier.' },
ram: { title: 'Memory', text: 'Required to run applications. Each app needs RAM to function.' },
motherboard: { title: 'Motherboard', text: 'Determines which OS versions you can support. Required for major upgrades.' }
};
if (info[component]) {
this.showToast(info[component].title, info[component].text, 5000);
}
}
showToast(title, text, duration = 3000) {
const toast = document.getElementById('info-toast');
document.getElementById('info-title').textContent = title;
document.getElementById('info-text').textContent = text;
toast.classList.remove('translate-y-20', 'opacity-0');
setTimeout(() => {
toast.classList.add('translate-y-20', 'opacity-0');
}, duration);
}
saveGame() {
const data = {
money: this.money,
totalEarned: this.totalEarned,
investors: this.investors,
hardware: this.hardware,
currentOS: this.currentOS,
installedApps: this.installedApps,
availableApps: this.availableApps.map(app => ({ id: app.id, installed: app.installed })),
prestigeMultiplier: this.prestigeMultiplier,
totalPrestiges: this.totalPrestiges
};
localStorage.setItem('computerEvolutionSave', JSON.stringify(data));
this.showToast('Game Saved', 'Your progress has been saved!');
}
loadGame() {
const saved = localStorage.getItem('computerEvolutionSave');
if (saved) {
try {
const data = JSON.parse(saved);
this.money = data.money || 50;
this.totalEarned = data.totalEarned || 0;
this.investors = data.investors || 0;
if (data.hardware) this.hardware = data.hardware;
if (data.currentOS) this.currentOS = data.currentOS;
if (data.installedApps) this.installedApps = data.installedApps;
if (data.availableApps) {
data.availableApps.forEach(savedApp => {
const app = this.availableApps.find(a => a.id === savedApp.id);
if (app) app.installed = savedApp.installed;
});
}
if (data.prestigeMultiplier) this.prestigeMultiplier = data.prestigeMultiplier;
if (data.totalPrestiges) this.totalPrestiges = data.totalPrestiges;
this.showToast('Game Loaded', 'Welcome back!');
} catch (e) {
console.error('Failed to load save:', e);
}
}
}
resetGame() {
if (confirm('Are you sure you want to reset all progress?')) {
localStorage.removeItem('computerEvolutionSave');
location.reload();
}
}
}
// Initialize game
const game = new ComputerEvolution();
// Prevent context menu on right click for game feel
document.addEventListener('contextmenu', e => e.preventDefault());