A Pen by mode-mercury on CodePen.
Created
June 8, 2025 02:05
-
-
Save mode-mercury/0ef6dbfe75a4f03cf0e0986beab9f992 to your computer and use it in GitHub Desktop.
Untitled
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>Time-Shredders: Lords of Radical History</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet"> | |
| <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --neon-blue: #00f3ff; | |
| --neon-purple: #bf00ff; | |
| --neon-pink: #ff00e5; | |
| --neon-green: #39ff14; | |
| --neon-green-bright: #5aff3d; | |
| --dark-bg: #05051a; | |
| --dark-blue: #0a0a20; | |
| --neon-yellow: #ffec00; | |
| --neon-orange: #ff8c00; | |
| --neon-orange-bright: #ffab44; | |
| --cyberpunk-red: #ff2a6d; | |
| --cyberpunk-red-bright: #ff5b8d; | |
| --cyberpunk-teal: #05d9e8; | |
| --timeline-ancient: #ffb347; | |
| --timeline-renaissance: #8a5a44; | |
| --timeline-modern: #555555; | |
| --timeline-future: #6b3fa0; | |
| --pixel-border: 4px; | |
| --glow-intensity: 12px; | |
| } | |
| body { | |
| font-family: 'Press Start 2P', cursive; | |
| background-color: var(--dark-bg); | |
| color: white; | |
| overflow-x: hidden; | |
| touch-action: manipulation; | |
| overscroll-behavior: none; | |
| -webkit-tap-highlight-color: transparent; | |
| background-image: | |
| radial-gradient(circle at 20% 30%, rgba(107, 63, 160, 0.15) 0%, transparent 50%), | |
| radial-gradient(circle at 80% 70%, rgba(191, 0, 255, 0.1) 0%, transparent 50%); | |
| } | |
| .retro-btn { | |
| background-color: #111; | |
| color: var(--neon-blue); | |
| border: 3px solid var(--neon-blue); | |
| padding: 12px 20px; | |
| font-family: 'Press Start 2P', cursive; | |
| text-transform: uppercase; | |
| cursor: pointer; | |
| position: relative; | |
| overflow: hidden; | |
| transition: all 0.2s; | |
| font-size: 12px; | |
| line-height: 1.2; | |
| z-index: 5; | |
| box-shadow: 0 0 var(--glow-intensity) var(--neon-blue); | |
| text-shadow: 0 0 5px var(--neon-blue); | |
| display: inline-block; | |
| width: auto; | |
| min-width: 200px; | |
| text-align: center; | |
| margin: 0.5rem; | |
| } | |
| .retro-btn::after { | |
| content: ''; | |
| position: absolute; | |
| top: -2px; | |
| left: -2px; | |
| right: -2px; | |
| bottom: -2px; | |
| border: 2px solid var(--neon-blue); | |
| opacity: 0; | |
| transition: all 0.3s; | |
| z-index: -1; | |
| } | |
| .retro-btn:hover, .retro-btn:active { | |
| background-color: var(--neon-blue); | |
| color: #000; | |
| box-shadow: 0 0 15px var(--neon-blue), 0 0 30px var(--neon-blue); | |
| transform: translateY(-2px) scale(1.05); | |
| text-shadow: none; | |
| } | |
| .retro-btn:hover::after, .retro-btn:active::after { | |
| opacity: 0.5; | |
| top: -6px; | |
| left: -6px; | |
| right: -6px; | |
| bottom: -6px; | |
| border-color: var(--neon-blue); | |
| } | |
| .retro-btn-green { | |
| color: var(--neon-green); | |
| border-color: var(--neon-green); | |
| box-shadow: 0 0 var(--glow-intensity) var(--neon-green); | |
| text-shadow: 0 0 5px var(--neon-green); | |
| } | |
| .retro-btn-green:hover, .retro-btn-green:active { | |
| background-color: var(--neon-green); | |
| box-shadow: 0 0 15px var(--neon-green), 0 0 30px var(--neon-green); | |
| } | |
| .retro-btn-pink { | |
| color: var(--neon-pink); | |
| border-color: var(--neon-pink); | |
| box-shadow: 0 0 var(--glow-intensity) var(--neon-pink); | |
| text-shadow: 0 0 5px var(--neon-pink); | |
| } | |
| .retro-btn-pink:hover, .retro-btn-pink:active { | |
| background-color: var(--neon-pink); | |
| box-shadow: 0 0 15px var(--neon-pink), 0 0 30px var(--neon-pink); | |
| } | |
| .retro-btn-orange { | |
| color: var(--neon-orange); | |
| border-color: var(--neon-orange); | |
| box-shadow: 0 0 var(--glow-intensity) var(--neon-orange); | |
| text-shadow: 0 0 5px var(--neon-orange); | |
| } | |
| .retro-btn-orange:hover, .retro-btn-orange:active { | |
| background-color: var(--neon-orange); | |
| box-shadow: 0 0 15px var(--neon-orange), 0 0 30px var(--neon-orange); | |
| } | |
| .retro-btn-purple { | |
| color: var(--neon-purple); | |
| border-color: var(--neon-purple); | |
| box-shadow: 0 0 var(--glow-intensity) var(--neon-purple); | |
| text-shadow: 0 0 5px var(--neon-purple); | |
| } | |
| .retro-btn-purple:hover, .retro-btn-purple:active { | |
| background-color: var(--neon-purple); | |
| box-shadow: 0 0 15px var(--neon-purple), 0 0 30px var(--neon-purple); | |
| } | |
| .pixel-border { | |
| position: relative; | |
| border: var(--pixel-border) solid var(--neon-blue); | |
| box-shadow: 0 0 10px var(--neon-blue), inset 0 0 10px var(--neon-blue); | |
| } | |
| .title-glow { | |
| text-shadow: 0 0 5px var(--neon-blue), 0 0 10px var(--neon-blue), 0 0 15px var(--neon-blue); | |
| animation: titlePulse 2s infinite alternate; | |
| } | |
| .title-glow-pink { | |
| text-shadow: 0 0 5px var(--neon-pink), 0 0 10px var(--neon-pink), 0 0 15px var(--neon-pink); | |
| animation: titlePulsePink 2s infinite alternate; | |
| } | |
| .title-glow-green { | |
| text-shadow: 0 0 5px var(--neon-green), 0 0 10px var(--neon-green), 0 0 15px var(--neon-green); | |
| animation: titlePulseGreen 2s infinite alternate; | |
| } | |
| .title-glow-purple { | |
| text-shadow: 0 0 5px var(--neon-purple), 0 0 10px var(--neon-purple), 0 0 15px var(--neon-purple); | |
| animation: titlePulsePurple 2s infinite alternate; | |
| } | |
| .glitch-text { | |
| position: relative; | |
| animation: glitch 3s infinite; | |
| } | |
| .character-card { | |
| background-color: rgba(0, 0, 0, 0.7); | |
| border: 2px solid var(--neon-purple); | |
| transition: all 0.3s; | |
| transform-style: preserve-3d; | |
| perspective: 1000px; | |
| border-radius: 8px; | |
| overflow: hidden; | |
| } | |
| .character-card:hover, .character-card.selected { | |
| border-color: var(--neon-pink); | |
| box-shadow: 0 0 15px var(--neon-pink); | |
| transform: translateY(-5px) rotateY(10deg); | |
| } | |
| .mission-card { | |
| background-color: rgba(0, 0, 0, 0.7); | |
| border: 2px solid var(--neon-green); | |
| transition: all 0.3s; | |
| border-radius: 8px; | |
| overflow: hidden; | |
| padding: 1rem; | |
| height: 100%; | |
| box-shadow: 0 0 8px var(--neon-green); | |
| } | |
| .mission-card:hover { | |
| border-color: var(--neon-green-bright); | |
| box-shadow: 0 0 15px var(--neon-green); | |
| transform: translateY(-5px); | |
| } | |
| .mission-card h3 { | |
| color: var(--neon-green); | |
| text-shadow: 0 0 5px var(--neon-green); | |
| font-size: 1.1rem; | |
| margin-bottom: 0.75rem; | |
| text-align: center; | |
| } | |
| .mission-card .mission-details { | |
| font-size: 0.7rem; | |
| color: white; | |
| margin-top: 0.5rem; | |
| } | |
| .mission-card .mission-objective { | |
| color: var(--neon-yellow); | |
| font-size: 0.7rem; | |
| margin-top: 0.5rem; | |
| } | |
| .mission-card .mission-difficulty { | |
| color: var(--neon-orange); | |
| font-size: 0.7rem; | |
| margin-top: 0.5rem; | |
| } | |
| .mission-card .mission-rewards { | |
| color: var(--cyberpunk-teal); | |
| font-size: 0.7rem; | |
| margin-top: 1rem; | |
| } | |
| .mission-image { | |
| width: 100%; | |
| height: 120px; | |
| display: block; | |
| margin: 0 auto 1rem; | |
| border: 2px solid var(--neon-green); | |
| border-radius: 4px; | |
| background-position: center; | |
| background-size: cover; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .mission-image::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(45deg, rgba(0,243,255,0.2), rgba(57,255,20,0.1), rgba(191,0,255,0.2)); | |
| pointer-events: none; | |
| } | |
| .scanline { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100vw; | |
| height: 100vh; | |
| background: linear-gradient(to bottom, | |
| rgba(255, 255, 255, 0) 0%, | |
| rgba(255, 255, 255, 0.03) 50%, | |
| rgba(255, 255, 255, 0) 100%); | |
| background-size: 100% 4px; | |
| pointer-events: none; | |
| z-index: 100; | |
| } | |
| .crt-effect { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100vw; | |
| height: 100vh; | |
| background: radial-gradient(ellipse at center, | |
| rgba(5, 5, 32, 0) 0%, | |
| rgba(5, 5, 32, 0.3) 80%, | |
| rgba(5, 5, 32, 0.6) 100%); | |
| pointer-events: none; | |
| z-index: 99; | |
| } | |
| .pixelated { | |
| image-rendering: pixelated; | |
| image-rendering: -moz-crisp-edges; | |
| image-rendering: crisp-edges; | |
| } | |
| /* Music controls */ | |
| .music-controls { | |
| position: fixed; | |
| top: 10px; | |
| right: 10px; | |
| z-index: 1000; | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .sound-btn { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50%; | |
| background-color: rgba(0,0,0,0.5); | |
| border: 2px solid var(--neon-blue); | |
| color: var(--neon-blue); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| font-size: 16px; | |
| box-shadow: 0 0 8px var(--neon-blue); | |
| transition: all 0.2s; | |
| } | |
| .sound-btn:hover, .sound-btn:active { | |
| transform: scale(1.1); | |
| box-shadow: 0 0 15px var(--neon-blue); | |
| } | |
| .sound-btn.muted { | |
| border-color: var(--cyberpunk-red); | |
| color: var(--cyberpunk-red); | |
| box-shadow: 0 0 8px var(--cyberpunk-red); | |
| } | |
| /* RPG Elements */ | |
| .stat-bar { | |
| height: 10px; | |
| background-color: #333; | |
| border: 1px solid var(--neon-green); | |
| border-radius: 5px; | |
| overflow: hidden; | |
| margin-bottom: 4px; | |
| } | |
| .stat-fill { | |
| height: 100%; | |
| background-color: var(--neon-green); | |
| position: relative; | |
| } | |
| .stat-fill::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); | |
| animation: shimmer 1.5s infinite; | |
| } | |
| @keyframes shimmer { | |
| 0% { transform: translateX(-100%); } | |
| 100% { transform: translateX(100%); } | |
| } | |
| .stat-text { | |
| font-size: 10px; | |
| color: var(--neon-green); | |
| margin-bottom: 2px; | |
| } | |
| .xp-bar { | |
| height: 6px; | |
| background-color: #333; | |
| border: 1px solid var(--neon-yellow); | |
| border-radius: 3px; | |
| overflow: hidden; | |
| } | |
| .xp-fill { | |
| height: 100%; | |
| background-color: var(--neon-yellow); | |
| position: relative; | |
| } | |
| .xp-fill::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); | |
| animation: shimmer 1.5s infinite; | |
| } | |
| /* Intro screen */ | |
| .intro-container { | |
| perspective: 400px; | |
| overflow: hidden; | |
| position: relative; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .intro-text { | |
| position: absolute; | |
| top: 100%; | |
| left: 0; | |
| width: 100%; | |
| font-size: 16px; | |
| text-align: center; | |
| transform-origin: 50% 100%; | |
| transform: rotateX(25deg); | |
| line-height: 1.5; | |
| color: var(--neon-yellow); | |
| animation: scrollText 60s linear infinite; | |
| } | |
| @keyframes scrollText { | |
| 0% { top: 100%; } | |
| 100% { top: -300%; } | |
| } | |
| .start-prompt { | |
| position: absolute; | |
| bottom: 20%; | |
| left: 0; | |
| width: 100%; | |
| text-align: center; | |
| animation: blink 1s infinite; | |
| color: var(--neon-green); | |
| z-index: 10; | |
| } | |
| @keyframes blink { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0; } | |
| } | |
| .grid-container { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); | |
| gap: 20px; | |
| padding: 0 1rem; | |
| width: 100%; | |
| } | |
| .mission-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); | |
| gap: 20px; | |
| padding: 0 1rem; | |
| width: 100%; | |
| } | |
| .button-container { | |
| display: flex; | |
| justify-content: center; | |
| flex-wrap: wrap; | |
| gap: 10px; | |
| margin-top: 1.5rem; | |
| width: 100%; | |
| } | |
| /* Optimize for mobile devices */ | |
| @media (max-width: 640px) { | |
| .retro-btn { | |
| padding: 10px 16px; | |
| font-size: 10px; | |
| width: 100%; | |
| max-width: 250px; | |
| margin: 0.25rem auto; | |
| } | |
| .intro-text { | |
| font-size: 14px; | |
| } | |
| .grid-container, .mission-grid { | |
| grid-template-columns: 1fr; | |
| padding: 0 10px; | |
| } | |
| .title-glow { | |
| font-size: 1.2rem; | |
| } | |
| .music-controls { | |
| top: 5px; | |
| right: 5px; | |
| } | |
| .sound-btn { | |
| width: 30px; | |
| height: 30px; | |
| font-size: 14px; | |
| } | |
| } | |
| @keyframes titlePulse { | |
| 0% { text-shadow: 0 0 5px var(--neon-blue), 0 0 10px var(--neon-blue); } | |
| 100% { text-shadow: 0 0 10px var(--neon-blue), 0 0 20px var(--neon-blue), 0 0 30px var(--neon-blue); } | |
| } | |
| @keyframes titlePulsePink { | |
| 0% { text-shadow: 0 0 5px var(--neon-pink), 0 0 10px var(--neon-pink); } | |
| 100% { text-shadow: 0 0 10px var(--neon-pink), 0 0 20px var(--neon-pink), 0 0 30px var(--neon-pink); } | |
| } | |
| @keyframes titlePulseGreen { | |
| 0% { text-shadow: 0 0 5px var(--neon-green), 0 0 10px var(--neon-green); } | |
| 100% { text-shadow: 0 0 10px var(--neon-green), 0 0 20px var(--neon-green), 0 0 30px var(--neon-green); } | |
| } | |
| @keyframes titlePulsePurple { | |
| 0% { text-shadow: 0 0 5px var(--neon-purple), 0 0 10px var(--neon-purple); } | |
| 100% { text-shadow: 0 0 10px var(--neon-purple), 0 0 20px var(--neon-purple), 0 0 30px var(--neon-purple); } | |
| } | |
| @keyframes glitch { | |
| 0% { transform: translate(0); } | |
| 20% { transform: translate(-2px, 2px); } | |
| 40% { transform: translate(-2px, -2px); } | |
| 60% { transform: translate(2px, 2px); } | |
| 80% { transform: translate(2px, -2px); } | |
| 100% { transform: translate(0); } | |
| } | |
| /* Futuristic elements */ | |
| .neo-container { | |
| border: 1px solid var(--neon-blue); | |
| background-color: rgba(0, 243, 255, 0.05); | |
| border-radius: 8px; | |
| padding: 1.5rem; | |
| box-shadow: 0 0 15px rgba(0, 243, 255, 0.2); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .neo-container::before { | |
| content: ''; | |
| position: absolute; | |
| top: -50%; | |
| left: -50%; | |
| width: 200%; | |
| height: 200%; | |
| background: linear-gradient( | |
| 45deg, | |
| transparent 0%, | |
| rgba(0, 243, 255, 0.05) 30%, | |
| rgba(0, 243, 255, 0.1) 47%, | |
| rgba(0, 243, 255, 0.05) 50%, | |
| transparent 100% | |
| ); | |
| transform: rotate(45deg); | |
| animation: neoGlow 8s linear infinite; | |
| } | |
| @keyframes neoGlow { | |
| 0% { transform: translateX(-100%) rotate(45deg); } | |
| 100% { transform: translateX(100%) rotate(45deg); } | |
| } | |
| .pixel-backdrop { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| pointer-events: none; | |
| z-index: -1; | |
| opacity: 0.2; | |
| background-image: | |
| linear-gradient(90deg, var(--neon-purple) 1px, transparent 1px), | |
| linear-gradient(0deg, var(--neon-blue) 1px, transparent 1px); | |
| background-size: 20px 20px; | |
| transform: perspective(500px) rotateX(60deg); | |
| transform-origin: top; | |
| animation: gridMove 20s linear infinite; | |
| } | |
| @keyframes gridMove { | |
| 0% { background-position: 0 0; } | |
| 100% { background-position: 0 100%; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- CRT effects --> | |
| <div class="scanline"></div> | |
| <div class="crt-effect"></div> | |
| <div class="pixel-backdrop"></div> | |
| <!-- Music Controls --> | |
| <div class="music-controls"> | |
| <button id="musicToggle" class="sound-btn" title="Toggle Music"> | |
| <span>♪</span> | |
| </button> | |
| <button id="soundToggle" class="sound-btn" title="Toggle Sound Effects"> | |
| <span>🔊</span> | |
| </button> | |
| </div> | |
| <!-- Title Screen --> | |
| <div id="title-screen" class="game-screen min-h-screen flex flex-col items-center justify-center p-4"> | |
| <div class="text-center"> | |
| <h1 class="text-xl md:text-3xl mb-4 title-glow text-blue-400 glitch-text tracking-wider"> | |
| TIME-SHREDDERS | |
| </h1> | |
| <h1 class="text-2xl md:text-4xl mb-2 title-glow-pink text-purple-400 glitch-text tracking-wider"> | |
| LORDS OF RADICAL HISTORY | |
| </h1> | |
| <h2 class="text-xl md:text-2xl mb-6 title-glow-green text-pink-400 glitch-text tracking-wide"> | |
| MAKING HISTORY MY BITCH SINCE THE BIG BANG | |
| </h2> | |
| <div class="mb-6 mt-4 pixel-art-container"> | |
| <div class="w-64 h-64 mx-auto mb-4 pixel-border overflow-hidden"> | |
| <canvas id="pixel-canvas" width="128" height="128" class="w-full h-full pixelated"></canvas> | |
| </div> | |
| </div> | |
| <div class="space-y-4 mt-6 flex flex-col items-center"> | |
| <button id="startGameButton" class="retro-btn retro-btn-green w-64 mx-auto block"> | |
| START GAME | |
| </button> | |
| <button id="controlsButton" class="retro-btn retro-btn-pink w-64 mx-auto block"> | |
| CONTROLS | |
| </button> | |
| <button id="skillTreePreviewButton" class="retro-btn retro-btn-purple w-64 mx-auto block"> | |
| TRICK PREVIEW | |
| </button> | |
| </div> | |
| <div class="text-xs md:text-sm mt-6 text-gray-400"> | |
| © 20XX RADICAL TEMPORAL SKATE COLLECTIVE | |
| </div> | |
| </div> | |
| <!-- Controls overlay --> | |
| <div id="controls-popup" class="controls-overlay p-4 max-w-md mx-auto fixed inset-0 bg-black bg-opacity-90 z-50 flex flex-col items-center justify-center hidden"> | |
| <div class="bg-black border-2 border-blue-400 p-4 max-w-md w-full"> | |
| <h3 class="text-xl text-center mb-4 text-blue-400">CONTROLS</h3> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div> | |
| <p class="mb-2 text-pink-400">D-PAD / ARROWS</p> | |
| <p class="text-sm mb-4">Move character</p> | |
| <p class="mb-2 text-pink-400">A BUTTON</p> | |
| <p class="text-sm mb-4">Quantum Jump / Confirm</p> | |
| <p class="mb-2 text-pink-400">B BUTTON</p> | |
| <p class="text-sm mb-4">Paradox Trick / Cancel</p> | |
| </div> | |
| <div> | |
| <p class="mb-2 text-pink-400">Q KEY</p> | |
| <p class="text-sm mb-4">Quantum Flow (slow time)</p> | |
| <p class="mb-2 text-pink-400">T KEY</p> | |
| <p class="text-sm mb-4">Timeline Weaving</p> | |
| <p class="mb-2 text-pink-400">P KEY</p> | |
| <p class="text-sm">Activate Paradox Power</p> | |
| </div> | |
| </div> | |
| <p class="text-center text-sm my-4 text-green-400">SWIPE UP FOR QUANTUM OLLIE<br>SWIPE DOWN FOR PARADOX GRIND</p> | |
| <button id="closeControlsButton" class="retro-btn retro-btn-pink w-48 mx-auto block mt-6"> | |
| CLOSE | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Trick Preview --> | |
| <div id="skillTreePreview" class="controls-overlay p-4 max-w-md mx-auto fixed inset-0 bg-black bg-opacity-90 z-50 flex flex-col items-center justify-center hidden"> | |
| <div class="bg-black border-2 border-purple-400 p-4 max-w-md w-full"> | |
| <h3 class="text-xl text-center mb-4 text-purple-400">QUANTUM TRICKS</h3> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div class="border border-blue-400 p-2"> | |
| <p class="text-blue-400 mb-2 text-sm">REALITY WARPERS</p> | |
| <div class="text-xs text-gray-200"> | |
| <p>• Quantum Cancel</p> | |
| <p>• Timeline Weaving</p> | |
| <p>• Grandfather Paradox Pop-shove it</p> | |
| </div> | |
| </div> | |
| <div class="border border-green-400 p-2"> | |
| <p class="text-green-400 mb-2 text-sm">TIMELINE TRICKS</p> | |
| <div class="text-xs text-gray-200"> | |
| <p>• Reality Edge Grind</p> | |
| <p>• Schrödinger's Kickflip</p> | |
| <p>• Fourth Dimensional Fingerflip</p> | |
| </div> | |
| </div> | |
| <div class="border border-yellow-400 p-2"> | |
| <p class="text-yellow-400 mb-2 text-sm">PARADOX POWER</p> | |
| <div class="text-xs text-gray-200"> | |
| <p>• Temporal Rewind</p> | |
| <p>• Reality Glitch</p> | |
| <p>• Butterfly Effect</p> | |
| </div> | |
| </div> | |
| <div class="border border-pink-400 p-2"> | |
| <p class="text-pink-400 mb-2 text-sm">SPECIAL MOVES</p> | |
| <div class="text-xs text-gray-200"> | |
| <p>• Big Bang Boneless</p> | |
| <p>• Paradox Push</p> | |
| <p>• Paradox Burst</p> | |
| </div> | |
| </div> | |
| </div> | |
| <button id="closeSkillPreviewButton" class="retro-btn retro-btn-purple w-48 mx-auto block mt-6"> | |
| CLOSE | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Intro Screen with Scrolling Text --> | |
| <div id="intro-screen" class="game-screen min-h-screen flex flex-col relative hidden"> | |
| <div class="intro-container"> | |
| <div class="intro-text"> | |
| <p class="mb-8">EPISODE 1: THE RENAISSANCE GONE WRONG</p> | |
| <p class="mb-8">2069: Neo-Tokyo lies in ruins. The spacetime continuum has been shredded harder than a half-pipe at the X-Games.</p> | |
| <p class="mb-8">The Time Cops thought they could regulate the timeline. The fools. Their meddling triggered a catastrophic paradox cascade, turning history into a chaotic mash-up of anachronistic nonsense.</p> | |
| <p class="mb-8">But there's still hope. The brilliantly unhinged Dr. Jared "Ollie" Chronos has developed the Q-Board 5000--a skateboard that can grind on the rails of reality itself.</p> | |
| <p class="mb-8">Recruiting history's most radical misfits--TRASH, the anti-establishment punk with a doctorate in particle physics; GHOST KIM, who can phase through solid matter and time barriers; and DATA, a hyper-intelligent quantum corgi--they formed the TIME-SHREDDERS: LORDS OF RADICAL HISTORY.</p> | |
| <p class="mb-8">Their mission: skate through fractured timelines, performing historically impossible tricks to restore the spacetime continuum, and look totally sick while doing it.</p> | |
| <p class="mb-8">First target: Renaissance Italy, 1500. Leonardo da Vinci has stolen your skateboard tech to build a flying machine, Michelangelo is tagging the Sistine Chapel with spray paint, and Pope Julius II is hosting underground breakdance battles. And don't even get us started on that robot-enhanced Mona Lisa.</p> | |
| <p class="mb-8">PRESS START OR TOUCH SCREEN TO BEGIN</p> | |
| </div> | |
| </div> | |
| <div class="start-prompt"> | |
| <p>PRESS START OR TOUCH SCREEN</p> | |
| </div> | |
| </div> | |
| <!-- Main Menu --> | |
| <div id="main-screen" class="game-screen min-h-screen flex flex-col p-4 hidden"> | |
| <h1 class="text-xl md:text-3xl text-center title-glow-purple text-blue-400 mb-6 mt-4"> | |
| TIME-SHREDDERS: MAIN MENU | |
| </h1> | |
| <div class="flex-grow flex flex-col items-center justify-center"> | |
| <div class="neo-container mb-6 w-full max-w-md"> | |
| <div class="button-container"> | |
| <button id="selectCharacterButton" class="retro-btn retro-btn-green"> | |
| SELECT SKATER | |
| </button> | |
| <button id="selectMissionButton" class="retro-btn retro-btn-pink"> | |
| SELECT TIMELINE | |
| </button> | |
| <button id="skillTreeButton" class="retro-btn retro-btn-purple"> | |
| QUANTUM SKILLS | |
| </button> | |
| <button id="inventoryButton" class="retro-btn retro-btn-blue"> | |
| TEMPORAL GEAR | |
| </button> | |
| <button id="questLogButton" class="retro-btn retro-btn-orange"> | |
| PARADOX LOG | |
| </button> | |
| <button id="shopButton" class="retro-btn retro-btn-green"> | |
| CHRONO SHOP | |
| </button> | |
| <button id="backToTitleButton" class="retro-btn"> | |
| BACK TO TITLE | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Character Stats Display --> | |
| <div class="mt-4 mb-2 border-2 border-blue-400 p-3 mx-auto w-full max-w-md neo-container"> | |
| <h3 class="text-center text-blue-400 mb-3 text-md">SKATER STATS</h3> | |
| <div class="grid grid-cols-2 gap-2"> | |
| <div> | |
| <p class="text-xs text-blue-400 mb-1">LEVEL: <span id="playerLevel">1</span></p> | |
| <div class="flex items-center mb-1"> | |
| <p class="text-xs text-yellow-400 mr-2">XP:</p> | |
| <div class="xp-bar w-full"> | |
| <div class="xp-fill" style="width: 25%"></div> | |
| </div> | |
| </div> | |
| <p class="text-xs text-green-400 mb-1">STYLE POINTS: <span id="stylePoints">0</span></p> | |
| </div> | |
| <div> | |
| <div class="flex items-center"> | |
| <p class="text-xs text-purple-400 mr-2 w-16">TECH:</p> | |
| <div class="stat-bar w-full"> | |
| <div class="stat-fill" style="width: 65%"></div> | |
| </div> | |
| </div> | |
| <div class="flex items-center"> | |
| <p class="text-xs text-purple-400 mr-2 w-16">QUANTUM:</p> | |
| <div class="stat-bar w-full"> | |
| <div class="stat-fill" style="width: 40%"></div> | |
| </div> | |
| </div> | |
| <div class="flex items-center"> | |
| <p class="text-xs text-purple-400 mr-2 w-16">PARADOX:</p> | |
| <div class="stat-bar w-full"> | |
| <div class="stat-fill" style="width: 30%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Character Select --> | |
| <div id="character-select" class="game-screen min-h-screen p-4 hidden"> | |
| <h1 class="text-xl md:text-3xl text-center title-glow-pink text-purple-400 mb-4 mt-2"> | |
| SELECT YOUR TIME-SHREDDER | |
| </h1> | |
| <div class="grid-container"> | |
| <!-- Character 1 --> | |
| <div class="character-card p-4 rounded" id="sammy-card" data-char="sammy"> | |
| <h3 class="text-md md:text-lg text-center mb-2 text-blue-400">DR. JARED "OLLIE" CHRONOS</h3> | |
| <div class="h-32 w-32 mx-auto mb-2 overflow-hidden pixel-border"> | |
| <canvas class="character-pixel-art w-full h-full pixelated" data-char="sammy" width="64" height="64"></canvas> | |
| </div> | |
| <!-- RPG Character Stats --> | |
| <div class="mb-2"> | |
| <div class="flex justify-between"> | |
| <p class="text-xs text-blue-400">LVL 5</p> | |
| <p class="text-xs text-yellow-400">STREET/TECH</p> | |
| </div> | |
| <div class="stat-text flex justify-between"> | |
| <span>SPEED</span> | |
| <span>★★★☆☆</span> | |
| </div> | |
| <div class="stat-bar"> | |
| <div class="stat-fill" style="width: 60%"></div> | |
| </div> | |
| <div class="stat-text flex justify-between"> | |
| <span>TECH</span> | |
| <span>★★★★★</span> | |
| </div> | |
| <div class="stat-bar"> | |
| <div class="stat-fill" style="width: 90%"></div> | |
| </div> | |
| <div class="stat-text flex justify-between"> | |
| <span>QUANTUM</span> | |
| <span>★★★★☆</span> | |
| </div> | |
| <div class="stat-bar"> | |
| <div class="stat-fill" style="width: 75%"></div> | |
| </div> | |
| </div> | |
| <p class="text-xs mb-2 text-gray-300">Special: Schrödinger's Kickflip</p> | |
| <p class="text-xs mb-2 text-gray-300">Skill: Lands tricks in multiple dimensions simultaneously</p> | |
| <button class="retro-btn w-full character-select-btn" data-char="sammy">SELECT</button> | |
| </div> | |
| <!-- Character 2 --> | |
| <div class="character-card p-4 rounded" id="ghost-card" data-char="ghost"> | |
| <h3 class="text-md md:text-lg text-center mb-2 text-blue-400">GHOST KIM</h3> | |
| <div class="h-32 w-32 mx-auto mb-2 overflow-hidden pixel-border"> | |
| <canvas class="character-pixel-art w-full h-full pixelated" data-char="ghost" width="64" height="64"></canvas> | |
| </div> | |
| <div class="mb-2"> | |
| <div class="flex justify-between"> | |
| <p class="text-xs text-blue-400">LVL 4</p> | |
| <p class="text-xs text-yellow-400">STEALTH/PHASE</p> | |
| </div> | |
| <div class="stat-text flex justify-between"> | |
| <span>SPEED</span> | |
| <span>★★☆☆☆</span> | |
| </div> | |
| <div class="stat-bar"> | |
| <div class="stat-fill" style="width: 40%"></div> | |
| </div> | |
| <div class="stat-text flex justify-between"> | |
| <span>STEALTH</span> | |
| <span>★★★★★</span> | |
| </div> | |
| <div class="stat-bar"> | |
| <div class="stat-fill" style="width: 95%"></div> | |
| </div> | |
| <div class="stat-text flex justify-between"> | |
| <span>QUANTUM</span> | |
| <span>★★★☆☆</span> | |
| </div> | |
| <div class="stat-bar"> | |
| <div class="stat-fill" style="width: 60%"></div> | |
| </div> | |
| </div> | |
| <p class="text-xs mb-2 text-gray-300">Special: Reality Phase</p> | |
| <p class="text-xs mb-2 text-gray-300">Skill: Grinds through solid objects and temporal barriers</p> | |
| <button class="retro-btn w-full character-select-btn" data-char="ghost">SELECT</button> | |
| </div> | |
| </div> | |
| <div class="button-container"> | |
| <button id="charSelectBackButton" class="retro-btn retro-btn-orange">BACK</button> | |
| <button id="startMission1Button" class="retro-btn retro-btn-green">START MISSION 1</button> | |
| </div> | |
| </div> | |
| <!-- Mission Select (Timeline Selection) --> | |
| <div id="mission-select" class="game-screen min-h-screen p-4 hidden"> | |
| <h1 class="text-xl md:text-3xl text-center title-glow-green text-green-400 mb-4 mt-2"> | |
| SELECT TIMELINE MISSION | |
| </h1> | |
| <div class="mission-grid"> | |
| <!-- Mission 1 --> | |
| <div class="mission-card"> | |
| <h3>THE RENAISSANCE GONE WRONG</h3> | |
| <div class="mission-image" style="background-color: var(--timeline-renaissance)"></div> | |
| <div class="mission-details"> | |
| <div class="mission-objective">• Tag the Sistine Chapel</div> | |
| <div class="mission-objective">• Retrieve your board from da Vinci</div> | |
| <div class="mission-objective">• Stop the pope's breakdance tournament</div> | |
| <div class="mission-difficulty">Difficulty: ★★☆☆☆</div> | |
| <div class="mission-rewards">Rewards: 500 XP, Schrödinger's Kickflip</div> | |
| </div> | |
| <button class="retro-btn retro-btn-green w-full mt-4">SELECT</button> | |
| </div> | |
| <!-- Mission 2 --> | |
| <div class="mission-card"> | |
| <h3>ANCIENT EGYPT X-TREME</h3> | |
| <div class="mission-image" style="background-color: var(--timeline-ancient)"></div> | |
| <div class="mission-details"> | |
| <div class="mission-objective">• Convert pyramids into epic half-pipes</div> | |
| <div class="mission-objective">• Teach Cleopatra sick tricks</div> | |
| <div class="mission-objective">• Survive the Pharaoh Tony Hawk Tournament</div> | |
| <div class="mission-difficulty">Difficulty: ★★★☆☆</div> | |
| <div class="mission-rewards">Rewards: 750 XP, Sphinx Grind</div> | |
| </div> | |
| <button class="retro-btn w-full mt-4" disabled style="opacity: 0.5">LOCKED</button> | |
| </div> | |
| <!-- Mission 3 --> | |
| <div class="mission-card"> | |
| <h3>WWI: RADICAL WARFARE</h3> | |
| <div class="mission-image" style="background-color: var(--timeline-modern)"></div> | |
| <div class="mission-details"> | |
| <div class="mission-objective">• Infiltrate Kaiser's skate bunker</div> | |
| <div class="mission-objective">• Witness Franz Ferdinand's last trick</div> | |
| <div class="mission-objective">• Convert trenches into gnarly snake runs</div> | |
| <div class="mission-difficulty">Difficulty: ★★★★☆</div> | |
| <div class="mission-rewards">Rewards: 1000 XP, Trench Grind</div> | |
| </div> | |
| <button class="retro-btn w-full mt-4" disabled style="opacity: 0.5">LOCKED</button> | |
| </div> | |
| <!-- Mission 4 --> | |
| <div class="mission-card"> | |
| <h3>BIG BANG BONELESS</h3> | |
| <div class="mission-image" style="background-color: var(--timeline-future)"></div> | |
| <div class="mission-details"> | |
| <div class="mission-objective">• Perform the Big Bang Boneless</div> | |
| <div class="mission-objective">• Avoid temporal paradox monsters</div> | |
| <div class="mission-objective">• Don't become your own grandparent</div> | |
| <div class="mission-difficulty">Difficulty: ★★★★★</div> | |
| <div class="mission-rewards">Rewards: 1500 XP, Cosmic Kickflip</div> | |
| </div> | |
| <button class="retro-btn w-full mt-4" disabled style="opacity: 0.5">LOCKED</button> | |
| </div> | |
| </div> | |
| <div class="button-container"> | |
| <button id="missionSelectBackButton" class="retro-btn retro-btn-orange">BACK TO MENU</button> | |
| </div> | |
| </div> | |
| <!-- Loading tip --> | |
| <div id="loading-tip" class="fixed bottom-5 left-5 bg-black bg-opacity-80 border-2 border-blue-400 p-3 z-50 hidden text-xs text-blue-400 max-w-xs"> | |
| TIP: Using Quantum Flow (Q key) slows time but consumes Paradox Power! | |
| </div> | |
| <script> | |
| // Debug flags | |
| const DEBUG = true; | |
| const logScreenChanges = true; | |
| // Initialize variables | |
| let selectedCharacter = 'sammy'; | |
| let selectedLevel = 1; | |
| let musicMuted = false; | |
| let soundMuted = false; | |
| let currentMusic = null; | |
| // Wait for DOM content to be fully loaded | |
| document.addEventListener('DOMContentLoaded', function() { | |
| log("DOM fully loaded - initializing game"); | |
| // Create the pixel art for title screen | |
| drawTitlePixelArt(); | |
| // Add navigation listeners | |
| setupEventListeners(); | |
| // Show a random loading tip | |
| showRandomLoadingTip(); | |
| // Log detection of key elements | |
| logElementStatus('startGameButton'); | |
| logElementStatus('intro-screen'); | |
| logElementStatus('main-screen'); | |
| logElementStatus('character-select'); | |
| logElementStatus('mission-select'); | |
| }); | |
| function log(message) { | |
| if (DEBUG) { | |
| console.log(`[TimeShredders] ${message}`); | |
| } | |
| } | |
| function logElementStatus(elementId) { | |
| const element = document.getElementById(elementId); | |
| log(`Element "${elementId}": ${element ? 'FOUND' : 'NOT FOUND'}`); | |
| } | |
| // Show a screen by ID, hiding all others | |
| function showScreen(screenId) { | |
| const screens = document.querySelectorAll('.game-screen'); | |
| // Hide all screens first | |
| screens.forEach(screen => { | |
| screen.style.display = 'none'; | |
| log(`Hidden screen: ${screen.id}`); | |
| }); | |
| // Show the requested screen | |
| const targetScreen = document.getElementById(screenId); | |
| if (targetScreen) { | |
| targetScreen.style.display = 'flex'; | |
| if (logScreenChanges) { | |
| log(`Showing screen: ${screenId}`); | |
| } | |
| } else { | |
| console.error(`Screen not found: ${screenId}`); | |
| } | |
| } | |
| // Setup main event listeners | |
| function setupEventListeners() { | |
| log("Setting up event listeners"); | |
| // Title Screen - Start Game Button | |
| attachClickHandler('startGameButton', function() { | |
| log("Start Game button clicked"); | |
| showScreen('intro-screen'); | |
| playSound('start'); | |
| }); | |
| // Controls Button | |
| attachClickHandler('controlsButton', function() { | |
| log("Controls button clicked"); | |
| document.getElementById('controls-popup').style.display = 'flex'; | |
| playSound('menuSelect'); | |
| }); | |
| // Close Controls Button | |
| attachClickHandler('closeControlsButton', function() { | |
| log("Close Controls button clicked"); | |
| document.getElementById('controls-popup').style.display = 'none'; | |
| playSound('menuSelect'); | |
| }); | |
| // Skill Tree Preview Button | |
| attachClickHandler('skillTreePreviewButton', function() { | |
| log("Skill Tree Preview button clicked"); | |
| document.getElementById('skillTreePreview').style.display = 'flex'; | |
| playSound('menuSelect'); | |
| }); | |
| // Close Skill Tree Preview Button | |
| attachClickHandler('closeSkillPreviewButton', function() { | |
| log("Close Skill Tree Preview button clicked"); | |
| document.getElementById('skillTreePreview').style.display = 'none'; | |
| playSound('menuSelect'); | |
| }); | |
| // Intro Screen Click | |
| attachClickHandler('intro-screen', function() { | |
| log("Intro screen clicked"); | |
| showScreen('main-screen'); | |
| playSound('menuSelect'); | |
| }); | |
| // Main Menu Buttons | |
| attachClickHandler('selectCharacterButton', function() { | |
| log("Select Character button clicked"); | |
| showScreen('character-select'); | |
| drawCharacterPixelArt(); | |
| playSound('menuSelect'); | |
| }); | |
| attachClickHandler('selectMissionButton', function() { | |
| log("Select Mission button clicked"); | |
| showScreen('mission-select'); | |
| playSound('menuSelect'); | |
| }); | |
| attachClickHandler('backToTitleButton', function() { | |
| log("Back to Title button clicked"); | |
| showScreen('title-screen'); | |
| playSound('menuSelect'); | |
| }); | |
| // Character Select Screen | |
| attachClickHandler('charSelectBackButton', function() { | |
| log("Character Select Back button clicked"); | |
| showScreen('main-screen'); | |
| playSound('menuSelect'); | |
| }); | |
| // Mission Select Screen | |
| attachClickHandler('missionSelectBackButton', function() { | |
| log("Mission Select Back button clicked"); | |
| showScreen('main-screen'); | |
| playSound('menuSelect'); | |
| }); | |
| // Sound Controls | |
| attachClickHandler('musicToggle', function() { | |
| musicMuted = !musicMuted; | |
| this.classList.toggle('muted'); | |
| log(`Music ${musicMuted ? 'muted' : 'unmuted'}`); | |
| }); | |
| attachClickHandler('soundToggle', function() { | |
| soundMuted = !soundMuted; | |
| this.classList.toggle('muted'); | |
| log(`Sound effects ${soundMuted ? 'muted' : 'unmuted'}`); | |
| }); | |
| // Character selection | |
| const characterButtons = document.querySelectorAll('.character-select-btn'); | |
| characterButtons.forEach(button => { | |
| button.addEventListener('click', function() { | |
| const char = this.getAttribute('data-char'); | |
| selectCharacter(char); | |
| playSound('rpgConfirm'); | |
| }); | |
| }); | |
| } | |
| // Utility to safely attach click handlers | |
| function attachClickHandler(elementId, handler) { | |
| const element = document.getElementById(elementId); | |
| if (element) { | |
| element.addEventListener('click', handler); | |
| log(`Click handler attached to ${elementId}`); | |
| } else { | |
| console.error(`Failed to attach click handler - element not found: ${elementId}`); | |
| } | |
| } | |
| // Play sound effect (simplified for CodePen) | |
| function playSound(soundName) { | |
| if (!soundMuted) { | |
| log(`Playing sound: ${soundName}`); | |
| } | |
| } | |
| // Draw the pixel art on the title screen with enhanced visuals | |
| function drawTitlePixelArt() { | |
| const canvas = document.getElementById('pixel-canvas'); | |
| if (!canvas) { | |
| console.error("Pixel canvas not found"); | |
| return; | |
| } | |
| const ctx = canvas.getContext('2d'); | |
| const width = canvas.width; | |
| const height = canvas.height; | |
| // Clear canvas | |
| ctx.clearRect(0, 0, width, height); | |
| // Draw a more vibrant background | |
| const gradient = ctx.createRadialGradient(width/2, height/2, 10, width/2, height/2, width/2); | |
| gradient.addColorStop(0, '#390067'); | |
| gradient.addColorStop(0.7, '#05051a'); | |
| gradient.addColorStop(1, '#000'); | |
| ctx.fillStyle = gradient; | |
| ctx.fillRect(0, 0, width, height); | |
| // Draw cool grid lines | |
| ctx.strokeStyle = 'rgba(57, 255, 20, 0.3)'; | |
| ctx.lineWidth = 1; | |
| // Horizontal grid lines | |
| for (let y = 0; y < height; y += 10) { | |
| ctx.beginPath(); | |
| ctx.moveTo(0, y); | |
| ctx.lineTo(width, y); | |
| ctx.stroke(); | |
| } | |
| // Vertical grid lines | |
| for (let x = 0; x < width; x += 10) { | |
| ctx.beginPath(); | |
| ctx.moveTo(x, 0); | |
| ctx.lineTo(x, height); | |
| ctx.stroke(); | |
| } | |
| // Draw a cool skateboard | |
| // Board base (with gradient) | |
| const boardGradient = ctx.createLinearGradient(width/2 - 30, height/2, width/2 + 30, height/2); | |
| boardGradient.addColorStop(0, '#bf00ff'); | |
| boardGradient.addColorStop(0.5, '#ff00e5'); | |
| boardGradient.addColorStop(1, '#bf00ff'); | |
| ctx.fillStyle = boardGradient; | |
| ctx.fillRect(width/2 - 30, height/2, 60, 12); | |
| // Cool board design | |
| ctx.fillStyle = "#000"; | |
| ctx.fillRect(width/2 - 25, height/2 + 2, 50, 8); | |
| // Neon design stripes | |
| ctx.fillStyle = "#39ff14"; | |
| ctx.fillRect(width/2 - 23, height/2 + 4, 46, 1); | |
| ctx.fillRect(width/2 - 23, height/2 + 7, 46, 1); | |
| // Wheel base | |
| ctx.fillStyle = "#333"; | |
| ctx.fillRect(width/2 - 25, height/2 + 12, 10, 2); | |
| ctx.fillRect(width/2 + 15, height/2 + 12, 10, 2); | |
| // Wheels with glow | |
| ctx.shadowColor = "#00f3ff"; | |
| ctx.shadowBlur = 10; | |
| ctx.fillStyle = "#00f3ff"; | |
| ctx.fillRect(width/2 - 25, height/2 + 14, 10, 10); | |
| ctx.fillRect(width/2 + 15, height/2 + 14, 10, 10); | |
| ctx.shadowBlur = 0; | |
| // Cool TIME SHRED text with outlines | |
| ctx.shadowColor = "#ff00e5"; | |
| ctx.shadowBlur = 5; | |
| ctx.strokeStyle = '#000'; | |
| ctx.lineWidth = 3; | |
| ctx.font = "bold 14px 'Press Start 2P'"; | |
| ctx.textAlign = "center"; | |
| ctx.strokeText("TIME", width/2, height/2 - 30); | |
| ctx.fillStyle = "#39ff14"; | |
| ctx.fillText("TIME", width/2, height/2 - 30); | |
| ctx.strokeText("SHRED", width/2, height/2 - 15); | |
| ctx.fillStyle = "#00f3ff"; | |
| ctx.fillText("SHRED", width/2, height/2 - 15); | |
| ctx.shadowBlur = 0; | |
| // Add cool sparkling stars in background | |
| for (let i = 0; i < 20; i++) { | |
| const x = Math.random() * width; | |
| const y = Math.random() * height; | |
| const size = Math.random() * 2 + 1; | |
| ctx.fillStyle = "rgba(255, 255, 255, 0.8)"; | |
| ctx.fillRect(x, y, size, size); | |
| } | |
| log("Enhanced title pixel art drawn"); | |
| } | |
| // Draw character pixel art with improved visuals | |
| function drawCharacterPixelArt() { | |
| const canvases = document.querySelectorAll('.character-pixel-art'); | |
| canvases.forEach(canvas => { | |
| if (!canvas) return; | |
| const ctx = canvas.getContext('2d'); | |
| const width = canvas.width; | |
| const height = canvas.height; | |
| const character = canvas.getAttribute('data-char'); | |
| // Clear canvas | |
| ctx.clearRect(0, 0, width, height); | |
| // Draw backdrop (different for each character) | |
| let bgColor = '#05051a'; | |
| if (character === 'sammy') bgColor = 'rgba(0, 243, 255, 0.1)'; | |
| if (character === 'ghost') bgColor = 'rgba(191, 0, 255, 0.1)'; | |
| ctx.fillStyle = bgColor; | |
| ctx.fillRect(0, 0, width, height); | |
| // Draw pixel grid | |
| ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)'; | |
| ctx.lineWidth = 0.5; | |
| for (let x = 0; x < width; x += 8) { | |
| ctx.beginPath(); | |
| ctx.moveTo(x, 0); | |
| ctx.lineTo(x, height); | |
| ctx.stroke(); | |
| } | |
| for (let y = 0; y < height; y += 8) { | |
| ctx.beginPath(); | |
| ctx.moveTo(0, y); | |
| ctx.lineTo(width, y); | |
| ctx.stroke(); | |
| } | |
| // Draw based on character type with enhanced visuals | |
| if (character === 'sammy') { | |
| // Lab coat (with gradient) | |
| const coatGradient = ctx.createLinearGradient(width/2 - 10, height/2, width/2 + 10, height/2); | |
| coatGradient.addColorStop(0, '#FFFFFF'); | |
| coatGradient.addColorStop(0.5, '#EEEEFF'); | |
| coatGradient.addColorStop(1, '#FFFFFF'); | |
| ctx.fillStyle = coatGradient; | |
| ctx.fillRect(width/2 - 10, height/2, 20, 20); | |
| // Dr. Ollie character with more details | |
| ctx.fillStyle = "#FFD3B6"; // Skin tone | |
| ctx.fillRect(width/2 - 8, height/2 - 16, 16, 16); // Head | |
| ctx.fillStyle = "#663931"; // Hair | |
| ctx.fillRect(width/2 - 10, height/2 - 18, 20, 6); | |
| // Glasses with glow | |
| ctx.shadowColor = "#00f3ff"; | |
| ctx.shadowBlur = 5; | |
| ctx.fillStyle = "#00f3ff"; // Neon blue glasses | |
| ctx.fillRect(width/2 - 8, height/2 - 10, 5, 3); | |
| ctx.fillRect(width/2 + 3, height/2 - 10, 5, 3); | |
| ctx.shadowBlur = 0; | |
| // Little skateboard under his feet | |
| ctx.fillStyle = "#39ff14"; // Green board | |
| ctx.fillRect(width/2 - 12, height/2 + 20, 24, 3); | |
| // Wheels | |
| ctx.fillStyle = "#ff00e5"; // Pink wheels | |
| ctx.fillRect(width/2 - 10, height/2 + 23, 4, 4); | |
| ctx.fillRect(width/2 + 6, height/2 + 23, 4, 4); | |
| } | |
| else if (character === 'ghost') { | |
| // Ghost Kim character with better effects | |
| ctx.fillStyle = "rgba(255, 255, 255, 0.2)"; // Base ghost effect | |
| ctx.beginPath(); | |
| ctx.arc(width/2, height/2 - 5, 17, 0, Math.PI * 2); | |
| ctx.fill(); | |
| // Ghost body with gradient | |
| const ghostGradient = ctx.createLinearGradient(width/2 - 15, height/2, width/2 + 15, height/2); | |
| ghostGradient.addColorStop(0, 'rgba(255, 255, 255, 0.7)'); | |
| ghostGradient.addColorStop(0.5, 'rgba(220, 220, 255, 0.8)'); | |
| ghostGradient.addColorStop(1, 'rgba(255, 255, 255, 0.7)'); | |
| ctx.fillStyle = ghostGradient; | |
| ctx.beginPath(); | |
| ctx.arc(width/2, height/2 - 5, 15, 0, Math.PI * 2); | |
| ctx.fill(); | |
| ctx.fillRect(width/2 - 15, height/2 - 5, 30, 20); | |
| // Ghost tail effect | |
| ctx.beginPath(); | |
| ctx.moveTo(width/2 - 15, height/2 + 15); | |
| ctx.lineTo(width/2 - 10, height/2 + 20); | |
| ctx.lineTo(width/2 - 5, height/2 + 15); | |
| ctx.lineTo(width/2, height/2 + 20); | |
| ctx.lineTo(width/2 + 5, height/2 + 15); | |
| ctx.lineTo(width/2 + 10, height/2 + 20); | |
| ctx.lineTo(width/2 + 15, height/2 + 15); | |
| ctx.fill(); | |
| // Eyes with glow | |
| ctx.shadowColor = "#00f3ff"; | |
| ctx.shadowBlur = 10; | |
| ctx.fillStyle = "#00f3ff"; // Glowing blue eyes | |
| ctx.fillRect(width/2 - 8, height/2 - 8, 5, 5); | |
| ctx.fillRect(width/2 + 3, height/2 - 8, 5, 5); | |
| ctx.shadowBlur = 0; | |
| // Ghostly skateboard that's semi-transparent | |
| ctx.fillStyle = "rgba(255, 0, 229, 0.4)"; // Semi-transparent neon pink | |
| ctx.fillRect(width/2 - 15, height/2 + 25, 30, 5); | |
| // Add ghostly particle effects | |
| for (let i = 0; i < 10; i++) { | |
| const x = width/2 + (Math.random() * 40 - 20); | |
| const y = height/2 + (Math.random() * 40 - 20); | |
| const size = Math.random() * 2 + 1; | |
| ctx.fillStyle = "rgba(255, 255, 255, 0.6)"; | |
| ctx.fillRect(x, y, size, size); | |
| } | |
| } | |
| log(`Enhanced character pixel art drawn for: ${character}`); | |
| }); | |
| } | |
| // Select a character | |
| function selectCharacter(char) { | |
| selectedCharacter = char; | |
| // Update the UI | |
| document.querySelectorAll('.character-card').forEach(card => { | |
| card.classList.remove('selected'); | |
| }); | |
| const selectedCard = document.getElementById(`${char}-card`); | |
| if (selectedCard) { | |
| selectedCard.classList.add('selected'); | |
| } | |
| log(`Selected character: ${char}`); | |
| } | |
| // Show a random loading tip | |
| function showRandomLoadingTip() { | |
| const tips = [ | |
| "Using Quantum Flow (Q key) slows time but consumes Paradox Power!", | |
| "Each character has a unique special move - choose wisely!", | |
| "The Butterfly Effect can have unexpected consequences in other timelines!", | |
| "Grind on timeline rails to build Paradox Power faster!", | |
| "Switch between time periods (T key) to access different areas and challenges.", | |
| "Don't become your own grandparent - it causes severe temporal migraines!", | |
| "Reality Edge Grind can tear holes in the fabric of spacetime!", | |
| "Collecting temporal artifacts increases your Paradox Meter", | |
| "Perform tricks in multiple timelines for combo multipliers!" | |
| ]; | |
| const randomTip = tips[Math.floor(Math.random() * tips.length)]; | |
| const tipElement = document.getElementById('loading-tip'); | |
| if (tipElement) { | |
| tipElement.textContent = `TIP: ${randomTip}`; | |
| tipElement.style.display = 'block'; | |
| // Hide after 5 seconds | |
| setTimeout(() => { | |
| tipElement.style.display = 'none'; | |
| }, 5000); | |
| log(`Showing tip: ${randomTip}`); | |
| } | |
| } | |
| // Emergency fallback for clicks on title screen | |
| window.addEventListener('load', function() { | |
| log("Window fully loaded"); | |
| // Final check to make sure start button is working | |
| const startButton = document.getElementById('startGameButton'); | |
| if (startButton) { | |
| startButton.onclick = function() { | |
| log("Start button clicked (emergency handler)"); | |
| showScreen('intro-screen'); | |
| }; | |
| } | |
| // Make sure title screen click works as backup | |
| const titleScreen = document.getElementById('title-screen'); | |
| if (titleScreen) { | |
| titleScreen.addEventListener('click', function(e) { | |
| // Only if not clicking on a button | |
| if (e.target.tagName !== 'BUTTON' && | |
| !e.target.closest('#controls-popup') && | |
| !e.target.closest('#skillTreePreview')) { | |
| log("Title screen background clicked"); | |
| showScreen('intro-screen'); | |
| } | |
| }); | |
| } | |
| }); | |
| // Log initialization complete | |
| console.log("[TimeShredders] Script loaded and initialized"); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment