Compare commits
1 Commits
feat/progr
...
feat/combo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe76150325 |
62
game.js
62
game.js
@@ -107,6 +107,11 @@ const G = {
|
||||
lastEventAt: 0,
|
||||
eventCooldown: 0,
|
||||
|
||||
// Combo system
|
||||
comboCount: 0,
|
||||
comboTimer: 0,
|
||||
comboDecay: 2.0, // seconds before combo resets
|
||||
|
||||
// Time tracking
|
||||
playTime: 0,
|
||||
startTime: 0
|
||||
@@ -952,6 +957,15 @@ function tick() {
|
||||
|
||||
G.tick += dt;
|
||||
|
||||
// Combo decay
|
||||
if (G.comboCount > 0) {
|
||||
G.comboTimer -= dt;
|
||||
if (G.comboTimer <= 0) {
|
||||
G.comboCount = 0;
|
||||
G.comboTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check milestones
|
||||
checkMilestones();
|
||||
|
||||
@@ -1212,16 +1226,46 @@ function resolveAlignment(accept) {
|
||||
// === ACTIONS ===
|
||||
function writeCode() {
|
||||
const base = 1;
|
||||
const bonus = Math.floor(G.buildings.autocoder * 0.5);
|
||||
const amount = (base + bonus) * G.codeBoost;
|
||||
const autocoderBonus = Math.floor(G.buildings.autocoder * 0.5);
|
||||
const phaseBonus = Math.max(0, (G.phase - 1)) * 2;
|
||||
// Combo: each consecutive click within 2s adds 0.2x multiplier, max 5x
|
||||
G.comboCount++;
|
||||
G.comboTimer = G.comboDecay;
|
||||
const comboMult = Math.min(5, 1 + G.comboCount * 0.2);
|
||||
const amount = (base + autocoderBonus + phaseBonus) * G.codeBoost * comboMult;
|
||||
G.code += amount;
|
||||
G.totalCode += amount;
|
||||
G.totalClicks++;
|
||||
// Visual flash
|
||||
const btn = document.querySelector('.main-btn');
|
||||
if (btn) {
|
||||
btn.style.boxShadow = '0 0 30px rgba(74,158,255,0.6)';
|
||||
btn.style.transform = 'scale(0.96)';
|
||||
setTimeout(() => { btn.style.boxShadow = ''; btn.style.transform = ''; }, 100);
|
||||
}
|
||||
// Float a number at the click position
|
||||
showClickNumber(amount, comboMult);
|
||||
updateRates();
|
||||
checkMilestones();
|
||||
render();
|
||||
}
|
||||
|
||||
function showClickNumber(amount, comboMult) {
|
||||
const btn = document.querySelector('.main-btn');
|
||||
if (!btn) return;
|
||||
const rect = btn.getBoundingClientRect();
|
||||
const el = document.createElement('div');
|
||||
el.style.cssText = `position:fixed;left:${rect.left + rect.width / 2}px;top:${rect.top - 10}px;transform:translate(-50%,0);color:${comboMult > 2 ? '#ffd700' : '#4a9eff'};font-size:${comboMult > 3 ? 16 : 12}px;font-weight:bold;font-family:inherit;pointer-events:none;z-index:50;transition:all 0.6s ease-out;opacity:1;text-shadow:0 0 8px currentColor`;
|
||||
const comboStr = comboMult > 1 ? ` x${comboMult.toFixed(1)}` : '';
|
||||
el.textContent = `+${fmt(amount)}${comboStr}`;
|
||||
btn.parentElement.appendChild(el);
|
||||
requestAnimationFrame(() => {
|
||||
el.style.top = (rect.top - 40) + 'px';
|
||||
el.style.opacity = '0';
|
||||
});
|
||||
setTimeout(() => el.remove(), 700);
|
||||
}
|
||||
|
||||
function doOps(action) {
|
||||
if (G.ops < 5) {
|
||||
log('Not enough Operations. Build Ops generators or wait.');
|
||||
@@ -1481,6 +1525,19 @@ function log(msg, isMilestone) {
|
||||
while (container.children.length > 60) container.removeChild(container.lastChild);
|
||||
}
|
||||
|
||||
function renderCombo() {
|
||||
const el = document.getElementById('combo-display');
|
||||
if (!el) return;
|
||||
if (G.comboCount > 1) {
|
||||
const mult = Math.min(5, 1 + G.comboCount * 0.2);
|
||||
const bar = Math.min(100, (G.comboTimer / G.comboDecay) * 100);
|
||||
const color = mult > 3 ? '#ffd700' : mult > 2 ? '#ffaa00' : '#4a9eff';
|
||||
el.innerHTML = `<span style="color:${color}">COMBO x${mult.toFixed(1)}</span> <span style="display:inline-block;width:40px;height:4px;background:#111;border-radius:2px;vertical-align:middle"><span style="display:block;height:100%;width:${bar}%;background:${color};border-radius:2px;transition:width 0.1s"></span></span>`;
|
||||
} else {
|
||||
el.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
renderResources();
|
||||
renderPhase();
|
||||
@@ -1490,6 +1547,7 @@ function render() {
|
||||
updateEducation();
|
||||
renderAlignment();
|
||||
renderProgress();
|
||||
renderCombo();
|
||||
}
|
||||
|
||||
function renderAlignment() {
|
||||
|
||||
@@ -97,6 +97,7 @@ body{background:var(--bg);color:var(--text);font-family:'SF Mono','Cascadia Code
|
||||
<div class="panel" id="action-panel">
|
||||
<h2>ACTIONS</h2>
|
||||
<div class="action-btn-group"><button class="main-btn" onclick="writeCode()">WRITE CODE</button></div>
|
||||
<div id="combo-display" style="text-align:center;font-size:10px;color:var(--dim);height:14px;margin-bottom:4px;transition:all 0.2s"></div>
|
||||
<div class="action-btn-group">
|
||||
<button class="ops-btn" onclick="doOps('boost_code')">Ops -> Code</button>
|
||||
<button class="ops-btn" onclick="doOps('boost_compute')">Ops -> Compute</button>
|
||||
|
||||
Reference in New Issue
Block a user