Spaces:
Running
Running
Create an advanced retro gaming platform called "DoseGame Arcade Universe" with these extreme features: MULTI-GAME IMPLEMENTATION: 1. FULLY PLAYABLE SNAKE GAME: - Use WASD or arrow keys for movement - Dynamic speed increase as snake grows - Power-ups: Speed boost (blue), Invincibility (gold), Double points (red) - Obstacles that appear after level 5 - Multiplayer mode where 2 players use WASD vs Arrow keys - Leaderboard that updates in real-time using localStorage 2. TETRIS WITH TWIST: - Standard Tetris mechanics with rotation, drop, and line clearing - Special pieces that explode clearing 3x3 area - Ghost piece showing where current piece will land - Hold feature to save pieces - T-spin detection with bonus points - Background music tempo that increases with speed 3. PAC-MAN MAZE GENERATOR: - Procedurally generated mazes each playthrough - Ghost AI with different personalities (Blinky chases, Pinky ambushes, Inky flanks, Clyde random) - Power pellets that make ghosts edible - Bonus fruits appear based on score - Warp tunnels on maze edges ADVANCED CUSTOMIZATION ENGINE: - Visual sprite editor using canvas where users can: * Draw pixel art characters with color picker * Save custom sprites to localStorage * Import/export sprite sheets as base64 - Level editor for creating custom Snake/Pac-Man mazes - Sound effect creator with frequency/waveform controls - Custom game rules editor (gravity, speed, lives, etc.) REAL-TIME FEATURES: - Fake multiplayer lobby showing "online players" (randomly generated names) - Chat system with pre-programmed bot responses - Tournament bracket system for competitive play - Live streaming simulation showing "viewers watching" - Achievements that pop up with animations E-COMMERCE WITH CRYPTO: - Shopping cart that accepts "DoseCoins" (fake cryptocurrency) - Mining mini-game to earn DoseCoins - NFT-style unique skins marketplace - Auction house for rare items - Trading system between players AI INTEGRATION: - "AI Opponent" mode that adapts to player skill - Hint system that suggests moves in puzzle games - Voice commands using speech recognition API ("move left", "rotate", "pause") - Procedural music generation based on gameplay SOCIAL FEATURES: - User profiles with customizable avatars - Friend system with online status indicators - Guild/clan creation with shared achievements - Forum section with working post/reply system - Screenshot gallery with like/comment features TECHNICAL SHOWCASES: - WebGL shader effects for retro CRT, glitch, and rainbow effects - Physics engine for realistic collision in certain games - Particle system for explosions and effects - 3D mode toggle that transforms 2D games to isometric view - WebRTC for peer-to-peer connections (simulated) ACCESSIBILITY: - Colorblind modes with pattern alternatives - Screen reader support with ARIA labels - Adjustable game speed for all skill levels - One-button mode for simplified controls - Visual sound indicators ANALYTICS DASHBOARD: - Heatmap showing where players die most - Real-time graph of active players - Performance metrics (FPS, latency) - A/B testing interface for game features EASTER EGGS: - Konami code unlocks secret menu - Hidden retro console emulator - Matrix-style code rain background option - Boss rush mode combining all games - Time travel feature showing site "history" Make the entire platform feel alive with ambient animations, dynamic backgrounds that react to gameplay, and smooth transitions between all sections. Include loading screens with game tips, error pages styled as game over screens, and a credits roll listing fictional developers. CRITICAL: Implement at least 3 fully playable games with all features working, not just mockups. - Follow Up Deployment
87ba862
verified
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>DoseGame Arcade Universe</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> | |
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap'); | |
:root { | |
--primary: #ff3860; | |
--secondary: #3273dc; | |
--accent: #00d1b2; | |
--dark: #0f0f23; | |
--darker: #080817; | |
--retro-green: #00ff41; | |
--retro-blue: #00b3ff; | |
--retro-pink: #ff00ff; | |
} | |
body { | |
background: linear-gradient(135deg, var(--darker) 0%, var(--dark) 100%); | |
font-family: 'VT323', monospace; | |
color: white; | |
overflow-x: hidden; | |
min-height: 100vh; | |
} | |
.retro-font { | |
font-family: 'Press Start 2P', cursive; | |
} | |
.crt-effect { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
pointer-events: none; | |
background: repeating-linear-gradient( | |
0deg, | |
rgba(0, 0, 0, 0.15), | |
rgba(0, 0, 0, 0.15) 1px, | |
transparent 1px, | |
transparent 2px | |
); | |
z-index: 100; | |
opacity: 0.5; | |
} | |
.scanlines { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
pointer-events: none; | |
background: linear-gradient( | |
rgba(18, 16, 16, 0) 50%, | |
rgba(0, 0, 0, 0.25) 50% | |
); | |
background-size: 100% 4px; | |
z-index: 101; | |
opacity: 0.3; | |
} | |
.glow { | |
text-shadow: 0 0 10px var(--retro-green), 0 0 20px var(--retro-green); | |
} | |
.pixel-border { | |
border: 4px solid white; | |
box-shadow: | |
inset 0 0 0 2px black, | |
inset 0 0 0 6px #555, | |
inset 0 0 0 8px black, | |
0 0 10px rgba(0, 255, 65, 0.5); | |
} | |
.game-card { | |
transition: all 0.3s ease; | |
transform: scale(0.95); | |
} | |
.game-card:hover { | |
transform: scale(1); | |
box-shadow: 0 0 20px var(--accent); | |
} | |
.retro-btn { | |
background: linear-gradient(to bottom, #555, #333); | |
border: 2px solid #000; | |
color: white; | |
padding: 8px 16px; | |
font-size: 1.2rem; | |
font-family: 'VT323', monospace; | |
text-transform: uppercase; | |
letter-spacing: 2px; | |
position: relative; | |
overflow: hidden; | |
box-shadow: 0 4px 0 #000, inset 0 0 10px rgba(0,0,0,0.5); | |
transition: all 0.1s ease; | |
} | |
.retro-btn:active { | |
transform: translateY(4px); | |
box-shadow: 0 0 0 #000, inset 0 0 10px rgba(0,0,0,0.5); | |
} | |
.retro-btn::before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: -100%; | |
width: 100%; | |
height: 100%; | |
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent); | |
transition: 0.5s; | |
} | |
.retro-btn:hover::before { | |
left: 100%; | |
} | |
.retro-btn-primary { | |
background: linear-gradient(to bottom, var(--primary), #d0002f); | |
text-shadow: 0 0 5px rgba(255, 255, 255, 0.8); | |
} | |
.retro-btn-secondary { | |
background: linear-gradient(to bottom, var(--secondary), #2659c0); | |
} | |
.retro-btn-accent { | |
background: linear-gradient(to bottom, var(--accent), #00b8a0); | |
} | |
.leaderboard-entry { | |
animation: slideIn 0.3s ease-out; | |
} | |
@keyframes slideIn { | |
from { transform: translateX(-100%); opacity: 0; } | |
to { transform: translateX(0); opacity: 1; } | |
} | |
.achievement-popup { | |
animation: popIn 0.5s ease-out forwards; | |
} | |
@keyframes popIn { | |
0% { transform: scale(0.5); opacity: 0; } | |
70% { transform: scale(1.1); opacity: 1; } | |
100% { transform: scale(1); opacity: 1; } | |
} | |
.pixel-art { | |
image-rendering: pixelated; | |
image-rendering: -moz-crisp-edges; | |
image-rendering: crisp-edges; | |
} | |
.grid-bg { | |
background-image: | |
linear-gradient(rgba(50, 50, 50, 0.2) 1px, transparent 1px), | |
linear-gradient(90deg, rgba(50, 50, 50, 0.2) 1px, transparent 1px); | |
background-size: 20px 20px; | |
} | |
canvas { | |
display: block; | |
margin: 0 auto; | |
image-rendering: pixelated; | |
} | |
.power-up { | |
animation: pulse 1.5s infinite; | |
} | |
@keyframes pulse { | |
0% { transform: scale(1); } | |
50% { transform: scale(1.1); } | |
100% { transform: scale(1); } | |
} | |
.ghost { | |
animation: float 3s infinite ease-in-out; | |
} | |
@keyframes float { | |
0% { transform: translateY(0); } | |
50% { transform: translateY(-10px); } | |
100% { transform: translateY(0); } | |
} | |
.online-user { | |
animation: blink 1.5s infinite; | |
} | |
@keyframes blink { | |
0% { opacity: 1; } | |
50% { opacity: 0.5; } | |
100% { opacity: 1; } | |
} | |
.rainbow-text { | |
background: linear-gradient(to right, #ff3860, #ffdd57, #00d1b2, #3273dc, #b86bff); | |
-webkit-background-clip: text; | |
background-clip: text; | |
color: transparent; | |
animation: rainbow-animation 5s linear infinite; | |
} | |
@keyframes rainbow-animation { | |
to { background-position: 100vw; } | |
} | |
.matrix-bg { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: black; | |
z-index: -2; | |
} | |
.matrix-char { | |
position: absolute; | |
color: #00ff41; | |
font-family: 'VT323', monospace; | |
font-size: 16px; | |
opacity: 0; | |
animation: fall linear forwards; | |
} | |
@keyframes fall { | |
to { | |
transform: translateY(100vh); | |
opacity: 1; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<!-- CRT Effect --> | |
<div class="crt-effect"></div> | |
<div class="scanlines"></div> | |
<!-- Matrix Background (Easter Egg) --> | |
<div id="matrix-bg" class="matrix-bg hidden"></div> | |
<!-- Main Container --> | |
<div class="container mx-auto px-4 py-6 max-w-7xl"> | |
<!-- Header --> | |
<header class="flex flex-col items-center mb-8"> | |
<div class="flex items-center justify-center w-full mb-4"> | |
<div class="bg-gray-800 rounded-full w-16 h-16 flex items-center justify-center mr-4"> | |
<i class="fas fa-gamepad text-3xl text-purple-500"></i> | |
</div> | |
<h1 class="retro-font text-4xl md:text-6xl text-center glow rainbow-text">DoseGame Arcade Universe</h1> | |
<div class="bg-gray-800 rounded-full w-16 h-16 flex items-center justify-center ml-4"> | |
<i class="fas fa-joystick text-3xl text-green-500"></i> | |
</div> | |
</div> | |
<div class="flex space-x-4 mb-6"> | |
<div class="bg-blue-600 px-4 py-1 rounded-lg flex items-center"> | |
<i class="fas fa-users mr-2"></i> | |
<span id="online-count">128</span> Online | |
</div> | |
<div class="bg-purple-600 px-4 py-1 rounded-lg flex items-center"> | |
<i class="fas fa-eye mr-2"></i> | |
<span id="viewers-count">2.4K</span> Viewers | |
</div> | |
<div class="bg-green-600 px-4 py-1 rounded-lg flex items-center"> | |
<i class="fas fa-coins mr-2"></i> | |
<span id="dosecoins">1,250</span> DoseCoins | |
</div> | |
</div> | |
<nav class="w-full grid grid-cols-3 gap-2 max-w-3xl"> | |
<button id="nav-games" class="retro-btn retro-btn-primary">Games</button> | |
<button id="nav-leaderboard" class="retro-btn retro-btn-secondary">Leaderboard</button> | |
<button id="nav-shop" class="retro-btn retro-btn-accent">NFT Shop</button> | |
</nav> | |
</header> | |
<!-- Main Content Area --> | |
<main class="grid-bg rounded-xl p-6 pixel-border"> | |
<!-- Games Section --> | |
<section id="games-section"> | |
<h2 class="retro-font text-3xl mb-6 text-center text-green-400">Arcade Games</h2> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"> | |
<!-- Snake Game Card --> | |
<div class="game-card bg-gray-800 rounded-xl overflow-hidden"> | |
<div class="bg-gray-900 p-4"> | |
<h3 class="retro-font text-xl text-center text-green-400 mb-2">SNAKE</h3> | |
<div class="aspect-w-16 aspect-h-9 bg-black relative"> | |
<canvas id="snake-preview" width="300" height="200"></canvas> | |
<div class="absolute inset-0 flex items-center justify-center"> | |
<button id="play-snake" class="retro-btn retro-btn-primary text-lg">PLAY NOW</button> | |
</div> | |
</div> | |
</div> | |
<div class="p-4"> | |
<p class="mb-3">Classic snake game with power-ups and multiplayer mode!</p> | |
<div class="flex flex-wrap gap-2"> | |
<span class="bg-gray-700 px-2 py-1 rounded text-sm">Multiplayer</span> | |
<span class="bg-gray-700 px-2 py-1 rounded text-sm">Power-ups</span> | |
<span class="bg-gray-700 px-2 py-1 rounded text-sm">Leaderboard</span> | |
</div> | |
</div> | |
</div> | |
<!-- Tetris Game Card --> | |
<div class="game-card bg-gray-800 rounded-xl overflow-hidden"> | |
<div class="bg-gray-900 p-4"> | |
<h3 class="retro-font text-xl text-center text-blue-400 mb-2">TETRIS</h3> | |
<div class="aspect-w-16 aspect-h-9 bg-black relative"> | |
<canvas id="tetris-preview" width="300" height="200"></canvas> | |
<div class="absolute inset-0 flex items-center justify-center"> | |
<button id="play-tetris" class="retro-btn retro-btn-primary text-lg">PLAY NOW</button> | |
</div> | |
</div> | |
</div> | |
<div class="p-4"> | |
<p class="mb-3">Tetris with special blocks and T-spin bonuses!</p> | |
<div class="flex flex-wrap gap-2"> | |
<span class="bg-gray-700 px-2 py-1 rounded text-sm">Special Blocks</span> | |
<span class="bg-gray-700 px-2 py-1 rounded text-sm">T-Spin</span> | |
<span class="bg-gray-700 px-2 py-1 rounded text-sm">Ghost Piece</span> | |
</div> | |
</div> | |
</div> | |
<!-- Pac-Man Game Card --> | |
<div class="game-card bg-gray-800 rounded-xl overflow-hidden"> | |
<div class="bg-gray-900 p-4"> | |
<h3 class="retro-font text-xl text-center text-yellow-400 mb-2">PAC-MAN</h3> | |
<div class="aspect-w-16 aspect-h-9 bg-black relative"> | |
<canvas id="pacman-preview" width="300" height="200"></canvas> | |
<div class="absolute inset-0 flex items-center justify-center"> | |
<button id="play-pacman" class="retro-btn retro-btn-primary text-lg">PLAY NOW</button> | |
</div> | |
</div> | |
</div> | |
<div class="p-4"> | |
<p class="mb-3">Pac-Man with generated mazes and smart ghosts!</p> | |
<div class="flex flex-wrap gap-2"> | |
<span class="bg-gray-700 px-2 py-1 rounded text-sm">Procedural Mazes</span> | |
<span class="bg-gray-700 px-2 py-1 rounded text-sm">Ghost AI</span> | |
<span class="bg-gray-700 px-2 py-1 rounded text-sm">Power Pellets</span> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Multiplayer Lobby --> | |
<div class="bg-gray-800 rounded-xl p-6 mb-8"> | |
<h3 class="retro-font text-2xl mb-4 text-center text-purple-400">Multiplayer Lobby</h3> | |
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
<div> | |
<h4 class="text-xl mb-3 text-green-400">Online Players</h4> | |
<div id="online-players" class="bg-gray-900 rounded-lg p-4 h-64 overflow-y-auto"> | |
<!-- Players will be populated by JS --> | |
</div> | |
</div> | |
<div> | |
<h4 class="text-xl mb-3 text-blue-400">Tournaments</h4> | |
<div class="bg-gray-900 rounded-lg p-4"> | |
<div class="mb-4"> | |
<h5 class="text-lg mb-2">Snake Championship</h5> | |
<div class="flex justify-between mb-1"> | |
<span>Players: 24/32</span> | |
<span>Starts in: 12:45</span> | |
</div> | |
<div class="w-full bg-gray-700 rounded-full h-2"> | |
<div class="bg-green-500 h-2 rounded-full" style="width: 75%"></div> | |
</div> | |
</div> | |
<div class="mb-4"> | |
<h5 class="text-lg mb-2">Tetris Masters</h5> | |
<div class="flex justify-between mb-1"> | |
<span>Players: 18/24</span> | |
<span>Starts in: 24:30</span> | |
</div> | |
<div class="w-full bg-gray-700 rounded-full h-2"> | |
<div class="bg-blue-500 h-2 rounded-full" style="width: 60%"></div> | |
</div> | |
</div> | |
<button class="retro-btn retro-btn-secondary w-full">JOIN TOURNAMENT</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Chat Section --> | |
<div class="bg-gray-800 rounded-xl p-6"> | |
<h3 class="retro-font text-2xl mb-4 text-center text-yellow-400">Arcade Chat</h3> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
<div class="md:col-span-2"> | |
<div id="chat-messages" class="bg-gray-900 rounded-lg p-4 h-64 overflow-y-auto mb-3"> | |
<!-- Chat messages will be populated by JS --> | |
</div> | |
<div class="flex"> | |
<input type="text" id="chat-input" placeholder="Type your message..." class="flex-grow bg-gray-700 text-white px-4 py-2 rounded-l-lg focus:outline-none"> | |
<button id="send-chat" class="retro-btn retro-btn-primary rounded-l-none">SEND</button> | |
</div> | |
</div> | |
<div> | |
<h4 class="text-xl mb-3 text-pink-400">Achievements</h4> | |
<div id="achievements" class="bg-gray-900 rounded-lg p-4 h-64 overflow-y-auto"> | |
<!-- Achievements will be populated by JS --> | |
</div> | |
</div> | |
</div> | |
</div> | |
</section> | |
<!-- Leaderboard Section (Hidden by default) --> | |
<section id="leaderboard-section" class="hidden"> | |
<h2 class="retro-font text-3xl mb-6 text-center text-blue-400">Leaderboards</h2> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8"> | |
<div class="bg-gray-800 rounded-xl p-6"> | |
<h3 class="retro-font text-2xl mb-4 text-center text-green-400">Snake Champions</h3> | |
<div id="snake-leaderboard" class="space-y-3"> | |
<!-- Snake leaderboard entries will be populated by JS --> | |
</div> | |
</div> | |
<div class="bg-gray-800 rounded-xl p-6"> | |
<h3 class="retro-font text-2xl mb-4 text-center text-blue-400">Tetris Masters</h3> | |
<div id="tetris-leaderboard" class="space-y-3"> | |
<!-- Tetris leaderboard entries will be populated by JS --> | |
</div> | |
</div> | |
<div class="bg-gray-800 rounded-xl p-6"> | |
<h3 class="retro-font text-2xl mb-4 text-center text-yellow-400">Pac-Man Legends</h3> | |
<div id="pacman-leaderboard" class="space-y-3"> | |
<!-- Pac-Man leaderboard entries will be populated by JS --> | |
</div> | |
</div> | |
</div> | |
<div class="bg-gray-800 rounded-xl p-6"> | |
<h3 class="retro-font text-2xl mb-4 text-center text-purple-400">Your Stats</h3> | |
<div class="grid grid-cols-1 md:grid-cols-3 gap-6"> | |
<div class="bg-gray-900 p-4 rounded-lg"> | |
<h4 class="text-lg mb-2 text-green-400">Snake</h4> | |
<p>High Score: <span id="snake-highscore">0</span></p> | |
<p>Games Played: <span id="snake-games">0</span></p> | |
<p>Longest Snake: <span id="snake-length">0</span></p> | |
</div> | |
<div class="bg-gray-900 p-4 rounded-lg"> | |
<h4 class="text-lg mb-2 text-blue-400">Tetris</h4> | |
<p>High Score: <span id="tetris-highscore">0</span></p> | |
<p>Lines Cleared: <span id="tetris-lines">0</span></p> | |
<p>T-Spins: <span id="tetris-tspins">0</span></p> | |
</div> | |
<div class="bg-gray-900 p-4 rounded-lg"> | |
<h4 class="text-lg mb-2 text-yellow-400">Pac-Man</h4> | |
<p>High Score: <span id="pacman-highscore">0</span></p> | |
<p>Ghosts Eaten: <span id="pacman-ghosts">0</span></p> | |
<p>Level Reached: <span id="pacman-level">0</span></p> | |
</div> | |
</div> | |
</div> | |
</section> | |
<!-- NFT Shop Section (Hidden by default) --> | |
<section id="shop-section" class="hidden"> | |
<h2 class="retro-font text-3xl mb-6 text-center text-purple-400">NFT Marketplace</h2> | |
<div class="bg-gray-800 rounded-xl p-6 mb-8"> | |
<div class="flex justify-between items-center mb-6"> | |
<h3 class="retro-font text-2xl text-yellow-400">Collectible Skins</h3> | |
<div class="flex items-center"> | |
<span class="mr-2"><i class="fas fa-coins text-yellow-400"></i> 1,250</span> | |
<button class="retro-btn retro-btn-accent ml-2">Mine Coins</button> | |
</div> | |
</div> | |
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> | |
<!-- NFT items will be populated by JS --> | |
</div> | |
</div> | |
<div class="bg-gray-800 rounded-xl p-6"> | |
<h3 class="retro-font text-2xl mb-4 text-center text-green-400">Your Inventory</h3> | |
<div id="inventory" class="grid grid-cols-2 md:grid-cols-4 gap-4"> | |
<!-- Inventory items will be populated by JS --> | |
</div> | |
</div> | |
</section> | |
</main> | |
<!-- Game Containers (Hidden by default) --> | |
<div id="game-container" class="hidden fixed inset-0 bg-black bg-opacity-90 z-50 flex items-center justify-center p-4"> | |
<div class="relative w-full max-w-4xl"> | |
<button id="close-game" class="absolute top-4 right-4 z-10 retro-btn retro-btn-primary"> | |
<i class="fas fa-times"></i> | |
</button> | |
<div class="bg-gray-800 rounded-xl p-2 pixel-border"> | |
<canvas id="game-canvas" width="800" height="600" class="w-full"></canvas> | |
</div> | |
<div id="game-ui" class="mt-4 grid grid-cols-3 gap-4"> | |
<div class="bg-gray-800 p-3 rounded-lg"> | |
<div class="text-center mb-2">SCORE</div> | |
<div id="game-score" class="text-2xl text-center">0</div> | |
</div> | |
<div class="bg-gray-800 p-3 rounded-lg"> | |
<div class="text-center mb-2">LEVEL</div> | |
<div id="game-level" class="text-2xl text-center">1</div> | |
</div> | |
<div class="bg-gray-800 p-3 rounded-lg"> | |
<div class="text-center mb-2">LIVES</div> | |
<div id="game-lives" class="text-2xl text-center">3</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Achievement Popup Container --> | |
<div id="achievement-container" class="fixed top-4 right-4 z-50"></div> | |
</div> | |
<!-- Footer --> | |
<footer class="mt-12 py-6 text-center text-gray-400"> | |
<div class="mb-4"> | |
<button id="easter-egg-btn" class="retro-btn retro-btn-secondary mx-2">Konami Code</button> | |
<button id="matrix-bg-btn" class="retro-btn retro-btn-secondary mx-2">Matrix Mode</button> | |
<button id="credits-btn" class="retro-btn retro-btn-secondary mx-2">Credits</button> | |
</div> | |
<p>DoseGame Arcade Universe © 2023 | All games are fully playable in your browser!</p> | |
<p class="mt-2">Powered by WebGL, WebRTC, and DoseCoins™</p> | |
</footer> | |
<script> | |
// Initialize game data | |
const gameData = { | |
currentGame: null, | |
snakePreview: null, | |
tetrisPreview: null, | |
pacmanPreview: null, | |
gameCanvas: null, | |
gameContext: null, | |
gameActive: false, | |
gameLoop: null, | |
leaderboard: { | |
snake: JSON.parse(localStorage.getItem('snakeLeaderboard')) || [], | |
tetris: JSON.parse(localStorage.getItem('tetrisLeaderboard')) || [], | |
pacman: JSON.parse(localStorage.getItem('pacmanLeaderboard')) || [] | |
}, | |
userStats: JSON.parse(localStorage.getItem('userStats')) || { | |
snake: { highScore: 0, gamesPlayed: 0, longestSnake: 0 }, | |
tetris: { highScore: 0, linesCleared: 0, tspins: 0 }, | |
pacman: { highScore: 0, ghostsEaten: 0, levelReached: 0 } | |
}, | |
dosecoins: parseInt(localStorage.getItem('dosecoins')) || 1250, | |
ownedSkins: JSON.parse(localStorage.getItem('ownedSkins')) || [], | |
matrixMode: false | |
}; | |
// DOM Elements | |
const elements = { | |
gamesSection: document.getElementById('games-section'), | |
leaderboardSection: document.getElementById('leaderboard-section'), | |
shopSection: document.getElementById('shop-section'), | |
gameContainer: document.getElementById('game-container'), | |
gameCanvas: document.getElementById('game-canvas'), | |
gameContext: document.getElementById('game-canvas').getContext('2d'), | |
gameScore: document.getElementById('game-score'), | |
gameLevel: document.getElementById('game-level'), | |
gameLives: document.getElementById('game-lives'), | |
closeGame: document.getElementById('close-game'), | |
onlinePlayers: document.getElementById('online-players'), | |
chatMessages: document.getElementById('chat-messages'), | |
chatInput: document.getElementById('chat-input'), | |
sendChat: document.getElementById('send-chat'), | |
achievements: document.getElementById('achievements'), | |
achievementContainer: document.getElementById('achievement-container'), | |
snakeLeaderboard: document.getElementById('snake-leaderboard'), | |
tetrisLeaderboard: document.getElementById('tetris-leaderboard'), | |
pacmanLeaderboard: document.getElementById('pacman-leaderboard'), | |
snakeHighscore: document.getElementById('snake-highscore'), | |
snakeGames: document.getElementById('snake-games'), | |
snakeLength: document.getElementById('snake-length'), | |
tetrisHighscore: document.getElementById('tetris-highscore'), | |
tetrisLines: document.getElementById('tetris-lines'), | |
tetrisTspins: document.getElementById('tetris-tspins'), | |
pacmanHighscore: document.getElementById('pacman-highscore'), | |
pacmanGhosts: document.getElementById('pacman-ghosts'), | |
pacmanLevel: document.getElementById('pacman-level'), | |
onlineCount: document.getElementById('online-count'), | |
viewersCount: document.getElementById('viewers-count'), | |
dosecoinsDisplay: document.getElementById('dosecoins'), | |
matrixBg: document.getElementById('matrix-bg'), | |
matrixBgBtn: document.getElementById('matrix-bg-btn') | |
}; | |
// Initialize the platform | |
function initPlatform() { | |
// Set up navigation | |
document.getElementById('nav-games').addEventListener('click', () => showSection('games')); | |
document.getElementById('nav-leaderboard').addEventListener('click', () => showSection('leaderboard')); | |
document.getElementById('nav-shop').addEventListener('click', () => showSection('shop')); | |
// Set up game buttons | |
document.getElementById('play-snake').addEventListener('click', () => startGame('snake')); | |
document.getElementById('play-tetris').addEventListener('click', () => startGame('tetris')); | |
document.getElementById('play-pacman').addEventListener('click', () => startGame('pacman')); | |
// Close game button | |
elements.closeGame.addEventListener('click', closeGame); | |
// Chat system | |
elements.sendChat.addEventListener('click', sendChatMessage); | |
elements.chatInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') sendChatMessage(); | |
}); | |
// Easter eggs | |
document.getElementById('easter-egg-btn').addEventListener('click', konamiCode); | |
elements.matrixBgBtn.addEventListener('click', toggleMatrixMode); | |
document.getElementById('credits-btn').addEventListener('click', showCredits); | |
// Initialize preview canvases | |
initPreviewCanvases(); | |
// Load data | |
loadLeaderboards(); | |
loadUserStats(); | |
updateCoinDisplay(); | |
// Populate online players | |
generateOnlinePlayers(); | |
// Populate achievements | |
generateAchievements(); | |
// Populate NFT shop | |
generateNFTShop(); | |
// Populate inventory | |
generateInventory(); | |
// Simulate live viewers | |
simulateViewers(); | |
// Start chat bots | |
startChatBots(); | |
// Show games section by default | |
showSection('games'); | |
} | |
// Show a specific section | |
function showSection(section) { | |
elements.gamesSection.classList.add('hidden'); | |
elements.leaderboardSection.classList.add('hidden'); | |
elements.shopSection.classList.add('hidden'); | |
switch(section) { | |
case 'games': | |
elements.gamesSection.classList.remove('hidden'); | |
break; | |
case 'leaderboard': | |
elements.leaderboardSection.classList.remove('hidden'); | |
break; | |
case 'shop': | |
elements.shopSection.classList.remove('hidden'); | |
break; | |
} | |
} | |
// Initialize preview canvases | |
function initPreviewCanvases() { | |
// Snake preview | |
const snakeCanvas = document.getElementById('snake-preview'); | |
const snakeCtx = snakeCanvas.getContext('2d'); | |
drawSnakePreview(snakeCtx, snakeCanvas.width, snakeCanvas.height); | |
// Tetris preview | |
const tetrisCanvas = document.getElementById('tetris-preview'); | |
const tetrisCtx = tetrisCanvas.getContext('2d'); | |
drawTetrisPreview(tetrisCtx, tetrisCanvas.width, tetrisCanvas.height); | |
// Pac-Man preview | |
const pacmanCanvas = document.getElementById('pacman-preview'); | |
const pacmanCtx = pacmanCanvas.getContext('2d'); | |
drawPacmanPreview(pacmanCtx, pacmanCanvas.width, pacmanCanvas.height); | |
} | |
// Draw Snake preview | |
function drawSnakePreview(ctx, width, height) { | |
ctx.fillStyle = '#000'; | |
ctx.fillRect(0, 0, width, height); | |
// Draw grid | |
ctx.strokeStyle = '#222'; | |
ctx.lineWidth = 1; | |
for (let x = 0; x <= width; x += 20) { | |
ctx.beginPath(); | |
ctx.moveTo(x, 0); | |
ctx.lineTo(x, height); | |
ctx.stroke(); | |
} | |
for (let y = 0; y <= height; y += 20) { | |
ctx.beginPath(); | |
ctx.moveTo(0, y); | |
ctx.lineTo(width, y); | |
ctx.stroke(); | |
} | |
// Draw snake | |
ctx.fillStyle = '#00ff41'; | |
ctx.fillRect(60, 80, 20, 20); | |
ctx.fillRect(80, 80, 20, 20); | |
ctx.fillRect(100, 80, 20, 20); | |
ctx.fillRect(120, 80, 20, 20); | |
ctx.fillRect(140, 80, 20, 20); | |
// Draw snake head | |
ctx.fillStyle = '#00cc33'; | |
ctx.fillRect(140, 80, 20, 20); | |
// Draw apple | |
ctx.fillStyle = '#ff3860'; | |
ctx.beginPath(); | |
ctx.arc(200, 120, 10, 0, Math.PI * 2); | |
ctx.fill(); | |
// Draw power-up | |
ctx.fillStyle = '#3273dc'; | |
ctx.beginPath(); | |
ctx.arc(240, 60, 8, 0, Math.PI * 2); | |
ctx.fill(); | |
} | |
// Draw Tetris preview | |
function drawTetrisPreview(ctx, width, height) { | |
ctx.fillStyle = '#000'; | |
ctx.fillRect(0, 0, width, height); | |
// Draw grid | |
ctx.strokeStyle = '#222'; | |
ctx.lineWidth = 1; | |
for (let x = 0; x <= width; x += 20) { | |
ctx.beginPath(); | |
ctx.moveTo(x, 0); | |
ctx.lineTo(x, height); | |
ctx.stroke(); | |
} | |
for (let y = 0; y <= height; y += 20) { | |
ctx.beginPath(); | |
ctx.moveTo(0, y); | |
ctx.lineTo(width, y); | |
ctx.stroke(); | |
} | |
// Draw blocks | |
const colors = ['#ff3860', '#3273dc', '#00d1b2', '#ffdd57', '#b86bff']; | |
// Draw L block | |
ctx.fillStyle = colors[0]; | |
ctx.fillRect(100, 40, 20, 20); | |
ctx.fillRect(100, 60, 20, 20); | |
ctx.fillRect(100, 80, 20, 20); | |
ctx.fillRect(120, 80, 20, 20); | |
// Draw T block | |
ctx.fillStyle = colors[1]; | |
ctx.fillRect(160, 60, 20, 20); | |
ctx.fillRect(180, 60, 20, 20); | |
ctx.fillRect(200, 60, 20, 20); | |
ctx.fillRect(180, 80, 20, 20); | |
// Draw square block | |
ctx.fillStyle = colors[2]; | |
ctx.fillRect(240, 60, 20, 20); | |
ctx.fillRect(260, 60, 20, 20); | |
ctx.fillRect(240, 80, 20, 20); | |
ctx.fillRect(260, 80, 20, 20); | |
// Draw explosion effect | |
ctx.fillStyle = '#ffdd57'; | |
ctx.beginPath(); | |
ctx.arc(180, 140, 15, 0, Math.PI * 2); | |
ctx.fill(); | |
ctx.strokeStyle = '#ffaa00'; | |
ctx.lineWidth = 2; | |
ctx.beginPath(); | |
ctx.moveTo(165, 140); | |
ctx.lineTo(155, 140); | |
ctx.moveTo(195, 140); | |
ctx.lineTo(205, 140); | |
ctx.moveTo(180, 125); | |
ctx.lineTo(180, 115); | |
ctx.moveTo(180, 155); | |
ctx.lineTo(180, 165); | |
ctx.stroke(); | |
} | |
// Draw Pac-Man preview | |
function drawPacmanPreview(ctx, width, height) { | |
ctx.fillStyle = '#000'; | |
ctx.fillRect(0, 0, width, height); | |
// Draw maze | |
ctx.strokeStyle = '#3273dc'; | |
ctx.lineWidth = 2; | |
// Outer walls | |
ctx.strokeRect(20, 20, width - 40, height - 40); | |
// Inner walls | |
ctx.beginPath(); | |
ctx.moveTo(100, 20); | |
ctx.lineTo(100, 100); | |
ctx.moveTo(200, 20); | |
ctx.lineTo(200, 100); | |
ctx.moveTo(20, 100); | |
ctx.lineTo(280, 100); | |
ctx.stroke(); | |
// Draw dots | |
ctx.fillStyle = '#fff'; | |
for (let x = 40; x < width - 20; x += 20) { | |
for (let y = 40; y < height - 20; y += 20) { | |
if ((x < 80 || x > 120) && (y < 80 || y > 120)) { | |
ctx.beginPath(); | |
ctx.arc(x, y, 2, 0, Math.PI * 2); | |
ctx.fill(); | |
} | |
} | |
} | |
// Draw power pellet | |
ctx.fillStyle = '#ffdd57'; | |
ctx.beginPath(); | |
ctx.arc(150, 60, 5, 0, Math.PI * 2); | |
ctx.fill(); | |
// Draw Pac-Man | |
ctx.fillStyle = '#ffdd57'; | |
ctx.beginPath(); | |
ctx.arc(60, 60, 15, 0.2 * Math.PI, 1.8 * Math.PI); | |
ctx.lineTo(60, 60); | |
ctx.fill(); | |
// Draw ghosts | |
const ghostColors = ['#ff3860', '#ff88ff', '#00d1b2', '#ffdd57']; | |
const ghostPositions = [ | |
{x: 180, y: 60}, | |
{x: 220, y: 60}, | |
{x: 180, y: 140}, | |
{x: 220, y: 140} | |
]; | |
ghostColors.forEach((color, i) => { | |
ctx.fillStyle = color; | |
drawGhost(ctx, ghostPositions[i].x, ghostPositions[i].y); | |
}); | |
} | |
// Draw a ghost | |
function drawGhost(ctx, x, y) { | |
ctx.beginPath(); | |
ctx.arc(x, y, 10, Math.PI, 0, false); // Top half | |
ctx.lineTo(x + 10, y + 15); | |
ctx.lineTo(x + 7, y + 10); | |
ctx.lineTo(x + 3, y + 15); | |
ctx.lineTo(x, y + 10); | |
ctx.closePath(); | |
ctx.fill(); | |
// Eyes | |
ctx.fillStyle = '#fff'; | |
ctx.beginPath(); | |
ctx.arc(x - 3, y - 2, 3, 0, Math.PI * 2); | |
ctx.arc(x + 3, y - 2, 3, 0, Math.PI * 2); | |
ctx.fill(); | |
ctx.fillStyle = '#000'; | |
ctx.beginPath(); | |
ctx.arc(x - 3, y - 2, 1.5, 0, Math.PI * 2); | |
ctx.arc(x + 3, y - 2, 1.5, 0, Math.PI * 2); | |
ctx.fill(); | |
} | |
// Start a game | |
function startGame(game) { | |
gameData.currentGame = game; | |
elements.gameContainer.classList.remove('hidden'); | |
// Set up game UI | |
elements.gameScore.textContent = '0'; | |
elements.gameLevel.textContent = '1'; | |
elements.gameLives.textContent = '3'; | |
// Start the game | |
switch(game) { | |
case 'snake': | |
startSnakeGame(); | |
break; | |
case 'tetris': | |
startTetrisGame(); | |
break; | |
case 'pacman': | |
startPacmanGame(); | |
break; | |
} | |
} | |
// Close the game | |
function closeGame() { | |
if (gameData.gameActive) { | |
gameData.gameActive = false; | |
cancelAnimationFrame(gameData.gameLoop); | |
} | |
elements.gameContainer.classList.add('hidden'); | |
} | |
// Snake Game Implementation | |
function startSnakeGame() { | |
const canvas = elements.gameCanvas; | |
const ctx = elements.gameContext; | |
const gridSize = 20; | |
const width = canvas.width; | |
const height = canvas.height; | |
let snake = [ | |
{x: 5, y: 5}, | |
{x: 4, y: 5}, | |
{x: 3, y: 5} | |
]; | |
let direction = 'right'; | |
let food = {x: 10, y: 10}; | |
let score = 0; | |
let gameSpeed = 150; | |
let lastRenderTime = 0; | |
let gameOver = false; | |
// Power-ups | |
let powerUps = []; | |
let powerUpTypes = ['speed', 'invincible', 'double']; | |
let powerUpColors = { | |
'speed': '#3273dc', | |
'invincible': '#ffdd57', | |
'double': '#ff3860' | |
}; | |
// Generate initial food | |
generateFood(); | |
// Game loop | |
function gameLoop(currentTime) { | |
if (gameOver) { | |
endGame(); | |
return; | |
} | |
gameData.gameLoop = requestAnimationFrame(gameLoop); | |
const secondsSinceLastRender = (currentTime - lastRenderTime) / 1000; | |
if (secondsSinceLastRender < 1 / (1000 / gameSpeed)) return; | |
lastRenderTime = currentTime; | |
update(); | |
draw(); | |
} | |
function update() { | |
// Move snake | |
const head = {...snake[0]}; | |
switch(direction) { | |
case 'up': head.y--; break; | |
case 'down': head.y++; break; | |
case 'left': head.x--; break; | |
case 'right': head.x++; break; | |
} | |
// Check collision with walls | |
if (head.x < 0 || head.x >= width/gridSize || head.y < 0 || head.y >= height/gridSize) { | |
gameOver = true; | |
return; | |
} | |
// Check collision with self | |
for (let i = 0; i < snake.length; i++) { | |
if (snake[i].x === head.x && snake[i].y === head.y) { | |
gameOver = true; | |
return; | |
} | |
} | |
// Add new head | |
snake.unshift(head); | |
// Check food collision | |
if (head.x === food.x && head.y === food.y) { | |
score += 10; | |
elements.gameScore.textContent = score; | |
generateFood(); | |
// Occasionally generate power-up | |
if (Math.random() > 0.7) { | |
generatePowerUp(); | |
} | |
} else { | |
// Remove tail | |
snake.pop(); | |
} | |
// Check power-up collision | |
for (let i = 0; i < powerUps.length; i++) { | |
const p = powerUps[i]; | |
if (head.x === p.x && head.y === p.y) { | |
applyPowerUp(p.type); | |
powerUps.splice(i, 1); | |
break; | |
} | |
} | |
} | |
function draw() { | |
// Clear canvas | |
ctx.fillStyle = '#000'; | |
ctx.fillRect(0, 0, width, height); | |
// Draw grid | |
ctx.strokeStyle = '#222'; | |
ctx.lineWidth = 1; | |
for (let x = 0; x <= width; x += gridSize) { | |
ctx.beginPath(); | |
ctx.moveTo(x, 0); | |
ctx.lineTo(x, height); | |
ctx.stroke(); | |
} | |
for (let y = 0; y <= height; y += gridSize) { | |
ctx.beginPath(); | |
ctx.moveTo(0, y); | |
ctx.lineTo(width, y); | |
ctx.stroke(); | |
} | |
// Draw snake | |
snake.forEach((segment, index) => { | |
ctx.fillStyle = index === 0 ? '#00cc33' : '#00ff41'; | |
ctx.fillRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize); | |
ctx.strokeStyle = '#000'; | |
ctx.lineWidth = 1; | |
ctx.strokeRect(segment.x * gridSize, segment.y * gridSize, gridSize, gridSize); | |
}); | |
// Draw food | |
ctx.fillStyle = '#ff3860'; | |
ctx.beginPath(); | |
ctx.arc(food.x * gridSize + gridSize/2, food.y * gridSize + gridSize/2, gridSize/2, 0, Math.PI * 2); | |
ctx.fill(); | |
// Draw power-ups | |
powerUps.forEach(powerUp => { | |
ctx.fillStyle = powerUpColors[powerUp.type]; | |
ctx.beginPath(); | |
ctx.arc(powerUp.x * gridSize + gridSize/2, powerUp.y * gridSize + gridSize/2, gridSize/3, 0, Math.PI * 2); | |
ctx.fill(); | |
}); | |
// Draw score | |
ctx.fillStyle = '#fff'; | |
ctx.font = '20px "Press Start 2P"'; | |
ctx.fillText(`SCORE: ${score}`, 10, 30); | |
} | |
function generateFood() { | |
food = { | |
x: Math.floor(Math.random() * (width / gridSize)), | |
y: Math.floor(Math.random() * (height / gridSize)) | |
}; | |
// Make sure food doesn't appear on snake | |
for (let segment of snake) { | |
if (segment.x === food.x && segment.y === food.y) { | |
generateFood(); | |
break; | |
} | |
} | |
} | |
function generatePowerUp() { | |
const type = powerUpTypes[Math.floor(Math.random() * powerUpTypes.length)]; | |
const powerUp = { | |
x: Math.floor(Math.random() * (width / gridSize)), | |
y: Math.floor(Math.random() * (height / gridSize)), | |
type: type | |
}; | |
// Make sure power-up doesn't appear on snake or food | |
let validPosition = true; | |
for (let segment of snake) { | |
if (segment.x === powerUp.x && segment.y === powerUp.y) { | |
validPosition = false; | |
break; | |
} | |
} | |
if (food.x === powerUp.x && food.y === powerUp.y) { | |
validPosition = false; | |
} | |
if (validPosition) { | |
powerUps.push(powerUp); | |
} else { | |
generatePowerUp(); | |
} | |
} | |
function applyPowerUp(type) { | |
switch(type) { | |
case 'speed': | |
gameSpeed = Math.max(50, gameSpeed - 20); | |
showAchievement('Speed Boost!', '#3273dc'); | |
break; | |
case 'invincible': | |
showAchievement('Invincibility!', '#ffdd57'); | |
setTimeout(() => { | |
showAchievement('Invincibility Ended', '#ffdd57'); | |
}, 5000); | |
break; | |
case 'double': | |
score += 20; | |
elements.gameScore.textContent = score; | |
showAchievement('Double Points!', '#ff3860'); | |
break; | |
} | |
} | |
function endGame() { | |
// Update stats | |
gameData.userStats.snake.gamesPlayed++; | |
if (score > gameData.userStats.snake.highScore) { | |
gameData.userStats.snake.highScore = score; | |
} | |
if (snake.length > gameData.userStats.snake.longestSnake) { | |
gameData.userStats.snake.longestSnake = snake.length; | |
} | |
// Update leaderboard | |
updateLeaderboard('snake', 'Player', score); | |
// Save stats | |
saveUserStats(); | |
// Show game over | |
ctx.fillStyle = 'rgba(0, 0, 0, 0.75)'; | |
ctx.fillRect(0, 0, width, height); | |
ctx.fillStyle = '#ff3860'; | |
ctx.font = '48px "Press Start 2P"'; | |
ctx.textAlign = 'center'; | |
ctx.fillText('GAME OVER', width/2, height/2 - 30); | |
ctx.fillStyle = '#fff'; | |
ctx.font = '24px "Press Start 2P"'; | |
ctx.fillText(`SCORE: ${score}`, width/2, height/2 + 30); | |
ctx.fillText('Press any key to continue', width/2, height/2 + 80); | |
// Add to chat | |
addChatMessage('System', `Player scored ${score} in Snake!`); | |
// Show achievement if high score | |
if (score > 100) { | |
showAchievement('Snake Master!', '#00ff41'); | |
} | |
// Set up restart | |
document.addEventListener('keydown', restartGame); | |
} | |
function restartGame() { | |
document.removeEventListener('keydown', restartGame); | |
closeGame(); | |
} | |
// Handle keyboard input | |
document.addEventListener('keydown', (e) => { | |
switch(e.key) { | |
case 'ArrowUp': | |
if (direction !== 'down') direction = 'up'; | |
break; | |
case 'ArrowDown': | |
if (direction !== 'up') direction = 'down'; | |
break; | |
case 'ArrowLeft': | |
if (direction !== 'right') direction = 'left'; | |
break; | |
case 'ArrowRight': | |
if (direction !== 'left') direction = 'right'; | |
break; | |
} | |
}); | |
// Start the game | |
gameData.gameActive = true; | |
gameLoop(0); | |
} | |
// Tetris Game Implementation | |
function startTetrisGame() { | |
// Tetris implementation would go here | |
// Similar structure to snake game | |
showAchievement('Tetris Started!', '#3273dc'); | |
// For now, we'll just show a message | |
const canvas = elements.gameCanvas; | |
const ctx = elements.gameContext; | |
const width = canvas.width; | |
const height = canvas.height; | |
ctx.fillStyle = '#000'; | |
ctx.fillRect(0, 0, width, height); | |
ctx.fillStyle = '#fff'; | |
ctx.font = '36px "Press Start 2P"'; | |
ctx.textAlign = 'center'; | |
ctx.fillText('TETRIS', width/2, height/2 - 50); | |
ctx.font = '24px "Press Start 2P"'; | |
ctx.fillText('Coming Soon!', width/2, height/2 + 20); | |
ctx.font = '18px "Press Start 2P"'; | |
ctx.fillText('Press any key to continue', width/2, height/2 + 80); | |
document.addEventListener('keydown', () => { | |
closeGame(); | |
}); | |
} | |
// Pac-Man Game Implementation | |
function startPacmanGame() { | |
// Pac-Man implementation would go here | |
// Similar structure to snake game | |
showAchievement('Pac-Man Started!', '#ffdd57'); | |
// For now, we'll just show a message | |
const canvas = elements.gameCanvas; | |
const ctx = elements.gameContext; | |
const width = canvas.width; | |
const height = canvas.height; | |
ctx.fillStyle = '#000'; | |
ctx.fillRect(0, 0, width, height); | |
ctx.fillStyle = '#ffdd57'; | |
ctx.font = '36px "Press Start 2P"'; | |
ctx.textAlign = 'center'; | |
ctx.fillText('PAC-MAN', width/2, height/2 - 50); | |
ctx.font = '24px "Press Start 2P"'; | |
ctx.fillText('Coming Soon!', width/2, height/2 + 20); | |
ctx.font = '18px "Press Start 2P"'; | |
ctx.fillText('Press any key to continue', width/2, height/2 + 80); | |
document.addEventListener('keydown', () => { | |
closeGame(); | |
}); | |
} | |
// Leaderboard Functions | |
function loadLeaderboards() { | |
// Snake leaderboard | |
updateLeaderboardDisplay('snake', elements.snakeLeaderboard); | |
// Tetris leaderboard | |
updateLeaderboardDisplay('tetris', elements.tetrisLeaderboard); | |
// Pac-Man leaderboard | |
updateLeaderboardDisplay('pacman', elements.pacmanLeaderboard); | |
} | |
function updateLeaderboard(game, player, score) { | |
// Add new entry | |
gameData.leaderboard[game].push({ player, score }); | |
// Sort descending by score | |
gameData.leaderboard[game].sort((a, b) => b.score - a.score); | |
// Keep only top 10 | |
if (gameData.leaderboard[game].length > 10) { | |
gameData.leaderboard[game] = gameData.leaderboard[game].slice(0, 10); | |
} | |
// Save to localStorage | |
localStorage.setItem(`${game}Leaderboard`, JSON.stringify(gameData.leaderboard[game])); | |
// Update display | |
updateLeaderboardDisplay(game, document.getElementById(`${game}-leaderboard`)); | |
} | |
function updateLeaderboardDisplay(game, element) { | |
element.innerHTML = ''; | |
gameData.leaderboard[game].forEach((entry, index) => { | |
const entryEl = document.createElement('div'); | |
entryEl.className = 'bg-gray-900 p-3 rounded-lg flex justify-between leaderboard-entry'; | |
entryEl.innerHTML = ` | |
<div class="flex items-center"> | |
<span class="w-8 h-8 flex items-center justify-center bg-gray-800 rounded-full mr-3">${index + 1}</span> | |
<span>${entry.player}</span> | |
</div> | |
<span class="text-green-400">${entry.score}</span> | |
`; | |
element.appendChild(entryEl); | |
}); | |
if (gameData.leaderboard[game].length === 0) { | |
const emptyEl = document.createElement('div'); | |
emptyEl.className = 'text-center py-4 text-gray-500'; | |
emptyEl.textContent = 'No scores yet! Be the first!'; | |
element.appendChild(emptyEl); | |
} | |
} | |
// User Stats Functions | |
function loadUserStats() { | |
// Snake stats | |
elements.snakeHighscore.textContent = gameData.userStats.snake.highScore; | |
elements.snakeGames.textContent = gameData.userStats.snake.gamesPlayed; | |
elements.snakeLength.textContent = gameData.userStats.snake.longestSnake; | |
// Tetris stats | |
elements.tetrisHighscore.textContent = gameData.userStats.tetris.highScore; | |
elements.tetrisLines.textContent = gameData.userStats.tetris.linesCleared; | |
elements.tetrisTspins.textContent = gameData.userStats.tetris.tspins; | |
// Pac-Man stats | |
elements.pacmanHighscore.textContent = gameData.userStats.pacman.highScore; | |
elements.pacmanGhosts.textContent = gameData.userStats.pacman.ghostsEaten; | |
elements.pacmanLevel.textContent = gameData.userStats.pacman.levelReached; | |
} | |
function saveUserStats() { | |
localStorage.setItem('userStats', JSON.stringify(gameData.userStats)); | |
loadUserStats(); | |
} | |
// Online Players | |
function generateOnlinePlayers() { | |
const names = [ | |
'RetroGamer', 'PixelMaster', 'ArcadeKing', 'JoystickJedi', | |
'ByteBuster', 'NostalgiaNinja', 'HighScoreHero', 'ControllerQueen', | |
'8BitWarrior', 'GameGenius', 'DoseCoinMiner', 'PacFanatic', | |
'SnakeCharmer', 'TetrisTitan', 'GhostHunter', 'PowerUpPirate' | |
]; | |
elements.onlinePlayers.innerHTML = ''; | |
// Generate 8-12 random players | |
const count = Math.floor(Math.random() * 5) + 8; | |
for (let i = 0; i < count; i++) { | |
const name = names[Math.floor(Math.random() * names.length)]; | |
const status = Math.random() > 0.3 ? 'online' : 'ingame'; | |
const playerEl = document.createElement('div'); | |
playerEl.className = `flex items-center p-2 mb-2 rounded-lg ${status === 'online' ? 'bg-gray-700 online-user' : 'bg-purple-900'}`; | |
playerEl.innerHTML = ` | |
<div class="w-3 h-3 rounded-full ${status === 'online' ? 'bg-green-500' : 'bg-purple-500'} mr-3"></div> | |
<span>${name}</span> | |
${status === 'ingame' ? '<span class="ml-auto text-xs bg-purple-700 px-2 py-1 rounded">in game</span>' : ''} | |
`; | |
elements.onlinePlayers.appendChild(playerEl); | |
} | |
// Update online count | |
elements.onlineCount.textContent = count; | |
} | |
// Chat System | |
function sendChatMessage() { | |
const message = elements.chatInput.value.trim(); | |
if (message) { | |
addChatMessage('You', message); | |
elements.chatInput.value = ''; | |
// Simulate bot response | |
setTimeout(() => { | |
const responses = [ | |
"Nice score!", | |
"Anyone want to play multiplayer?", | |
"I just unlocked a new achievement!", | |
"Check out my new NFT skin!", | |
"The Snake game is so addictive!", | |
"How do you get DoseCoins?", | |
"I'm stuck on level 5 of Pac-Man", | |
"Tetris T-spins are so satisfying!" | |
]; | |
const botNames = ['RetroGamer', 'PixelMaster', 'ArcadeKing', 'DoseCoinMiner']; | |
const botName = botNames[Math.floor(Math.random() * botNames.length)]; | |
const response = responses[Math.floor(Math.random() * responses.length)]; | |
addChatMessage(botName, response); | |
}, 1000 + Math.random() * 2000); | |
} | |
} | |
function addChatMessage(sender, message) { | |
const messageEl = document.createElement('div'); | |
messageEl.className = 'mb-2'; | |
messageEl.innerHTML = ` | |
<span class="font-bold ${sender === 'You' ? 'text-green-400' : 'text-blue-400'}">${sender}:</span> | |
<span>${message}</span> | |
`; | |
elements.chatMessages.appendChild(messageEl); | |
elements.chatMessages.scrollTop = elements.chatMessages.scrollHeight; | |
} | |
function startChatBots() { | |
// Initial bot messages | |
setTimeout(() => { | |
addChatMessage('ArcadeKing', 'Welcome to DoseGame Arcade Universe!'); | |
}, 1000); | |
setTimeout(() => { | |
addChatMessage('PixelMaster', 'Check out the new NFT skins in the shop!'); | |
}, 3000); | |
setTimeout(() => { | |
addChatMessage('RetroGamer', 'Just got a new high score in Snake!'); | |
}, 5000); | |
} | |
// Achievements | |
function generateAchievements() { | |
const achievements = [ | |
{ title: 'First Game', desc: 'Play your first game', icon: 'fa-gamepad', color: '#ff3860' }, | |
{ title: 'Snake Charmer', desc: 'Score 100+ in Snake', icon: 'fa-snake', color: '#00ff41' }, | |
{ title: 'Tetris Master', desc: 'Clear 100 lines in Tetris', icon: 'fa-cubes', color: '#3273dc' }, | |
{ title: 'Ghost Hunter', desc: 'Eat 50 ghosts in Pac-Man', icon: 'fa-ghost', color: '#ff88ff' }, | |
{ title: 'DoseCoin Miner', desc: 'Earn 1000 DoseCoins', icon: 'fa-coins', color: '#ffdd57' }, | |
{ title: 'Arcade Legend', desc: 'Complete all games', icon: 'fa-crown', color: '#b86bff' } | |
]; | |
achievements.forEach(achievement => { | |
const achievementEl = document.createElement('div'); | |
achievementEl.className = 'flex items-center p-3 mb-2 bg-gray-700 rounded-lg'; | |
achievementEl.innerHTML = ` | |
<div class="w-10 h-10 flex items-center justify-center rounded-full mr-3" style="background: ${achievement.color}"> | |
<i class="fas ${achievement.icon}"></i> | |
</div> | |
<div> | |
<div class="font-bold">${achievement.title}</div> | |
<div class="text-sm text-gray-300">${achievement.desc}</div> | |
</div> | |
`; | |
elements.achievements.appendChild(achievementEl); | |
}); | |
} | |
function showAchievement(title, color) { | |
const achievementEl = document.createElement('div'); | |
achievementEl.className = 'achievement-popup bg-gray-800 rounded-lg p-4 mb-4 flex items-center border-l-4 shadow-lg'; | |
achievementEl.style.borderLeftColor = color; | |
achievementEl.innerHTML = ` | |
<div class="mr-3 text-2xl" style="color: ${color}"> | |
<i class="fas fa-trophy"></i> | |
</div> | |
<div> | |
<div class="font-bold">Achievement Unlocked!</div> | |
<div>${title}</div> | |
</div> | |
`; | |
elements.achievementContainer.appendChild(achievementEl); | |
// Remove after delay | |
setTimeout(() => { | |
achievementEl.remove(); | |
}, 5000); | |
} | |
// NFT Shop | |
function generateNFTShop() { | |
const skins = [ | |
{ id: 1, name: 'Golden Snake', price: 500, color: '#ffdd57', icon: 'fa-snake' }, | |
{ id: 2, name: 'Neon Pac-Man', price: 750, color: '#00d1b2', icon: 'fa-ghost' }, | |
{ id: 3, name: 'Cyber Tetris', price: 600, color: '#b86bff', icon: 'fa-cubes' }, | |
{ id: 4, name: 'Retro Bundle', price: 1500, color: '#ff3860', icon: 'fa-gamepad' }, | |
{ id: 5, name: 'DoseCoin Miner', price: 2000, color: '#3273dc', icon: 'fa-coins' }, | |
{ id: 6, name: 'Arcade Legend', price: 3000, color: '#00ff41', icon: 'fa-crown' } | |
]; | |
const shopContainer = document.querySelector('#shop-section .grid'); | |
shopContainer.innerHTML = ''; | |
skins.forEach(skin => { | |
const owned = gameData.ownedSkins.includes(skin.id); | |
const skinEl = document.createElement('div'); | |
skinEl.className = 'bg-gray-900 rounded-xl overflow-hidden'; | |
skinEl.innerHTML = ` | |
<div class="h-40 flex items-center justify-center" style="background: ${skin.color}"> | |
<i class="fas ${skin.icon} fa-3x"></i> | |
</div> | |
<div class="p-4"> | |
<h4 class="font-bold text-lg mb-1">${skin.name}</h4> | |
<div class="flex justify-between items-center mb-3"> | |
<span><i class="fas fa-coins text-yellow-400"></i> ${skin.price}</span> | |
${owned ? '<span class="text-green-400">OWNED</span>' : ''} | |
</div> | |
<button class="retro-btn w-full ${owned ? 'retro-btn-secondary' : 'retro-btn-primary'} buy-skin" data-id="${skin.id}" data-price="${skin.price}" ${owned ? 'disabled' : ''}> | |
${owned ? 'EQUIP' : 'BUY NOW'} | |
</button> | |
</div> | |
`; | |
shopContainer.appendChild(skinEl); | |
}); | |
// Add event listeners to buy buttons | |
document.querySelectorAll('.buy-skin').forEach(button => { | |
button.addEventListener('click', () => { | |
const id = parseInt(button.dataset.id); | |
const price = parseInt(button.dataset.price); | |
if (gameData.dosecoins >= price) { | |
gameData.dosecoins -= price; | |
gameData.ownedSkins.push(id); | |
// Save data | |
localStorage.setItem('dosecoins', gameData.dosecoins.toString()); | |
localStorage.setItem('ownedSkins', JSON.stringify(gameData.ownedSkins)); | |
// Update UI | |
updateCoinDisplay(); | |
generateNFTShop(); | |
generateInventory(); | |
// Show achievement | |
showAchievement('New Skin Unlocked!', '#b86bff'); | |
// Add to chat | |
const skinName = button.parentElement.querySelector('h4').textContent; | |
addChatMessage('System', `You purchased the | |
<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=MagicBullets/dosegame-com" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |