From 154e45e7c5c51ae0002d75d6058aba1521142462 Mon Sep 17 00:00:00 2001 From: John Bampton Date: Mon, 26 Jan 2026 10:10:51 +1000 Subject: [PATCH] Add game with 3 levels --- src/_includes/bio.njk | 18 +++ src/_includes/footer.njk | 47 +++---- src/assets/css/style.css | 27 ++++ src/assets/js/script.js | 292 +++++++++++++++++++++++++++++++-------- src/index.njk | 19 +++ src/users/mohdrash.yaml | 2 +- 6 files changed, 321 insertions(+), 84 deletions(-) diff --git a/src/_includes/bio.njk b/src/_includes/bio.njk index bb1c86ed..f19d6dd4 100644 --- a/src/_includes/bio.njk +++ b/src/_includes/bio.njk @@ -23,6 +23,24 @@

Viewing Profile

{{ name }}

+
+
+
+ +
+
+ --- + + + LVL 0 + +
+ +
+
+
+
+
diff --git a/src/_includes/footer.njk b/src/_includes/footer.njk index d64b75aa..223f2809 100644 --- a/src/_includes/footer.njk +++ b/src/_includes/footer.njk @@ -3,44 +3,39 @@

Developer Directory

-

ยฉ 2026 Powered by the open-source community

