Skip to content

Instantly share code, notes, and snippets.

@notnotrishi
Last active November 14, 2025 07:03
Show Gist options
  • Select an option

  • Save notnotrishi/47dbe8088a614effec71e6a22a7af0ab to your computer and use it in GitHub Desktop.

Select an option

Save notnotrishi/47dbe8088a614effec71e6a22a7af0ab to your computer and use it in GitHub Desktop.
(() => {
// Detect environment
const detectEnvironment = () => {
const ua = navigator.userAgent;
const isVSCode = ua.includes('Visual Studio Code') ||
typeof acquireVsCodeApi !== 'undefined' ||
window.vscodeApi !== undefined;
const isElectron = ua.includes('Electron') || typeof require !== 'undefined';
const isChrome = /Chrome/.test(ua) && !/Edge/.test(ua);
const isFirefox = /Firefox/.test(ua);
const isSafari = /Safari/.test(ua) && !/Chrome/.test(ua);
return { isVSCode, isElectron, isChrome, isFirefox, isSafari, ua };
};
const ENV = detectEnvironment();
const SHOW_PULSING_ICON = ENV.isVSCode; // Only show in VS Code webviews
const isDark = typeof THEME !== "undefined" ? THEME === "dark" : true;
const COLORS = {
text: isDark ? "#0aae5cff" : "#006644",
boxBg: isDark ? "rgba(17,17,17,0.82)" : "rgba(255,255,255,0.82)",
boxBorder: isDark ? "#0aae5cff" : "#006644",
launcherBg: isDark ? "#111" : "#ddd",
launcherText: isDark ? "#0aae5cff" : "#006644"
};
// ๐ŸŽฎ launcher button (bottom-left)
const launcher = document.createElement("div");
launcher.textContent = "๐ŸŽฎ";
Object.assign(launcher.style, {
position: "fixed",
bottom: "10px",
left: "10px",
background: COLORS.launcherBg,
color: COLORS.launcherText,
padding: "6px 10px",
borderRadius: "8px",
cursor: "pointer",
zIndex: 999999,
fontFamily: "Consolas, Courier New, monospace",
fontSize: "14px",
boxShadow: "0 2px 6px rgba(0,0,0,0.3)",
userSelect: "none",
transition: "transform 0.15s ease, opacity 0.2s ease"
});
document.body.appendChild(launcher);
// ๐Ÿงฉ centered pulsing icon overlay
const icon = document.createElement("img");
icon.src = "data:image/jpeg;base64,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v3n2kUBShQ+J9DmSRnMmJmZkzmZkzM5mWUkiRERBFVaqmqrVW7urdW7t1rWrrVt1pdXzP0PUUlVUKEfnfhZkmZlmZmGJmTEkmJnMkkSRIkRBFVaq01a0tu7daurdau7dXV22urt7H3lqpVQFyPQ+tSTMkwzmZzMJiZkznMzJlmEkjJCEqlqrVrTS6urrV1dXV1rVuru6urdW22tSyqQREmWZmMzMznMzmZmcyZmc5mZJlIkSIkQWlW00ttturdau2ru6urrTW7q3V1o1aajUNMpWUkYjOWZnOZnOcsSZzJnOJmSSSMkiJEsWlWrabq3Vt1d3Wrq61dautaurq61VbK0AM0zGWIyzmZzmZznMzMzOZMTEzGYyjKJCEVVqtKtuq1dW7utXV3btvV1bu6utLpVupVRKZMxJIzhnMzM4mcsZmcs4mZnMxcpMkSIhFqltW1bdW6urrdurrV1da1rWrq6bttW3RRZKiRJJJlmZzM5mZnEzM5zMzOc5zJlMokiEiFqltaLptdXV1rVuta2utbt3da1bbq2ro1KqAkkTMkmcyYmcyYmczOc5mc5wzmSSSRGSQSrS1Wlatt03dburd3WtXWru6urrVumi6W0qWQzc2ZZmZJhiYYkziZzmZznMznMzIyykRIhFaLVtVq23V1rWtXWm7rWrvV1q6umtW2tVos1FkRDMmYzM5mZnEmcTMznMznEzM5kkkyjJJAGhpWltt01q7utautXV1rWrrV1q9DVt0trRZVxc6mSTMkmGGJM5znOZmYmc5zmZzMzLLJIyZEqtFWrWrdW61q61q61rV1bvV1q7urpq2tVaalM6zZIyzlliTMznOZnOcSYzJnEzhnMyzESJIQUq2lt01bdXWtat1d61dXWru61q601bdLotVZcaiRlMyTMkziTEzmYzmZzM5zMTOZmSZRIkiAtLatXTVt1rV1q3W7rbetNXertvTVW1tatCJcozMzKSZxMzExJjOZiTOc5mMzMZkiRJERKtVVaaaturq63bq61rWtW71dau7q23Wi6athQiJJmSTLDEmMzEznOc5zmZmMzOJMpGUiRESqq2mra1dNa1q61brd1q61rV1q7urdW23SrbKESEzGEmZmZmJnExmZmJnOc5mMyZjMjMJERKqratataurrWm9Na1rV3q61da1daa1bbdNFVUlRmGcszMmZnMxM5xM5zM5zmZznMzmSSSEkRkaUtq221dN7t1q603rV1vTo1d61a1dW6WtUFyXKSSZTOWcMTOc5xM5mcTOZjOZM5ZkkRJEQFtVbatt1d3WrrTdu7rerejerrVumrppo0pZZCMpmSTMkzMzGMzMzjMznMxM5mJlMxmEkRJSqtVpppdXWtaurq61q7uta3dau2tVq6W22y0EQZkyzJhMSYwzMZzmZzMZmc5mcMySSGUSBTUttW21dXWtXWtXV1rWru61rWrtrTVtuq0pZRAzJJmZZkzmTGczExM5znMxM5mMyMxlGUSEqqrS21qtXWtXd1dXWta1q63d261q26W6amqUCEZyzJmM5kmM5mJiYmc5zmZznMxJIzGUSElUtNLVturda1bu61d271da1u7t1dW6rS3U1YogSSTLMkmZnMxnOc5mc4mc5mcMZmZJMoiSISqqqurWlutbba1rTetXW9W73pu6umrV1SqsLmomYywmWczOJmYzMZmMzOJMTMzmSSZREiIqrS2rpbbq63datutbu7vV3d61dW6ttttVVQCM3MwiZmZnOc5mc5ziYzmZzM5mMySZSJGSEVoW21bbdXVu7q6ut3ervd1vWru3TZq1VNSpYS5MyZiZkmc5ziZzjOc5znMznOZnMmWUkRGRKpbVaW6XVutXemta1rWtb1u723ptq221WgohEJmSSSTOZOeJjOM5ziZzmZznMzMspIkiICqWtLbbbdaut6aut7ut63vet6u7bq1paqk0QgkSSMJmTOM884xjMxiZzMZmZjMkiSMoiEq0rSaaaat1rWrq3e9b1vXTe99Lu3bU3WlLRViBIMssxnOc5xzxjnjExnEznMznOcyMspEiJLKVatWtLq3WrrWrrW9dNdN9Om+m+mtatrS1bSalCJZZCS4SZmcc8c+fPHLOM885mcTMziSRllGUSClVataq6t1dauta1vpvfTr169evW71rVs1oWipVEQiCJMsZxz58eXLly55xjGZiZznOZJJIySQkUotq1bbdN3WtXd3ve+vXt37+R2671rWtzRVFiirksJLEXLM58+XHx/H48eXHPPGMzExMzEykkkREhKKqtLVttutXW9Xd6769e3fyfJ+l/TferbSkFJUNCKQVCJGfS/mnzPjeLw4cufPGMTOc4zM5kSTJIiAKparTTVtu9a1rW99evbyPJ8v9a/dtgAl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ba7a7bbbbbazbbbbbTbaabTbabTbXa7bXXXba7bbbbbbbbbbabTTabTTabTbXa7XXXXWXXbbbbbbbbbbSWTTTTTTTbTbXa6663Xa67XbbbbbbbbTTSaaTTTaTTbaXXW663W663bXbbWbbbabSSaSaTSaSaXS7XLW623W267a7bbbbabTSSSaHSaSSTba7W6222223W3XbbbbbaaaSSSQzQzSSabbW63K222rLW3XXbbbabSaQySQySGTSabbXW25Wq21W223bXWbaaSTGSEyGSGSTTbba3LK1Wqqq223XXbbTTSGHEwmQwySTTbba3Wqq1VKq1W23a7aaSYyGEmGEwyTSTba7W22pWqp1Wq2267aSaGQwkkmEyQzSaba6622pVKpJKq1XW7TSSGGEQEwmSGSTTS7a25VW1JJJJKq263TSGGEkEkmGGGSTSba6221Kq1JpJOq223SSGEkiEEmGGGGzTTRa7Kq1K1JNJpVWq6yGQkggkQwmGE+X9Jewu2tsvg/M/iJWpVVJppJ1W26SQkkEEGEmEmH3v0vrtrbrfmH0aqqVSqaaaSStukMJIBBBhMJJM999MXbbK235f8ARVVJKpVNtNJKq6GEwcyASSYSSSff/Td22tty+XPQpVJJVJNptNKq4mEkgAEkkkkkz330/Nrrqrflr0CVSSSSSbbTSVuhJh5gHnCDCIQTPffUW2u2q1+WfQWpqppJJttpJK4mEgAAkEkiAmH2n1a9tddaPk71SqTSSdabbbSSuJJIAAJBJBJBJP8ASeym0113rf5utKtJpJpdG20klhCSBzAJIJBJBIOMm221VSrSbSSabfRtJJSEk8wOZBIIgBIJMkk2sqyqSaTTSab6NtNK0EkgcwCQSCASCTJDptbbVU000m00+j6Jpq4mAADmSAQSASCYYZNtcslWmk2k2munRtpJYkkAcwCQQQQQRCZJJtrVUkk2mmm0+nRNtJYkkDnzBIJAIJAJhhk22tqVSbSbaabfRttJYkgjmOZBJAIIIJMMk0u1qSSTabTaa6dG20liSRzAABIJAIIJhMkm11VSSTabTabfRtppYkkAcwASQQAQRDCdJtdVUkk2mm2m30bbSWJJAHMAEgkAAgwwnSbXVVKpdE202munRvokliYCOY5gEkEAHmSTIdNttUqqm022mmunR9GklRCCBzABBBHM8wSTJJptdbXak+jbbTTfVtutYkkAcwACRzHPnzAhkkm0u1ttSXTr06NtNPp0bbSWJJI5jmCCOfPlw48gDJjptLrrran27du3To20+j6NpJYmEAcwACOXHx/E9F6UiTbTbTXa7a1+6975fkdurbXTo+jTSuhJJ5jmAAOPDwvz38jm22222222222v6z+h+b5HXo2unTo2klaTCQBzAAHDxvXfP/pttttttttttttt7j6A9j5Pbo2unTo2lVaYYCBzAA58vE9f89eq2mu222220u223tPoT2Xk9ujT6t9E6ldDISBzHMAcfH8H8i/O9tZtZdLtptttr+g/rvn+T1bb6Po0krdJDCAOYAHPh43gfwHpzJNtttLtLtdV7f8Av/P8rv0bbfRtJWqaQkkgDmDz58fH4cQJJtpttttraunXyPI7dOibbfRKpZaYwkkgAADnz5Ak6Habbba61V9OnTo2030aSqtumhhhBABAIBJh0k2m2u1tqabTabbSSttu0khhJAIBgJMhmk2m211tqSSSbXRNKq23bTSQmEEEEkmSSSabTa3W22pKttN1K223baaSCEwEEiGQzSbTbbXW3VKtJtJKq23XbaaTEwwEkkk6HSabbba3VWqtNJKpW267babSSQwkiEkw6aTbSzW5a1VpJ1K1W667bbTTSSGEmEkySTTTbbXW211JJVVarXa7babaaSQwwwwmSSabbbXWq1VJVWq3W67bWbabTTGSGSEySHTTba622qqq1W263XbbWbbabSY4ySSGSTSbbbXW1W1W21a667bbbbbS6aTSSSSSSaTbSy622222227Xa7bbbbbaWbTSSTSTSaabbbXXWq62663a7bbbbbbbbabTSTSTTSbbbbXa5a3W667a7bbazbbbbbTabSaTaaabbbXa3W7W67a7bbba6azbbbbTbaTaabTbSzXXa3a67a7bbbbXbabbbbbbabbTTbTbbbba67a7Xbbbba7bf//EACkQAAIBAgQGAgMBAQAAAAAAABESAQAVAgUWYAMEBhBAUCAwcICQsMD/2gAIAQEAAQIB/wCBHH6LztYAfADsB2HYbs5XLwFUKoAAVVVVVRODmcu3PyGDyMwwbmy3ycy3Plvk5lufLfJzLc+XeTmW58u8nMdz5f5OY7ny7ycy3Pl/k5jufL/JzHwJ2vl/k5jufkPJzDc/B4kT42KePxNkx53B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"
// Ensure this path points to a valid icon image
Object.assign(icon.style, {
position: "fixed",
top: "50%",
left: "50%",
width: "120px",
height: "120px",
transform: "translate(-50%, -50%)",
opacity: "0.9",
zIndex: 999997,
pointerEvents: "none",
transition: "opacity 0.6s ease"
});
document.body.appendChild(icon);
// Pulse animation
const style = document.createElement("style");
style.textContent = `
@keyframes pulseIcon {
0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.85; }
50% { transform: translate(-50%, -50%) scale(1.1); opacity: 1; }
}
`;
document.head.appendChild(style);
const startPulse = () => {
icon.style.animation = "pulseIcon 2.5s ease-in-out infinite";
};
const stopPulse = () => {
icon.style.animation = "none";
};
let canvas, ctx, w, h, score, over, paddle, brick, animationId;
let gameActive = false;
let keys = {};
let keydownHandler, keyupHandler;
let particles = [];
let closeBtn, countdownTimer, countdown = 3;
let level = 1;
let starting = false;
// --- Single-tab (cross-tab) singleton support ---
const SINGLETON = { enable: true, heartbeatMs: 2000, staleMs: 6000, verifyMs: 120, pingMs: 500 };
const SINGLETON_KEY = "bricks_game_singleton";
const tabId = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
let heartbeatTimer = null;
let otherOwnerAlerted = false;
let lockHeld = false;
let lockCurrentId = null;
const pendingPings = new Map();
const delay = ms => new Promise(r => setTimeout(r, ms));
const bc = 'BroadcastChannel' in window ? new BroadcastChannel('vscode-bricks-singleton') : null;
const now = () => Date.now();
const readLock = () => {
try {
const raw = localStorage.getItem(SINGLETON_KEY);
return raw ? JSON.parse(raw) : null;
} catch {
return null;
}
};
const writeLock = (data) => {
try {
localStorage.setItem(SINGLETON_KEY, JSON.stringify(data));
lockCurrentId = data?.id ?? null;
} catch {}
};
const clearLock = () => {
try {
const cur = readLock();
if (cur && cur.id === tabId) {
localStorage.removeItem(SINGLETON_KEY);
lockCurrentId = null;
}
} catch {}
};
const isStale = (lock) => !lock || (now() - lock.ts) > SINGLETON.staleMs;
const ownerResponds = (lock) => {
if (!bc || !lock?.id) return Promise.resolve(true); // treat as alive if we can't ping
const correlationId = `${tabId}-${Math.random().toString(36).slice(2)}`;
return new Promise((resolve) => {
const timeout = setTimeout(() => {
pendingPings.delete(correlationId);
resolve(false);
}, SINGLETON.pingMs);
pendingPings.set(correlationId, () => {
clearTimeout(timeout);
resolve(true);
});
try {
bc.postMessage({ type: 'ping', from: tabId, lockId: lock.id, correlationId });
} catch {
clearTimeout(timeout);
pendingPings.delete(correlationId);
resolve(true);
}
});
};
async function claimSingleton() {
if (!SINGLETON.enable) return true;
const current = readLock();
if (current && current.id !== tabId && !isStale(current)) {
if (await ownerResponds(current)) {
flashLauncherLocked();
notifyExisting();
requestShow();
return false;
}
// Someone else actively owns it
flashLauncherLocked();
notifyExisting();
requestShow();
return false;
}
// Optimistic claim -> verify shortly to avoid races
writeLock({ id: tabId, ts: now() });
await delay(SINGLETON.verifyMs);
const after = readLock();
if (!after || after.id !== tabId) {
flashLauncherLocked();
notifyExisting();
requestShow();
return false;
}
startHeartbeat();
lockHeld = true;
return true;
}
function requestShow() {
try { bc?.postMessage({ type: 'show' }); } catch {}
}
function startHeartbeat() {
stopHeartbeat();
lockHeld = true;
heartbeatTimer = setInterval(() => {
const cur = readLock();
if (!cur || cur.id === tabId) {
writeLock({ id: tabId, ts: now() });
}
}, SINGLETON.heartbeatMs);
}
function stopHeartbeat() {
if (heartbeatTimer) {
clearInterval(heartbeatTimer);
heartbeatTimer = null;
}
lockHeld = false;
}
function releaseSingleton() {
stopHeartbeat();
clearLock();
}
function flashLauncherLocked() {
launcher.textContent = "๐Ÿ”’";
launcher.style.transform = "scale(1.2)";
setTimeout(() => (launcher.style.transform = "scale(1)"), 250);
}
function notifyExisting() {
if (otherOwnerAlerted) return;
otherOwnerAlerted = true;
// Gentle notice in place of alert
icon.style.opacity = "1";
icon.title = "Game already running in another tab.";
}
window.addEventListener("storage", (e) => {
if (e.key !== SINGLETON_KEY) return;
const lock = readLock();
if (lock && lock.id !== tabId && gameActive) {
// We lost ownership (another tab took over after we became stale) -> stop locally
stopGame({ showIdle: SHOW_PULSING_ICON });
notifyExisting();
}
});
window.addEventListener("pagehide", releaseSingleton);
window.addEventListener("beforeunload", releaseSingleton);
// --- end singleton support ---
if (bc) {
bc.addEventListener("message", (e) => {
const data = e?.data;
if (!data) return;
if (data.type === "show" && gameActive) {
launcher.style.transform = "scale(1.25)";
setTimeout(() => (launcher.style.transform = "scale(1)"), 220);
} else if (data.type === "ping") {
if (lockHeld && lockCurrentId && data.lockId === lockCurrentId) {
try { bc.postMessage({ type: "pong", to: data.from, correlationId: data.correlationId }); } catch {}
}
} else if (data.type === "pong" && data.to === tabId) {
const resolver = pendingPings.get(data.correlationId);
if (resolver) {
resolver();
pendingPings.delete(data.correlationId);
}
}
});
}
const AudioCtx = window.AudioContext || window.webkitAudioContext;
const audioCtx = new AudioCtx();
const playTone = (freq, duration = 0.1, type = "sine") => {
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = type;
osc.frequency.value = freq;
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start();
gain.gain.setValueAtTime(0.1, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + duration);
osc.stop(audioCtx.currentTime + duration);
};
const playCatchSound = () => {
playTone(600, 0.07, "square");
setTimeout(() => playTone(800, 0.07, "square"), 50);
};
const playGameOverSound = () => {
playTone(300, 0.15, "triangle");
setTimeout(() => playTone(200, 0.15, "triangle"), 100);
};
const playStartChime = () => {
playTone(400, 0.1, "sine");
setTimeout(() => playTone(600, 0.1, "sine"), 100);
setTimeout(() => playTone(800, 0.15, "sine"), 200);
};
const isSpaceKey = e => e.code === "Space" || e.key === " " || e.key === "Spacebar";
const createCloseButton = () => {
if (closeBtn) {
closeBtn.style.display = "block";
closeBtn.style.setProperty("z-index", "2147483647", "important");
try { document.documentElement.appendChild(closeBtn); } catch {}
return closeBtn;
}
closeBtn = document.createElement("div");
closeBtn.textContent = "โœ–๏ธ";
Object.assign(closeBtn.style, {
position: "fixed",
top: "12px",
right: "12px",
fontSize: "20px",
background: "transparent", // Remove background
color: "#fff",
padding: "6px 8px",
borderRadius: "6px",
cursor: "pointer",
zIndex: 2147483647,
userSelect: "none",
fontFamily: "Consolas, Courier New, monospace",
transition: "opacity 0.2s ease",
pointerEvents: "auto"
});
closeBtn.onmouseover = () => (closeBtn.style.opacity = "0.8");
closeBtn.onmouseout = () => (closeBtn.style.opacity = "1");
try { document.documentElement.appendChild(closeBtn); } catch { document.body.appendChild(closeBtn); }
return closeBtn;
};
const removeCloseButton = () => closeBtn?.remove();
const drawTextBox = (textLines) => {
const boxWidth = 370;
const boxHeight = 120;
const boxX = (w - boxWidth) / 2;
const boxY = (h - boxHeight) / 2 - 20;
ctx.fillStyle = COLORS.boxBg;
ctx.fillRect(boxX, boxY, boxWidth, boxHeight);
ctx.strokeStyle = COLORS.boxBorder;
ctx.lineWidth = 2;
ctx.strokeRect(boxX, boxY, boxWidth, boxHeight);
ctx.fillStyle = COLORS.text;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
textLines.forEach((line, i) => {
ctx.font = i === 0 ? "bold 36px Consolas, Courier New, monospace" : "18px Consolas, Courier New, monospace";
ctx.fillText(line.toUpperCase(), w / 2, boxY + 35 + i * 30);
});
};
const showCountdown = () => {
ctx.clearRect(0, 0, w, h);
drawTextBox([String(countdown), "PRESS โœ–๏ธ OR ESC MID-GAME TO EXIT"]);
};
const setupGame = () => {
w = canvas.width = innerWidth;
h = canvas.height = innerHeight;
paddle = { x: w / 2 - 60, y: h - 70, width: 120, height: 24, speed: 15 };
brick = { x: Math.random() * (w - 20), y: 0, size: 20, speed: 4 };
};
const showIcon = () => {
const btn = createCloseButton();
btn.style.display = "none"; // Hide the close button when showing pulsing icon
icon.style.opacity = "0.9";
icon.style.display = "block";
startPulse();
};
const hideIcon = () => {
icon.style.opacity = "0";
icon.style.display = "none";
stopPulse();
};
const startGame = async () => {
if (starting || gameActive) return;
if (SINGLETON.enable) {
const ok = await claimSingleton(); // verified claim
if (!ok) return;
}
starting = true;
launcher.style.transform = "scale(1.1)";
launcher.style.opacity = "0.7";
setTimeout(() => {
launcher.style.transform = "scale(1)";
launcher.style.opacity = "1";
}, 150);
score = 0;
level = 1;
launcher.textContent = "๐ŸŽฎ";
icon.style.display = "none";
gameActive = true;
over = false;
canvas = document.createElement("canvas");
Object.assign(canvas.style, {
position: "fixed",
top: 0,
left: 0,
width: "100vw",
height: "100vh",
background: "rgba(0,0,0,0.01)",
zIndex: 999998
});
document.body.appendChild(canvas);
ctx = canvas.getContext("2d");
addEventListener("resize", setupGame);
createCloseButton();
particles = [];
setupGame();
countdown = 3;
showCountdown();
countdownTimer = setInterval(() => {
countdown--;
if (countdown > 0) {
showCountdown();
} else {
clearInterval(countdownTimer);
playStartChime();
startGameplay();
starting = false;
}
}, 1000);
};
const startGameplay = () => {
keys = {};
keydownHandler = e => {
keys[e.key] = true;
if (isSpaceKey(e)) e.preventDefault();
if (e.key === "Escape") {
score = 0;
launcher.textContent = "๐ŸŽฎ";
stopGame({ showIdle: SHOW_PULSING_ICON });
}
if (over && isSpaceKey(e)) {
stopGame({ showIdle: false });
startGame();
}
};
keyupHandler = e => {
delete keys[e.key];
};
window.addEventListener("keydown", keydownHandler);
window.addEventListener("keyup", keyupHandler);
// when creating the close button
closeBtn.onclick = () => stopGame({ showIdle: true });
const makeParticles = (x, y, color = "#a84637") => {
for (let i = 0; i < 15; i++) {
particles.push({
x,
y,
vx: (Math.random() - 0.5) * 5,
vy: -Math.random() * 4,
life: 30,
color
});
}
};
const loop = () => {
ctx.clearRect(0, 0, w, h);
if (keys["ArrowLeft"]) paddle.x -= paddle.speed;
if (keys["ArrowRight"]) paddle.x += paddle.speed;
paddle.x = Math.max(0, Math.min(w - paddle.width, paddle.x));
if (!over) {
brick.y += brick.speed;
if (
brick.y + brick.size > paddle.y &&
brick.x + brick.size > paddle.x &&
brick.x < paddle.x + paddle.width
) {
score++;
playCatchSound();
launcher.textContent = `๐Ÿ† ${score}`;
makeParticles(brick.x + brick.size / 2, paddle.y, "#a84637");
brick.y = 0;
brick.x = Math.random() * (w - brick.size);
if (score % 10 === 0) {
brick.speed += 0.7;
level++;
}
}
if (brick.y > h) {
over = true;
playGameOverSound();
launcher.textContent = "๐ŸŽฎ";
}
ctx.fillStyle = "#a84637";
ctx.fillRect(brick.x, brick.y, brick.size, brick.size);
ctx.fillStyle = "#00FFFF";
ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
ctx.font = "bold 13px Consolas, Courier New, monospace";
ctx.fillStyle = "#000000";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(`LVL ${level}`.toUpperCase(), paddle.x + paddle.width / 2, paddle.y + paddle.height / 2);
particles = particles.filter(p => p.life > 0);
for (const p of particles) {
p.x += p.vx;
p.y += p.vy;
p.vy += 0.2;
p.life--;
ctx.fillStyle = `rgba(168,70,55,${p.life / 30})`;
ctx.fillRect(p.x, p.y, 3, 3);
}
animationId = requestAnimationFrame(loop);
} else {
drawTextBox([`GAME OVER`, `๐Ÿ† SCORE: ${score}`, `PRESS SPACE OR ๐ŸŽฎ TO RESTART`]);
}
};
loop();
};
const stopGame = ({ showIdle = true } = {}) => {
releaseSingleton();
gameActive = false;
starting = false;
cancelAnimationFrame(animationId);
clearInterval(countdownTimer);
if (keydownHandler) {
window.removeEventListener("keydown", keydownHandler);
keydownHandler = null;
}
if (keyupHandler) {
window.removeEventListener("keyup", keyupHandler);
keyupHandler = null;
}
keys = {};
canvas?.remove();
if (!showIdle) {
closeBtn?.style.setProperty("display", "none");
} else {
if (SHOW_PULSING_ICON) {
showIcon(); // only show the center icon if environment supports it
} else {
closeBtn?.style.setProperty("display", "none");
icon.style.display = "none";
}
}
};
// At the end, conditionally show icon
launcher.onclick = () => {
if (gameActive) {
if (over) {
stopGame({ showIdle: false });
startGame();
} else {
stopGame({ showIdle: SHOW_PULSING_ICON });
}
} else {
startGame();
}
};
// Allow spacebar to launch game from idle pulsating view
window.addEventListener("keydown", (e) => {
if (isSpaceKey(e) && !gameActive && !starting) {
e.preventDefault();
startGame();
}
});
// Show pulsing icon on idle start (only if enabled for this environment)
if (SHOW_PULSING_ICON) {
showIcon();
} else {
icon.style.display = "none";
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment