baue mir ein browser game was genau so ist wie das hier: https://www.kongregate.com/en/games/joao8991/computer-evolution
ea4d09b verified | class ComputerEvolution { | |
| constructor() { | |
| this.money = 0; | |
| this.totalMoney = 0; | |
| this.clickPower = 1; | |
| this.investors = 0; | |
| this.evolution = 0; | |
| this.evolutionProgress = 0; | |
| // Hardware stats | |
| this.cpu = { speed: 1, cores: 1, used: 0 }; | |
| this.ram = { size: 64, used: 0 }; // KB | |
| this.storage = { size: 10, used: 0 }; // MB | |
| // Apps | |
| this.apps = []; | |
| this.runningApps = []; | |
| // Configuration for each evolution stage | |
| this.stages = [ | |
| { name: "Vintage PC", os: "MS-DOS 1.0", icon: "monitor", color: "text-gray-400", multiplier: 1 }, | |
| { name: "Early GUI", os: "Windows 3.1", icon: "layout", color: "text-blue-400", multiplier: 5 }, | |
| { name: "Internet Era", os: "Windows 98", icon: "globe", color: "text-cyan-400", multiplier: 25 }, | |
| { name: "Modern PC", os: "Windows XP", icon: "computer", color: "text-green-400", multiplier: 100 }, | |
| { name: "Multi-Core", os: "Windows 7", icon: "layers", color: "text-purple-400", multiplier: 500 }, | |
| { name: "Future Tech", os: "Quantum OS", icon: "cpu", color: "text-pink-400", multiplier: 2500 } | |
| ]; | |
| this.availableApps = [ | |
| { id: 1, name: "Calculator", cost: 10, income: 0.5, cpu: 0.1, ram: 4, storage: 0.1, unlock: 0 }, | |
| { id: 2, name: "Text Editor", cost: 50, income: 2, cpu: 0.2, ram: 8, storage: 0.5, unlock: 0 }, | |
| { id: 3, name: "File Manager", cost: 200, income: 5, cpu: 0.3, ram: 12, storage: 1, unlock: 0 }, | |
| { id: 4, name: "Paint Program", cost: 500, income: 12, cpu: 0.5, ram: 32, storage: 2, unlock: 0 }, | |
| { id: 5, name: "Music Player", cost: 1000, income: 25, cpu: 0.4, ram: 16, storage: 5, unlock: 1 }, | |
| { id: 6, name: "Web Browser", cost: 2500, income: 60, cpu: 1.2, ram: 64, storage: 10, unlock: 1 }, | |
| { id: 7, name: "Email Client", cost: 5000, income: 120, cpu: 0.8, ram: 48, storage: 5, unlock: 1 }, | |
| { id: 8, name: "Video Player", cost: 10000, income: 250, cpu: 2.0, ram: 128, storage: 50, unlock: 2 }, | |
| { id: 9, name: "IDE", cost: 25000, income: 600, cpu: 3.0, ram: 256, storage: 100, unlock: 2 }, | |
| { id: 10, name: "Database", cost: 50000, income: 1200, cpu: 2.5, ram: 512, storage: 200, unlock: 2 }, | |
| { id: 11, name: "3D Renderer", cost: 100000, income: 2500, cpu: 5.0, ram: 1024, storage: 500, unlock: 3 }, | |
| { id: 12, name: "AI Assistant", cost: 250000, income: 6000, cpu: 8.0, ram: 2048, storage: 1000, unlock: 3 }, | |
| { id: 13, name: "VR Environment", cost: 500000, income: 15000, cpu: 15.0, ram: 4096, storage: 2000, unlock: 4 }, | |
| { id: 14, name: "Neural Network", cost: 1000000, income: 50000, cpu: 32.0, ram: 8192, storage: 5000, unlock: 4 } | |
| ]; | |
| this.hardwareUpgrades = [ | |
| { id: 'cpu', name: 'Upgrade CPU', type: 'cpu', cost: 100, multiplier: 1.5 }, | |
| { id: 'ram', name: 'Upgrade RAM', type: 'ram', cost: 150, multiplier: 2 }, | |
| { id: 'storage', name: 'Upgrade Storage', type: 'storage', cost: 80, multiplier: 2 } | |
| ]; | |
| this.init(); | |
| } | |
| init() { | |
| this.load(); | |
| this.setupUI(); | |
| this.startGameLoop(); | |
| this.updateUI(); | |
| } | |
| setupUI() { | |
| this.renderAppStore(); | |
| this.renderHardware(); | |
| } | |
| click() { | |
| const amount = this.clickPower * this.getInvestorMultiplier() * this.getStageMultiplier(); | |
| this.money += amount; | |
| this.totalMoney += amount; | |
| this.evolutionProgress += amount / 100; | |
| // Visual feedback | |
| this.createFloatingText(amount); | |
| this.animateComputer(); | |
| this.checkEvolution(); | |
| this.updateUI(); | |
| } | |
| createFloatingText(amount) { | |
| const btn = document.getElementById('computerBtn'); | |
| const rect = btn.getBoundingClientRect(); | |
| const el = document.createElement('div'); | |
| el.className = 'fixed text-green-400 font-bold text-lg floating-text pointer-events-none z-50'; | |
| el.style.left = rect.left + rect.width/2 + (Math.random() * 40 - 20) + 'px'; | |
| el.style.top = rect.top + 'px'; | |
| el.textContent = '+' + this.formatMoney(amount); | |
| document.body.appendChild(el); | |
| setTimeout(() => el.remove(), 1000); | |
| } | |
| animateComputer() { | |
| const btn = document.getElementById('computerBtn'); | |
| btn.classList.add('click-effect'); | |
| setTimeout(() => btn.classList.remove('click-effect'), 200); | |
| } | |
| buyApp(appId) { | |
| const app = this.availableApps.find(a => a.id === appId); | |
| if (!app || this.apps.includes(appId)) return; | |
| if (this.money >= app.cost) { | |
| this.money -= app.cost; | |
| this.apps.push(appId); | |
| this.installApp(appId); | |
| this.renderAppStore(); | |
| this.updateUI(); | |
| } | |
| } | |
| installApp(appId) { | |
| const app = this.availableApps.find(a => a.id === appId); | |
| if (!app) return; | |
| // Check if we can run it | |
| if (this.cpu.used + app.cpu > this.cpu.speed * this.cpu.cores) return; | |
| if (this.ram.used + app.ram > this.ram.size) return; | |
| if (this.storage.used + app.storage > this.storage.size) return; | |
| this.runningApps.push({ | |
| ...app, | |
| progress: 0, | |
| instance: 1 | |
| }); | |
| this.cpu.used += app.cpu; | |
| this.ram.used += app.ram; | |
| this.storage.used += app.storage; | |
| this.renderRunningApps(); | |
| this.updateUI(); | |
| } | |
| uninstallApp(index) { | |
| const app = this.runningApps[index]; | |
| if (!app) return; | |
| this.cpu.used -= app.cpu * app.instance; | |
| this.ram.used -= app.ram * app.instance; | |
| this.storage.used -= app.storage * app.instance; | |
| this.runningApps.splice(index, 1); | |
| this.renderRunningApps(); | |
| this.updateUI(); | |
| } | |
| upgradeHardware(type) { | |
| const upgrade = this.hardwareUpgrades.find(h => h.type === type); | |
| if (!upgrade) return; | |
| const cost = Math.floor(upgrade.cost * Math.pow(1.5, this.getUpgradeLevel(type))); | |
| if (this.money >= cost) { | |
| this.money -= cost; | |
| switch(type) { | |
| case 'cpu': | |
| this.cpu.speed = Math.floor(this.cpu.speed * 1.5); | |
| break; | |
| case 'ram': | |
| this.ram.size = Math.floor(this.ram.size * upgrade.multiplier); | |
| break; | |
| case 'storage': | |
| this.storage.size = Math.floor(this.storage.size * upgrade.multiplier); | |
| break; | |
| } | |
| this.renderHardware(); | |
| this.updateUI(); | |
| } | |
| } | |
| getUpgradeLevel(type) { | |
| // Simplified: calculate based on current stats | |
| switch(type) { | |
| case 'cpu': return Math.log2(this.cpu.speed); | |
| case 'ram': return Math.log2(this.ram.size / 64); | |
| case 'storage': return Math.log2(this.storage.size / 10); | |
| } | |
| return 0; | |
| } | |
| evolve() { | |
| if (this.evolutionProgress >= 100 && this.evolution < this.stages.length - 1) { | |
| this.evolution++; | |
| this.investors++; | |
| this.evolutionProgress = 0; | |
| // Reset apps but keep money multiplier | |
| this.runningApps = []; | |
| this.apps = []; | |
| this.cpu.used = 0; | |
| this.ram.used = 0; | |
| this.storage.used = 0; | |
| // Scale hardware for new era | |
| this.cpu.speed *= 2; | |
| this.ram.size *= 4; | |
| this.storage.size *= 4; | |
| this.showToast(`Evolved to ${this.stages[this.evolution].os}!`); | |
| this.renderRunningApps(); | |
| this.renderAppStore(); | |
| this.updateUI(); | |
| } | |
| } | |
| checkEvolution() { | |
| if (this.evolutionProgress >= 100 && this.evolution < this.stages.length - 1) { | |
| document.getElementById('evolutionPanel').style.display = 'block'; | |
| document.getElementById('nextEvolution').textContent = this.stages[this.evolution + 1].os; | |
| } | |
| } | |
| getInvestorMultiplier() { | |
| return 1 + (this.investors * 0.1); | |
| } | |
| getStageMultiplier() { | |
| return this.stages[this.evolution].multiplier; | |
| } | |
| getIncome() { | |
| let income = 0; | |
| this.runningApps.forEach(app => { | |
| const efficiency = this.getEfficiency(); | |
| income += app.income * app.instance * efficiency * this.getInvestorMultiplier() * this.getStageMultiplier(); | |
| }); | |
| return income; | |
| } | |
| getEfficiency() { | |
| const cpuFree = 1 - (this.cpu.used / (this.cpu.speed * this.cpu.cores)); | |
| const ramFree = 1 - (this.ram.used / this.ram.size); | |
| return Math.max(0.1, Math.min(1, (cpuFree + ramFree) / 2)); | |
| } | |
| startGameLoop() { | |
| setInterval(() => { | |
| const income = this.getIncome(); | |
| this.money += income / 10; // Update 10 times per second | |
| this.totalMoney += income / 10; | |
| this.evolutionProgress += (income / 10) / 100; | |
| this.checkEvolution(); | |
| this.updateUI(); | |
| }, 100); | |
| // Auto-save every 30 seconds | |
| setInterval(() => this.save(), 30000); | |
| } | |
| updateUI() { | |
| // Money | |
| document.getElementById('moneyDisplay').textContent = '$' + this.formatMoney(this.money); | |
| document.getElementById('perSecond').textContent = '$' + this.formatMoney(this.getIncome()) + '/sec'; | |
| // Resources | |
| const cpuTotal = this.cpu.speed * this.cpu.cores; | |
| document.getElementById('cpuText').textContent = `${this.cpu.used.toFixed(1)} / ${cpuTotal} MHz`; | |
| document.getElementById('cpuBar').style.width = (this.cpu.used / cpuTotal * 100) + '%'; | |
| document.getElementById('ramText').textContent = `${this.ram.used} / ${this.ram.size} KB`; | |
| document.getElementById('ramBar').style.width = (this.ram.used / this.ram.size * 100) + '%'; | |
| document.getElementById('storageText').textContent = `${this.storage.used.toFixed(1)} / ${this.storage.size} MB`; | |
| document.getElementById('storageBar').style.width = (this.storage.used / this.storage.size * 100) + '%'; | |
| // Evolution | |
| const stage = this.stages[this.evolution]; | |
| document.getElementById('evolutionStage').textContent = `Stage ${this.evolution + 1}: ${stage.name}`; | |
| document.getElementById('osName').textContent = stage.os; | |
| document.getElementById('computerIcon').setAttribute('class', `w-24 h-24 ${stage.color} group-hover:text-opacity-80 transition-colors`); | |
| const evoPercent = Math.min(100, this.evolutionProgress); | |
| document.getElementById('evolutionBar').style.width = evoPercent + '%'; | |
| document.getElementById('evolutionPercent').textContent = evoPercent.toFixed(1) + '%'; | |
| // Investors | |
| document.getElementById('investorCount').textContent = this.investors; | |
| document.getElementById('investorBonus').textContent = '+' + (this.investors * 10) + '%'; | |
| // App count | |
| document.getElementById('appCount').textContent = `${this.runningApps.length}/${Math.floor(this.evolution + 3)}`; | |
| // Update hardware costs | |
| this.renderHardware(); | |
| } | |
| renderAppStore() { | |
| const container = document.getElementById('appStore'); | |
| container.innerHTML = ''; | |
| this.availableApps.forEach(app => { | |
| if (app.unlock > this.evolution) return; | |
| if (this.apps.includes(app.id)) return; | |
| const canAfford = this.money >= app.cost; | |
| const div = document.createElement('div'); | |
| div.className = `app-card p-4 rounded-xl bg-gray-800/50 border border-gray-700 ${canAfford ? 'cursor-pointer hover:bg-gray-700/50' : 'opacity-50 cursor-not-allowed'}`; | |
| div.innerHTML = ` | |
| <div class="flex justify-between items-start mb-2"> | |
| <div> | |
| <div class="font-bold text-sm">${app.name}</div> | |
| <div class="text-xs text-gray-400">+$${this.formatMoney(app.income)}/sec</div> | |
| </div> | |
| <div class="text-right"> | |
| <div class="text-sm font-bold ${canAfford ? 'text-green-400' : 'text-red-400'}">$${this.formatMoney(app.cost)}</div> | |
| </div> | |
| </div> | |
| <div class="flex gap-3 text-xs text-gray-500 mt-2"> | |
| <span class="flex items-center gap-1"><i data-lucide="cpu" class="w-3 h-3"></i> ${app.cpu}MHz</span> | |
| <span class="flex items-center gap-1"><i data-lucide="memory-stick" class="w-3 h-3"></i> ${app.ram}KB</span> | |
| <span class="flex items-center gap-1"><i data-lucide="hard-drive" class="w-3 h-3"></i> ${app.storage}MB</span> | |
| </div> | |
| `; | |
| if (canAfford) { | |
| div.onclick = () => this.buyApp(app.id); | |
| } | |
| container.appendChild(div); | |
| }); | |
| lucide.createIcons(); | |
| } | |
| renderRunningApps() { | |
| const container = document.getElementById('runningApps'); | |
| if (this.runningApps.length === 0) { | |
| container.innerHTML = ` | |
| <div class="text-center text-gray-500 py-12"> | |
| <i data-lucide="app-window" class="w-12 h-12 mx-auto mb-3 opacity-50"></i> | |
| <p>No apps running</p> | |
| <p class="text-sm mt-2">Install apps from the store</p> | |
| </div> | |
| `; | |
| lucide.createIcons(); | |
| return; | |
| } | |
| container.innerHTML = ''; | |
| this.runningApps.forEach((app, index) => { | |
| const efficiency = this.getEfficiency() * 100; | |
| const div = document.createElement('div'); | |
| div.className = 'p-4 rounded-xl bg-gray-800/80 border border-gray-700 relative overflow-hidden'; | |
| div.innerHTML = ` | |
| <div class="flex justify-between items-center mb-2 relative z-10"> | |
| <div class="flex items-center gap-2"> | |
| <i data-lucide="play-circle" class="w-4 h-4 text-green-400"></i> | |
| <span class="font-bold text-sm">${app.name}</span> | |
| <span class="text-xs text-gray-400">x${app.instance}</span> | |
| </div> | |
| <button onclick="game.uninstallApp(${index})" class="text-red-400 hover:text-red-300"> | |
| <i data-lucide="x" class="w-4 h-4"></i> | |
| </button> | |
| </div> | |
| <div class="text-xs text-green-400 mb-2 relative z-10">+$${this.formatMoney(app.income * app.instance * this.getInvestorMultiplier() * this.getStageMultiplier())}/sec</div> | |
| <div class="h-1 bg-gray-700 rounded-full overflow-hidden relative z-10"> | |
| <div class="h-full bg-green-500 progress-bar" style="width: ${efficiency}%"></div> | |
| </div> | |
| <div class="text-xs text-gray-500 mt-1 relative z-10">Efficiency: ${efficiency.toFixed(0)}%</div> | |
| `; | |
| container.appendChild(div); | |
| }); | |
| lucide.createIcons(); | |
| } | |
| renderHardware() { | |
| const container = document.getElementById('hardwareList'); | |
| container.innerHTML = ''; | |
| this.hardwareUpgrades.forEach(hw => { | |
| const level = this.getUpgradeLevel(hw.type); | |
| const cost = Math.floor(hw.cost * Math.pow(1.5, level)); | |
| const canAfford = this.money >= cost; | |
| const div = document.createElement('button'); | |
| div.className = `w-full p-3 rounded-lg bg-gray-800/50 border ${canAfford ? 'border-blue-500/30 hover:bg-gray-700/50' : 'border-gray-700 opacity-50'} transition flex justify-between items-center`; | |
| div.onclick = () => this.upgradeHardware(hw.type); | |
| let current = ''; | |
| if (hw.type === 'cpu') current = `${this.cpu.speed} MHz`; | |
| if (hw.type === 'ram') current = `${this.ram.size} KB`; | |
| if (hw.type === 'storage') current = `${this.storage.size} MB`; | |
| div.innerHTML = ` | |
| <div class="text-left"> | |
| <div class="text-sm font-bold">${hw.name}</div> | |
| <div class="text-xs text-gray-400">Current: ${current}</div> | |
| </div> | |
| <div class="text-right"> | |
| <div class="text-sm font-bold ${canAfford ? 'text-green-400' : 'text-red-400'}">$${this.formatMoney(cost)}</div> | |
| <div class="text-xs text-gray-500">Lvl ${Math.floor(level)}</div> | |
| </div> | |
| `; | |
| container.appendChild(div); | |
| }); | |
| } | |
| formatMoney(num) { | |
| if (num >= 1e15) return (num / 1e15).toFixed(2) + 'Q'; | |
| if (num >= 1e12) return (num / 1e12).toFixed(2) + 'T'; | |
| if (num >= 1e9) return (num / 1e9).toFixed(2) + 'B'; | |
| if (num >= 1e6) return (num / 1e6).toFixed(2) + 'M'; | |
| if (num >= 1e3) return (num / 1e3).toFixed(2) + 'K'; | |
| return Math.floor(num).toString(); | |
| } | |
| showToast(text) { | |
| const toast = document.getElementById('toast'); | |
| document.getElementById('toastText').textContent = text; | |
| toast.classList.remove('translate-x-full'); | |
| setTimeout(() => toast.classList.add('translate-x-full'), 3000); | |
| } | |
| save() { | |
| const data = { | |
| money: this.money, | |
| totalMoney: this.totalMoney, | |
| investors: this.investors, | |
| evolution: this.evolution, | |
| evolutionProgress: this.evolutionProgress, | |
| cpu: this.cpu, | |
| ram: this.ram, | |
| storage: this.storage, | |
| apps: this.apps, | |
| runningApps: this.runningApps | |
| }; | |
| localStorage.setItem('computerEvolutionSave', JSON.stringify(data)); | |
| console.log('Game saved!'); | |
| } | |
| load() { | |
| const saved = localStorage.getItem('computerEvolutionSave'); | |
| if (saved) { | |
| try { | |
| const data = JSON.parse(saved); | |
| this.money = data.money || 0; | |
| this.totalMoney = data.totalMoney || 0; | |
| this.investors = data.investors || 0; | |
| this.evolution = data.evolution || 0; | |
| this.evolutionProgress = data.evolutionProgress || 0; | |
| this.cpu = data.cpu || { speed: 1, cores: 1, used: 0 }; | |
| this.ram = data.ram || { size: 64, used: 0 }; | |
| this.storage = data.storage || { size: 10, used: 0 }; | |
| this.apps = data.apps || []; | |
| this.runningApps = data.runningApps || []; | |
| } catch(e) { | |
| console.error('Failed to load save:', e); | |
| } | |
| } | |
| } | |
| reset() { | |
| if (confirm('Are you sure you want to reset all progress?')) { | |
| localStorage.removeItem('computerEvolutionSave'); | |
| location.reload(); | |
| } | |
| } | |
| } | |
| const game = new ComputerEvolution(); |