- -
- - Last Build: {{ build.timestamp }} - + Build: {{ build.timestamp }}
- - Build Hash: - {{ build.hash }} - โ†— - +
+ + + + โ†— + +
- - diff --git a/src/assets/css/style.css b/src/assets/css/style.css index db4f42dd..da586b15 100644 --- a/src/assets/css/style.css +++ b/src/assets/css/style.css @@ -57,3 +57,30 @@ body { } html { scroll-behavior: smooth; } + +/* Easter Egg: The Barrel Roll */ +.konami-roll { + transition: transform 2s cubic-bezier(0.65, 0, 0.35, 1); + transform: rotate(360deg); +} + +/* Optional: Fun font change for the title */ +.leet-mode h1 { + font-family: "Courier New", monospace !important; + color: #00ff00 !important; + text-shadow: 2px 2px #ff0000; +} + +#matrix-overlay { + background-color: black; + /* Ensure it's high, but lower than the Level Up notification (z-2000) */ + z-index: 1500; +} + +/* Make sure the canvas fills the whole screen even if scrolling */ +#matrix-canvas { + display: block; + position: fixed; + top: 0; + left: 0; +} diff --git a/src/assets/js/script.js b/src/assets/js/script.js index 6eb50725..3574a7d9 100644 --- a/src/assets/js/script.js +++ b/src/assets/js/script.js @@ -1,64 +1,142 @@ -function toggleTheme() { - const currentTheme = localStorage.getItem('theme') || 'light'; - let nextTheme; +/** + * 1. GLOBAL STATE & CONFIGURATION + */ +const LEVELS = [ + { level: 0, name: "Newbie", emoji: "๐Ÿฃ", color: "#94a3b8" }, // Start + { level: 1, name: "Script Kid", emoji: "๐Ÿ›น", color: "#10b981" }, // Matrix + { level: 2, name: "Code Breaker", emoji: "๐Ÿ•ต๏ธโ€โ™‚๏ธ", color: "#f59e0b" }, // Konami + { level: 3, name: "Void Walker", emoji: "๐ŸŒŒ", color: "#6366f1" }, // Gravity + { level: 4, name: "Bug Hunter", emoji: "๐Ÿ›", color: "#84cc16" }, + { level: 5, name: "Data Miner", emoji: "๐Ÿ’Ž", color: "#06b6d4" }, + { level: 6, name: "Sys Admin", emoji: "๐Ÿ› ๏ธ", color: "#ec4899" }, + { level: 7, name: "Terminal Pro", emoji: "โŒจ๏ธ", color: "#7c3aed" }, + { level: 8, name: "Cloud Expert", emoji: "โ˜๏ธ", color: "#3b82f6" }, + { level: 9, name: "Full Stack", emoji: "๐Ÿฅž", color: "#f97316" }, + { level: 10, name: "Architect", emoji: "๐Ÿ‘‘", color: "#ef4444" } +]; + +let unlockedEggs = JSON.parse(localStorage.getItem('unlockedEggs')) || []; +let surpriseClickCount = 0; +let matrixActive = false; +let konamiPosition = 0; +const konamiCode = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'b', 'a']; + +/** + * 2. GAME ENGINE + * Handles leveling up and UI updates + */ +function updateGameUI() { + const eggCount = unlockedEggs.length; + const levelIndex = Math.min(eggCount, LEVELS.length - 1); + const rank = LEVELS[levelIndex]; - if (currentTheme === 'light') nextTheme = 'dark'; - else if (currentTheme === 'dark') nextTheme = 'random'; - else nextTheme = 'light'; + const badge = document.getElementById('level-badge'); + const nameLabel = document.getElementById('level-name'); + const numLabel = document.getElementById('level-number'); + const progressBar = document.getElementById('level-progress'); - applyTheme(nextTheme); + if (badge) { + badge.innerText = rank.emoji; + badge.style.backgroundColor = rank.color; + } + if (nameLabel) { + nameLabel.innerText = rank.name; + nameLabel.style.color = rank.color; + } + if (numLabel) numLabel.innerText = levelIndex; + if (progressBar) { + progressBar.style.width = `${(levelIndex / (LEVELS.length - 1)) * 100}%`; + } } +function unlockEgg(eggId) { + if (!unlockedEggs.includes(eggId)) { + unlockedEggs.push(eggId); + localStorage.setItem('unlockedEggs', JSON.stringify(unlockedEggs)); + showLevelUpNotification(unlockedEggs.length); + updateGameUI(); + } +} + +function showLevelUpNotification(newLevelIndex) { + const levelIndex = Math.min(newLevelIndex, LEVELS.length - 1); + const rank = LEVELS[levelIndex]; + const notify = document.createElement('div'); + notify.className = "fixed top-24 left-1/2 -translate-x-1/2 z-[2000] px-8 py-4 bg-white dark:bg-slate-900 border-4 rounded-full shadow-2xl flex items-center gap-4 animate-bounce"; + notify.style.borderColor = rank.color; + notify.innerHTML = ` + ${rank.emoji} +
+

New Rank Achieved!

+

${rank.name}

+
+ `; + document.body.appendChild(notify); + setTimeout(() => { + notify.style.opacity = '0'; + setTimeout(() => notify.remove(), 500); + }, 4000); +} + +/** + * 3. THEME SYSTEM + */ function applyTheme(theme) { const html = document.documentElement; localStorage.setItem('theme', theme); - - // Reset all custom properties and classes html.classList.remove('dark'); + + // Clear dynamic styles const props = ['--bg-page', '--bg-card', '--bg-footer', '--text-main', '--text-muted', '--border-color', '--accent']; props.forEach(p => html.style.removeProperty(p)); if (theme === 'dark') { html.classList.add('dark'); } else if (theme === 'random') { - // Generate a random Hue (0-360) const h = Math.floor(Math.random() * 360); - - // Apply a cohesive HSL palette html.style.setProperty('--bg-page', `hsl(${h}, 40%, 8%)`); html.style.setProperty('--bg-card', `hsl(${h}, 35%, 12%)`); html.style.setProperty('--bg-footer', `hsl(${h}, 35%, 15%)`); html.style.setProperty('--text-main', `hsl(${h}, 20%, 95%)`); - html.style.setProperty('--text-muted', `hsl(${h}, 15%, 70%)`); - html.style.setProperty('--border-color', `hsl(${h}, 30%, 20%)`); - html.style.setProperty('--accent', `hsl(${(h + 150) % 360}, 80%, 65%)`); // Harmonious contrast + html.style.setProperty('--accent', `hsl(${(h + 150) % 360}, 80%, 65%)`); } + updateThemeIcon(theme); +} - updateIcon(theme); +function toggleTheme() { + const current = localStorage.getItem('theme') || 'light'; + const next = current === 'light' ? 'dark' : (current === 'dark' ? 'random' : 'light'); + applyTheme(next); } -function updateIcon(theme) { +function updateThemeIcon(theme) { const icon = document.getElementById('theme-icon'); - if (!icon) return; - if (theme === 'light') icon.innerText = '๐ŸŒ™'; // Next is Dark - else if (theme === 'dark') icon.innerText = '๐ŸŽฒ'; // Next is Random - else icon.innerText = 'โ˜€๏ธ'; // Next is Light + if (icon) icon.innerText = theme === 'light' ? '๐ŸŒ™' : (theme === 'dark' ? '๐ŸŽฒ' : 'โ˜€๏ธ'); } -// --- EASTER EGG STATE --- -let surpriseClickCount = 0; -let matrixActive = false; - /** - * Updated Surprise Me Logic with Counter + * 4. EASTER EGG TRIGGERS */ + +// EGG 1: Surprise Me x5 -> Matrix function scrollToRandomUser() { - // Increment Easter Egg counter + // 1. Force the count to increment surpriseClickCount++; - if (surpriseClickCount === 5) { + console.log("Surprise clicks:", surpriseClickCount); // Debugging line + + // 2. Check threshold + if (surpriseClickCount >= 5) { + // Reset immediately so the user can start the next 5-click cycle + surpriseClickCount = 0; + + // Attempt level unlock + unlockEgg('matrix'); + + // FORCE start the matrix initMatrix(); } + // Standard card highlight/scroll logic const cards = document.querySelectorAll('.user-card'); if (cards.length === 0) return; @@ -69,65 +147,165 @@ function scrollToRandomUser() { setTimeout(() => randomCard.classList.remove('highlight-pulse'), 3500); } -// --- THE MATRIX ENGINE --- +// EGG 2: Konami Code -> Barrel Roll +document.addEventListener('keydown', (e) => { + if (e.key === konamiCode[konamiPosition]) { + konamiPosition++; + if (konamiPosition === konamiCode.length) { + unlockEgg('konami'); + activateKonamiMode(); + konamiPosition = 0; + } + } else { konamiPosition = 0; } +}); + +function activateKonamiMode() { + document.body.classList.add('konami-roll'); + const title = document.querySelector('h1'); + if (title) { + const originalText = title.innerText; + title.innerText = "1337_D3V_CR3W"; + setTimeout(() => { title.innerText = originalText; }, 5000); + } + setTimeout(() => document.body.classList.remove('konami-roll'), 2000); +} + +// EGG 3: Gravity Glitch -> Build Hash Click +function triggerGravity(event) { + if (event) event.preventDefault(); + + // Level up! + unlockEgg('gravity'); + + // Immediate feedback: Shake everything + document.body.classList.add('glitch-shake'); + + setTimeout(() => { + document.body.classList.remove('glitch-shake'); + + // Target everything that should fall + const elements = document.querySelectorAll('.user-card, header, footer, main, h1, #game-stats'); + const viewportHeight = window.innerHeight; + + elements.forEach((el, index) => { + const rect = el.getBoundingClientRect(); + // Calculate a personalized fall distance so they don't all hit at once + const fallDist = viewportHeight - rect.top + (Math.random() * 300 + 100); + const rotation = Math.random() * 90 - 45; // Wider rotation for more "chaos" + + el.style.transition = `transform ${1 + Math.random()}s cubic-bezier(0.47, 0, 0.745, 0.715), opacity 1.5s ease-in`; + el.style.transform = `translateY(${fallDist}px) rotate(${rotation}deg)`; + el.style.opacity = "0"; + el.style.pointerEvents = "none"; + }); + + // Summon the Reset Button + setTimeout(() => { + if (!document.getElementById('repair-btn')) { + const btn = document.createElement('button'); + btn.id = 'repair-btn'; + btn.innerHTML = "REPAIR CORE SYSTEM"; + btn.className = "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-accent text-white px-10 py-5 rounded-full font-black z-[3000] shadow-[0_0_50px_rgba(0,0,0,0.5)] hover:scale-110 transition-all cursor-pointer border-4 border-white animate-pulse"; + btn.onclick = () => window.location.reload(); + document.body.appendChild(btn); + } + }, 1200); + }, 500); +} + +/** + * THE MATRIX ENGINE + */ function initMatrix() { + // 1. Reset state to ensure clean start matrixActive = true; const overlay = document.getElementById('matrix-overlay'); const canvas = document.getElementById('matrix-canvas'); - const ctx = canvas.getContext('2d'); + if (!overlay || !canvas) return; + // 2. Show the overlay overlay.classList.remove('hidden'); + overlay.style.display = 'block'; - // Set canvas to full screen + // 3. Setup Canvas canvas.width = window.innerWidth; canvas.height = window.innerHeight; - - const katakana = 'ใ‚ขใ‚กใ‚ซใ‚ตใ‚ฟใƒŠใƒใƒžใƒคใƒฃใƒฉใƒฏใ‚ฌใ‚ถใƒ€ใƒใƒ‘ใ‚คใ‚ฃใ‚ญใ‚ทใƒใƒ‹ใƒ’ใƒŸใƒชใƒฐใ‚ฎใ‚ธใƒ‚ใƒ“ใƒ”ใ‚ฆใ‚ฅใ‚ฏใ‚นใƒ„ใƒŒใƒ•ใƒ ใƒฆใƒฅใƒซใ‚ฐใ‚บใƒ–ใƒ…ใƒ—ใ‚จใ‚งใ‚ฑใ‚ปใƒ†ใƒใƒ˜ใƒกใƒฌใƒฑใ‚ฒใ‚ผใƒ‡ใƒ™ใƒšใ‚ชใ‚ฉใ‚ณใ‚ฝใƒˆใƒŽใƒ›ใƒขใƒจใƒงใƒญใƒฒใ‚ดใ‚พใƒ‰ใƒœใƒใƒดใƒƒใƒณ'; - const latin = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - const nums = '0123456789'; - const alphabet = katakana + latin + nums; - + const ctx = canvas.getContext('2d'); + const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ใ‚ขใ‚กใ‚ซใ‚ตใ‚ฟใƒŠใƒใƒžใƒคใƒฃ'; const fontSize = 16; - const columns = canvas.width / fontSize; + const columns = Math.floor(canvas.width / fontSize); const rainDrops = Array.from({ length: columns }).fill(1); + // 4. Rendering Loop with explicit Kill Switch const render = () => { - // Subtle fade effect to create trails + if (!matrixActive) { + // Stop the loop entirely + ctx.clearRect(0, 0, canvas.width, canvas.height); + return; + } + ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; ctx.fillRect(0, 0, canvas.width, canvas.height); - - ctx.fillStyle = '#0F0'; // Matrix Green + ctx.fillStyle = '#0F0'; ctx.font = fontSize + 'px monospace'; for (let i = 0; i < rainDrops.length; i++) { const text = alphabet.charAt(Math.floor(Math.random() * alphabet.length)); ctx.fillText(text, i * fontSize, rainDrops[i] * fontSize); - - if (rainDrops[i] * fontSize > canvas.height && Math.random() > 0.975) { - rainDrops[i] = 0; - } + if (rainDrops[i] * fontSize > canvas.height && Math.random() > 0.975) rainDrops[i] = 0; rainDrops[i]++; } - - if (matrixActive) requestAnimationFrame(render); + requestAnimationFrame(render); }; render(); - // Listen for Escape key to exit - window.addEventListener('keydown', handleEsc); + // 5. Add Escape Listener + window.addEventListener('keydown', handleMatrixEsc); +} + +// Separate function for the listener so we can remove it properly +function handleMatrixEsc(e) { + if (e.key === 'Escape') { + closeMatrix(); + } } function closeMatrix() { + // 1. Flip the kill switch matrixActive = false; - surpriseClickCount = 0; // Reset counter - document.getElementById('matrix-overlay').classList.add('hidden'); - window.removeEventListener('keydown', handleEsc); -} -function handleEsc(e) { - if (e.key === 'Escape') closeMatrix(); + // 2. Hide the UI + const overlay = document.getElementById('matrix-overlay'); + if (overlay) { + overlay.classList.add('hidden'); + overlay.style.display = 'none'; + } + + // 3. Clean up the listener to prevent memory leaks + window.removeEventListener('keydown', handleMatrixEsc); + + // 4. Reset click counter so they don't get stuck in a loop + surpriseClickCount = 0; } -// Initial Run -applyTheme(localStorage.getItem('theme') || 'light'); +/** + * 6. INITIALIZATION + */ +document.addEventListener('DOMContentLoaded', () => { + // 1. Theme + applyTheme(localStorage.getItem('theme') || 'light'); + // 2. Game Stats + updateGameUI(); +}); + +// Helper for Bio page email copy +function copyToClipboard(text, el) { + navigator.clipboard.writeText(text); + const span = el.querySelector('span:last-child'); + if (span) { + const original = span.innerText; + span.innerText = 'Copied!'; + setTimeout(() => span.innerText = original, 2000); + } +} diff --git a/src/index.njk b/src/index.njk index f2777387..60c8727a 100644 --- a/src/index.njk +++ b/src/index.njk @@ -32,6 +32,25 @@ layout: false +
+
+
+ +
+
+ --- + + + LVL 0 + +
+ +
+
+
+
+
+