Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Tyler's IT Adventure</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| @keyframes float { | |
| 0% { transform: translateY(0px); } | |
| 50% { transform: translateY(-10px); } | |
| 100% { transform: translateY(0px); } | |
| } | |
| .floating { | |
| animation: float 3s ease-in-out infinite; | |
| } | |
| @keyframes shake { | |
| 0% { transform: rotate(0deg); } | |
| 25% { transform: rotate(5deg); } | |
| 50% { transform: rotate(0eg); } | |
| 75% { transform: rotate(-5deg); } | |
| 100% { transform: rotate(0deg); } | |
| } | |
| .shake { | |
| animation: shake 0.5s ease-in-out; | |
| } | |
| .cable-drag { | |
| transition: all 0.3s ease; | |
| } | |
| .plug-success { | |
| transform: scale(1.1); | |
| transition: all 0.3s ease; | |
| } | |
| .task-complete { | |
| background-color: rgba(74, 222, 128, 0.3); | |
| transition: all 0.5s ease; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-blue-50 min-h-screen flex flex-col items-center justify-center p-4"> | |
| <div class="max-w-3xl w-full bg-white rounded-xl shadow-xl overflow-hidden"> | |
| <!-- Header --> | |
| <div class="bg-blue-600 text-white p-6"> | |
| <h1 class="text-3xl font-bold text-center">Tyler's IT Adventure</h1> | |
| <p class="text-center mt-2">Help Tyler complete simple IT tasks!</p> | |
| </div> | |
| <!-- Game Area --> | |
| <div class="p-6"> | |
| <!-- Character and Stats --> | |
| <div class="flex flex-col md:flex-row items-center justify-between mb-8"> | |
| <div class="flex items-center mb-4 md:mb-0"> | |
| <div class="relative"> | |
| <div class="w-24 h-24 bg-yellow-300 rounded-full flex items-center justify-center floating"> | |
| <i class="fas fa-user text-4xl text-yellow-700"></i> | |
| </div> | |
| <div class="absolute -bottom-2 -right-2 bg-green-500 text-white rounded-full w-8 h-8 flex items-center justify-center"> | |
| <span id="level">1</span> | |
| </div> | |
| </div> | |
| <div class="ml-4"> | |
| <h2 class="text-xl font-bold">Tyler</h2> | |
| <div class="flex items-center"> | |
| <div class="w-32 bg-gray-200 rounded-full h-4"> | |
| <div id="xp-bar" class="bg-green-500 h-4 rounded-full" style="width: 0%"></div> | |
| </div> | |
| <span id="xp-text" class="ml-2 text-sm">0/100 XP</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="bg-blue-100 rounded-lg p-4"> | |
| <div class="flex justify-between mb-2"> | |
| <span>Tasks Completed:</span> | |
| <span id="tasks-completed">0</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span>Current Streak:</span> | |
| <span id="current-streak">0</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Current Task --> | |
| <div id="task-container" class="bg-blue-100 rounded-lg p-6 mb-6"> | |
| <h3 class="text-xl font-bold mb-4 text-center">Current Task</h3> | |
| <p id="task-description" class="text-center mb-4">Plug in the computer cable to the power outlet</p> | |
| <!-- Game Interaction Area --> | |
| <div class="flex flex-col items-center"> | |
| <div class="relative w-full max-w-md h-48 bg-gray-200 rounded-lg mb-4 flex items-center justify-center"> | |
| <!-- Computer --> | |
| <div id="computer" class="absolute left-1/4 transform -translate-x-1/2 bg-gray-700 w-24 h-16 rounded flex items-center justify-center"> | |
| <div class="w-20 h-12 bg-gray-800 rounded flex items-center justify-center"> | |
| <div class="w-16 h-8 bg-blue-900 rounded"></div> | |
| </div> | |
| </div> | |
| <!-- Cable --> | |
| <div id="cable" class="absolute left-1/4 top-1/2 transform -translate-x-1/2 w-32 h-2 bg-gray-500 rounded-full cursor-grab"></div> | |
| <!-- Power Outlet --> | |
| <div id="outlet" class="absolute right-1/4 transform translate-x-1/2 bg-gray-300 w-16 h-10 rounded flex items-center justify-center"> | |
| <div class="w-12 h-8 bg-gray-400 rounded flex items-center justify-center"> | |
| <div class="w-2 h-6 bg-gray-700 rounded"></div> | |
| </div> | |
| </div> | |
| <!-- Plug --> | |
| <div id="plug" class="absolute left-1/4 top-1/2 transform translate-x-8 w-6 h-4 bg-gray-600 rounded cursor-grab"></div> | |
| </div> | |
| <button id="start-task" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-6 rounded-full transition"> | |
| Start Task | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Task Instructions --> | |
| <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 mb-6"> | |
| <h4 class="font-bold mb-2">How to play:</h4> | |
| <ol class="list-decimal pl-5 space-y-1"> | |
| <li>Click "Start Task" to begin</li> | |
| <li>Drag the plug to the power outlet</li> | |
| <li>Complete tasks to level up Tyler</li> | |
| </ol> | |
| </div> | |
| <!-- Upgrades --> | |
| <div class="bg-purple-50 rounded-lg p-4"> | |
| <h3 class="text-xl font-bold mb-4 text-center">Upgrades</h3> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div class="bg-white p-4 rounded-lg shadow"> | |
| <h4 class="font-bold">Better Cables</h4> | |
| <p class="text-sm text-gray-600 mb-2">Easier to plug in</p> | |
| <button class="upgrade-btn bg-purple-600 hover:bg-purple-700 text-white text-sm py-1 px-3 rounded" data-cost="50" data-upgrade="cables"> | |
| Buy (50 XP) | |
| </button> | |
| </div> | |
| <div class="bg-white p-4 rounded-lg shadow"> | |
| <h4 class="font-bold">Color Coding</h4> | |
| <p class="text-sm text-gray-600 mb-2">Visual guides</p> | |
| <button class="upgrade-btn bg-purple-600 hover:bg-purple-700 text-white text-sm py-1 px-3 rounded" data-cost="100" data-upgrade="colors"> | |
| Buy (100 XP) | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Audio Elements --> | |
| <audio id="plugSound" src="https://assets.mixkit.co/sfx/preview/mixkit-arcade-game-jump-coin-216.mp3" preload="auto"></audio> | |
| <audio id="completeSound" src="https://assets.mixkit.co/sfx/preview/mixkit-achievement-bell-600.mp3" preload="auto"></audio> | |
| <audio id="levelUpSound" src="https://assets.mixkit.co/sfx/preview/mixkit-unlock-game-notification-253.mp3" preload="auto"></audio> | |
| <script> | |
| // Game State | |
| const gameState = { | |
| xp: 0, | |
| level: 1, | |
| xpToNextLevel: 100, | |
| tasksCompleted: 0, | |
| currentStreak: 0, | |
| upgrades: { | |
| cables: false, | |
| colors: false | |
| }, | |
| currentTask: 'plug' | |
| }; | |
| // DOM Elements | |
| const xpBar = document.getElementById('xp-bar'); | |
| const xpText = document.getElementById('xp-text'); | |
| const levelDisplay = document.getElementById('level'); | |
| const tasksCompletedDisplay = document.getElementById('tasks-completed'); | |
| const currentStreakDisplay = document.getElementById('current-streak'); | |
| const taskDescription = document.getElementById('task-description'); | |
| const taskContainer = document.getElementById('task-container'); | |
| const startTaskBtn = document.getElementById('start-task'); | |
| const computer = document.getElementById('computer'); | |
| const cable = document.getElementById('cable'); | |
| const plug = document.getElementById('plug'); | |
| const outlet = document.getElementById('outlet'); | |
| const upgradeButtons = document.querySelectorAll('.upgrade-btn'); | |
| // Audio Elements | |
| const plugSound = document.getElementById('plugSound'); | |
| const completeSound = document.getElementById('completeSound'); | |
| const levelUpSound = document.getElementById('levelUpSound'); | |
| // Game Variables | |
| let isDragging = false; | |
| let taskActive = false; | |
| let plugConnected = false; | |
| // Initialize game | |
| function initGame() { | |
| updateUI(); | |
| setupEventListeners(); | |
| } | |
| // Update all UI elements based on game state | |
| function updateUI() { | |
| xpBar.style.width = `${(gameState.xp / gameState.xpToNextLevel) * 100}%`; | |
| xpText.textContent = `${gameState.xp}/${gameState.xpToNextLevel} XP`; | |
| levelDisplay.textContent = gameState.level; | |
| tasksCompletedDisplay.textContent = gameState.tasksCompleted; | |
| currentStreakDisplay.textContent = gameState.currentStreak; | |
| // Update upgrade buttons | |
| upgradeButtons.forEach(btn => { | |
| const cost = parseInt(btn.dataset.cost); | |
| const upgrade = btn.dataset.upgrade; | |
| if (gameState.upgrades[upgrade]) { | |
| btn.disabled = true; | |
| btn.classList.remove('bg-purple-600', 'hover:bg-purple-700'); | |
| btn.classList.add('bg-gray-400', 'cursor-not-allowed'); | |
| btn.textContent = 'Purchased'; | |
| } else if (gameState.xp < cost) { | |
| btn.disabled = true; | |
| btn.classList.remove('bg-purple-600', 'hover:bg-purple-700'); | |
| btn.classList.add('bg-gray-400', 'cursor-not-allowed'); | |
| } else { | |
| btn.disabled = false; | |
| btn.classList.add('bg-purple-600', 'hover:bg-purple-700'); | |
| btn.classList.remove('bg-gray-400', 'cursor-not-allowed'); | |
| } | |
| }); | |
| } | |
| // Set up event listeners | |
| function setupEventListeners() { | |
| // Start task button | |
| startTaskBtn.addEventListener('click', startTask); | |
| // Plug drag events | |
| plug.addEventListener('mousedown', startDrag); | |
| document.addEventListener('mousemove', drag); | |
| document.addEventListener('mouseup', endDrag); | |
| // Upgrade buttons | |
| upgradeButtons.forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const cost = parseInt(this.dataset.cost); | |
| const upgrade = this.dataset.upgrade; | |
| if (gameState.xp >= cost && !gameState.upgrades[upgrade]) { | |
| gameState.xp -= cost; | |
| gameState.upgrades[upgrade] = true; | |
| if (upgrade === 'cables') { | |
| cable.classList.add('bg-green-500'); | |
| } else if (upgrade === 'colors') { | |
| outlet.classList.add('bg-red-400'); | |
| plug.classList.add('bg-yellow-400'); | |
| } | |
| updateUI(); | |
| } | |
| }); | |
| }); | |
| } | |
| // Start a new task | |
| function startTask() { | |
| if (taskActive) return; | |
| taskActive = true; | |
| plugConnected = false; | |
| startTaskBtn.disabled = true; | |
| startTaskBtn.classList.add('bg-gray-400', 'cursor-not-allowed'); | |
| startTaskBtn.classList.remove('bg-blue-600', 'hover:bg-blue-700'); | |
| // Reset plug position | |
| plug.style.left = 'calc(25% + 32px)'; | |
| plug.style.top = '50%'; | |
| cable.style.width = '32px'; | |
| taskDescription.textContent = "Drag the plug to the power outlet"; | |
| } | |
| // Drag functionality | |
| function startDrag(e) { | |
| if (!taskActive) return; | |
| isDragging = true; | |
| plug.style.cursor = 'grabbing'; | |
| e.preventDefault(); | |
| } | |
| function drag(e) { | |
| if (!isDragging || !taskActive) return; | |
| const gameArea = plug.parentElement; | |
| const rect = gameArea.getBoundingClientRect(); | |
| // Calculate position relative to game area | |
| let x = e.clientX - rect.left; | |
| let y = e.clientY - rect.top; | |
| // Constrain to game area | |
| x = Math.max(0, Math.min(x, rect.width)); | |
| y = Math.max(0, Math.min(y, rect.height)); | |
| // Update plug position | |
| plug.style.left = `${x}px`; | |
| plug.style.top = `${y}px`; | |
| // Update cable length | |
| const computerX = rect.width * 0.25; | |
| const computerY = rect.height * 0.5; | |
| const distance = Math.sqrt(Math.pow(x - computerX, 2) + Math.pow(y - computerY, 2)); | |
| cable.style.width = `${distance}px`; | |
| // Calculate angle | |
| const angle = Math.atan2(y - computerY, x - computerX) * (180 / Math.PI); | |
| cable.style.transform = `translate(-50%, -50%) rotate(${angle}deg)`; | |
| // Check if plug is near outlet | |
| const outletRect = outlet.getBoundingClientRect(); | |
| const plugRect = plug.getBoundingClientRect(); | |
| const outletCenter = { | |
| x: outletRect.left + outletRect.width / 2, | |
| y: outletRect.top + outletRect.height / 2 | |
| }; | |
| const plugCenter = { | |
| x: plugRect.left + plugRect.width / 2, | |
| y: plugRect.top + plugRect.height / 2 | |
| }; | |
| const distanceToOutlet = Math.sqrt( | |
| Math.pow(outletCenter.x - plugCenter.x, 2) + | |
| Math.pow(outletCenter.y - plugCenter.y, 2) | |
| ); | |
| if (distanceToOutlet < 30 && !plugConnected) { | |
| completeTask(); | |
| } | |
| } | |
| function endDrag() { | |
| isDragging = false; | |
| plug.style.cursor = 'grab'; | |
| } | |
| // Complete the current task | |
| function completeTask() { | |
| plugConnected = true; | |
| taskActive = false; | |
| // Visual feedback | |
| plug.classList.add('plug-success'); | |
| taskContainer.classList.add('task-complete'); | |
| plugSound.play(); | |
| // Update game state | |
| gameState.xp += 10 + (gameState.currentStreak * 2); | |
| gameState.tasksCompleted++; | |
| gameState.currentStreak++; | |
| // Check for level up | |
| if (gameState.xp >= gameState.xpToNextLevel) { | |
| levelUp(); | |
| } | |
| // Update UI | |
| updateUI(); | |
| // Reset after delay | |
| setTimeout(() => { | |
| plug.classList.remove('plug-success'); | |
| taskContainer.classList.remove('task-complete'); | |
| startTaskBtn.disabled = false; | |
| startTaskBtn.classList.remove('bg-gray-400', 'cursor-not-allowed'); | |
| startTaskBtn.classList.add('bg-blue-600', 'hover:bg-blue-700'); | |
| // Play complete sound | |
| completeSound.play(); | |
| // Shake computer for fun | |
| computer.classList.add('shake'); | |
| setTimeout(() => { | |
| computer.classList.remove('shake'); | |
| }, 500); | |
| // Change task for variety | |
| const tasks = [ | |
| "Plug in the monitor cable", | |
| "Connect the keyboard", | |
| "Attach the mouse cable", | |
| "Plug in the speakers" | |
| ]; | |
| taskDescription.textContent = tasks[Math.floor(Math.random() * tasks.length)]; | |
| }, 1000); | |
| } | |
| // Level up the player | |
| function levelUp() { | |
| gameState.level++; | |
| gameState.xp -= gameState.xpToNextLevel; | |
| gameState.xpToNextLevel = Math.floor(gameState.xpToNextLevel * 1.5); | |
| // Visual feedback | |
| levelUpSound.play(); | |
| levelDisplay.classList.add('shake'); | |
| setTimeout(() => { | |
| levelDisplay.classList.remove('shake'); | |
| }, 1000); | |
| } | |
| // Start the game | |
| initGame(); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=TheLandlineMan/tyler-it" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |