vspace / index.html
vikassabbi's picture
Add 3 files
3d3a60e verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>8-Bit Pokémon Adventure</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* Pixel art styling */
.pixel {
image-rendering: pixelated;
image-rendering: -moz-crisp-edges;
image-rendering: crisp-edges;
}
.pixel-font {
font-family: 'Press Start 2P', cursive;
}
.dialog-box {
border: 4px solid #000;
background-color: #e0f8d0;
box-shadow: 4px 4px 0 rgba(0,0,0,0.2);
}
.health-bar {
height: 10px;
background: linear-gradient(to right, #ff0000, #ffcc00);
border: 2px solid #000;
box-sizing: border-box;
}
.pixel-button {
background-color: #e0f8d0;
border: 3px solid #000;
box-shadow: 3px 3px 0 rgba(0,0,0,0.2);
transition: all 0.1s;
}
.pixel-button:hover {
transform: translate(1px, 1px);
box-shadow: 2px 2px 0 rgba(0,0,0,0.2);
}
.pixel-button:active {
transform: translate(3px, 3px);
box-shadow: none;
}
.battle-screen {
background-color: #88c070;
}
.grass {
background-color: #48d0b0;
}
.water {
background-color: #6890f0;
}
.fire {
background-color: #f08030;
}
.electric {
background-color: #f8d030;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-5px); }
40%, 80% { transform: translateX(5px); }
}
.shake {
animation: shake 0.4s;
}
@keyframes flash {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
.flash {
animation: flash 0.3s 2;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.float {
animation: float 2s infinite;
}
/* Pixel sprites */
.sprite {
width: 64px;
height: 64px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.trainer-sprite {
width: 48px;
height: 48px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
/* Game map */
.map-tile {
width: 32px;
height: 32px;
background-size: contain;
}
.grass-tile {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect width="32" height="32" fill="%2348d0b0"/><rect x="0" y="24" width="32" height="8" fill="%2378c850"/><circle cx="8" cy="20" r="2" fill="%2378c850"/><circle cx="24" cy="18" r="1" fill="%2378c850"/><circle cx="16" cy="22" r="1" fill="%2378c850"/></svg>');
}
.tree-tile {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect width="32" height="32" fill="%2348d0b0"/><rect x="14" y="16" width="4" height="16" fill="%23a07050"/><rect x="8" y="8" width="16" height="8" fill="%2378c850"/></svg>');
}
.water-tile {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect width="32" height="32" fill="%236890f0"/><rect x="0" y="28" width="8" height="4" fill="%235888e0" opacity="0.7"/><rect x="16" y="26" width="8" height="6" fill="%235888e0" opacity="0.7"/><rect x="8" y="30" width="8" height="2" fill="%235888e0" opacity="0.7"/></svg>');
}
.path-tile {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect width="32" height="32" fill="%23e0c068"/><rect x="0" y="0" width="32" height="32" fill="%23e0c068" patternUnits="userSpaceOnUse" patternTransform="rotate(45 16 16)" patternContentUnits="userSpaceOnUse"><pattern id="diagonalHatch" width="4" height="4" patternTransform="rotate(45 16 16)" patternUnits="userSpaceOnUse"><rect width="2" height="4" fill="%23d0b050"/></pattern><rect width="32" height="32" fill="url(%23diagonalHatch)"/></rect></svg>');
}
/* Battle sprites */
.pikachu-sprite {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><rect width="64" height="64" fill="transparent"/><rect x="20" y="32" width="24" height="20" fill="%23f8d030"/><rect x="16" y="36" width="8" height="12" fill="%23f8d030"/><rect x="40" y="36" width="8" height="12" fill="%23f8d030"/><rect x="24" y="16" width="16" height="16" fill="%23f8d030"/><rect x="24" y="12" width="4" height="4" fill="%23f8d030"/><rect x="36" y="12" width="4" height="4" fill="%23f8d030"/><circle cx="28" cy="24" r="2" fill="%23000"/><circle cx="36" cy="24" r="2" fill="%23000"/><rect x="32" y="28" width="4" height="2" fill="%23000"/><path d="M28,40 L36,40 L34,44 L30,44 Z" fill="%23000"/><path d="M44,20 L52,12 L56,16 L48,24 Z" fill="%23f8d030" stroke="%23000" stroke-width="1"/><path d="M12,24 L4,16 L8,12 L16,20 Z" fill="%23f8d030" stroke="%23000" stroke-width="1"/></svg>');
}
.charmander-sprite {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><rect width="64" height="64" fill="transparent"/><rect x="20" y="28" width="24" height="24" fill="%23f08030"/><rect x="16" y="32" width="8" height="16" fill="%23f08030"/><rect x="40" y="32" width="8" height="16" fill="%23f08030"/><rect x="24" y="16" width="16" height="12" fill="%23f08030"/><circle cx="28" cy="24" r="2" fill="%23000"/><circle cx="36" cy="24" r="2" fill="%23000"/><rect x="32" y="28" width="4" height="2" fill="%23000"/><path d="M28,44 L36,44 L34,48 L30,48 Z" fill="%23000"/><path d="M44,24 L48,20 L52,24 L48,28 Z" fill="%23ff0000"/><path d="M44,24 L48,20 L52,24 L48,28 Z" fill="%23ff0000" stroke="%23000" stroke-width="1"/></svg>');
}
.squirtle-sprite {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><rect width="64" height="64" fill="transparent"/><circle cx="32" cy="36" r="16" fill="%236890f0"/><circle cx="32" cy="24" r="12" fill="%236890f0"/><circle cx="28" cy="20" r="2" fill="%23000"/><circle cx="36" cy="20" r="2" fill="%23000"/><rect x="30" cy="28" width="4" height="2" fill="%23000"/><rect x="20" y="36" width="8" height="12" fill="%236890f0"/><rect x="36" y="36" width="8" height="12" fill="%236890f0"/><path d="M24,48 L40,48 L36,52 L28,52 Z" fill="%23000"/></svg>');
}
.bulbasaur-sprite {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><rect width="64" height="64" fill="transparent"/><circle cx="32" cy="40" r="16" fill="%2378c850"/><circle cx="32" cy="24" r="12" fill="%2378c850"/><circle cx="28" cy="20" r="2" fill="%23000"/><circle cx="36" cy="20" r="2" fill="%23000"/><rect x="30" cy="28" width="4" height="2" fill="%23000"/><rect x="20" y="40" width="8" height="12" fill="%2378c850"/><rect x="36" y="40" width="8" height="12" fill="%2378c850"/><path d="M24,52 L40,52 L36,56 L28,56 Z" fill="%23000"/><circle cx="32" cy="8" r="6" fill="%2348d0b0"/><rect x="30" y="8" width="4" height="8" fill="%2348d0b0"/></svg>');
}
.rattata-sprite {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><rect width="64" height="64" fill="transparent"/><rect x="20" y="28" width="24" height="16" fill="%23a890f0"/><rect x="16" y="32" width="8" height="8" fill="%23a890f0"/><rect x="40" y="32" width="8" height="8" fill="%23a890f0"/><rect x="24" y="20" width="16" height="8" fill="%23a890f0"/><circle cx="28" cy="24" r="2" fill="%23000"/><circle cx="36" cy="24" r="2" fill="%23000"/><rect x="32" y="28" width="4" height="2" fill="%23000"/><path d="M24,40 L40,40 L36,44 L28,44 Z" fill="%23000"/><rect x="44" y="28" width="4" height="4" fill="%23a890f0"/><rect x="48" y="24" width="4" height="12" fill="%23a890f0"/></svg>');
}
.pidgey-sprite {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><rect width="64" height="64" fill="transparent"/><rect x="24" y="32" width="16" height="12" fill="%23f8d058"/><rect x="20" y="36" width="8" height="8" fill="%23f8d058"/><rect x="36" y="36" width="8" height="8" fill="%23f8d058"/><rect x="28" y="24" width="8" height="8" fill="%23f8d058"/><circle cx="30" cy="28" r="2" fill="%23000"/><circle cx="34" cy="28" r="2" fill="%23000"/><rect x="32" y="32" width="4" height="2" fill="%23000"/><path d="M28,40 L36,40 L34,44 L30,44 Z" fill="%23000"/><rect x="40" y="28" width="12" height="4" fill="%23f8d058"/><rect x="48" y="24" width="4" height="8" fill="%23f8d058"/></svg>');
}
/* Trainer sprites */
.player-sprite {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><rect width="48" height="48" fill="transparent"/><rect x="16" y="24" width="16" height="16" fill="%233088f8"/><rect x="16" y="16" width="16" height="8" fill="%23f8c870"/><rect x="20" y="12" width="8" height="4" fill="%23000"/><circle cx="20" cy="14" r="2" fill="%23f8c870"/><circle cx="28" cy="14" r="2" fill="%23f8c870"/><rect x="24" y="18" width="4" height="2" fill="%23000"/><rect x="12" y="24" width="4" height="12" fill="%233088f8"/><rect x="32" y="24" width="4" height="12" fill="%233088f8"/><rect x="16" y="40" width="4" height="4" fill="%23000"/><rect x="28" y="40" width="4" height="4" fill="%23000"/></svg>');
}
.rival-sprite {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><rect width="48" height="48" fill="transparent"/><rect x="16" y="24" width="16" height="16" fill="%23e05050"/><rect x="16" y="16" width="16" height="8" fill="%23f8c870"/><rect x="20" y="12" width="8" height="4" fill="%23000"/><circle cx="20" cy="14" r="2" fill="%23f8c870"/><circle cx="28" cy="14" r="2" fill="%23f8c870"/><rect x="24" y="18" width="4" height="2" fill="%23000"/><rect x="12" y="24" width="4" height="12" fill="%23e05050"/><rect x="32" y="24" width="4" height="12" fill="%23e05050"/><rect x="16" y="40" width="4" height="4" fill="%23000"/><rect x="28" y="40" width="4" height="4" fill="%23000"/></svg>');
}
/* Battle animations */
.tackle-animation {
animation: tackle 0.3s;
}
@keyframes tackle {
0% { transform: translateX(0); }
50% { transform: translateX(20px); }
100% { transform: translateX(0); }
}
.ember-animation {
position: relative;
}
.ember-animation::after {
content: '';
position: absolute;
top: 50%;
left: 100%;
width: 32px;
height: 32px;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect width="32" height="32" fill="transparent"/><circle cx="16" cy="16" r="8" fill="%23ff0000"/><circle cx="12" cy="12" r="4" fill="%23ffcc00"/><circle cx="20" cy="12" r="3" fill="%23ffcc00"/><circle cx="16" cy="20" r="3" fill="%23ffcc00"/></svg>');
animation: ember 0.5s forwards;
}
@keyframes ember {
0% { transform: translate(0, -50%) scale(0.5); opacity: 0; }
20% { transform: translate(0, -50%) scale(1); opacity: 1; }
100% { transform: translate(100px, -50%) scale(0.5); opacity: 0; }
}
.thunderbolt-animation {
position: relative;
}
.thunderbolt-animation::after {
content: '';
position: absolute;
top: 50%;
left: 100%;
width: 32px;
height: 32px;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect width="32" height="32" fill="transparent"/><path d="M16,4 L24,16 L16,12 L24,28 L12,20 L16,24 Z" fill="%23f8d030"/></svg>');
animation: thunderbolt 0.4s forwards;
}
@keyframes thunderbolt {
0% { transform: translate(0, -50%) scale(0.5); opacity: 0; }
20% { transform: translate(0, -50%) scale(1); opacity: 1; }
100% { transform: translate(100px, -50%) scale(0.5); opacity: 0; }
}
.bubble-animation {
position: relative;
}
.bubble-animation::after {
content: '';
position: absolute;
top: 50%;
left: 100%;
width: 24px;
height: 24px;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><rect width="24" height="24" fill="transparent"/><circle cx="12" cy="12" r="8" fill="%236890f0" opacity="0.7"/><circle cx="8" cy="8" r="3" fill="%23ffffff" opacity="0.9"/></svg>');
animation: bubble 0.6s forwards;
}
@keyframes bubble {
0% { transform: translate(0, -50%) scale(0.5); opacity: 0; }
20% { transform: translate(0, -50%) scale(1); opacity: 1; }
100% { transform: translate(100px, -50%) scale(0.5); opacity: 0; }
}
.vine-whip-animation {
position: relative;
}
.vine-whip-animation::after {
content: '';
position: absolute;
top: 50%;
left: 100%;
width: 64px;
height: 8px;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="64" height="8" viewBox="0 0 64 8"><rect width="64" height="8" fill="transparent"/><rect x="0" y="2" width="64" height="4" fill="%2378c850"/><rect x="8" y="0" width="4" height="8" fill="%2378c850"/><rect x="24" y="0" width="4" height="8" fill="%2378c850"/><rect x="40" y="0" width="4" height="8" fill="%2378c850"/><rect x="56" y="0" width="4" height="8" fill="%2378c850"/></svg>');
animation: vineWhip 0.5s forwards;
}
@keyframes vineWhip {
0% { transform: translate(0, -50%) scaleX(0.1); opacity: 0; }
20% { transform: translate(0, -50%) scaleX(1); opacity: 1; }
100% { transform: translate(100px, -50%) scaleX(0.1); opacity: 0; }
}
</style>
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
</head>
<body class="bg-gray-900 text-white pixel-font">
<div id="game-container" class="max-w-3xl mx-auto p-4">
<!-- Title Screen -->
<div id="title-screen" class="text-center">
<h1 class="text-4xl mb-8 text-yellow-300">POKÉMON ADVENTURE</h1>
<div class="sprite mx-auto mb-8 pikachu-sprite float"></div>
<div class="flex flex-col space-y-4 max-w-xs mx-auto">
<button onclick="startGame()" class="pixel-button px-4 py-2 text-lg">NEW GAME</button>
<button onclick="loadGame()" class="pixel-button px-4 py-2 text-lg">LOAD GAME</button>
<button onclick="showOptions()" class="pixel-button px-4 py-2 text-lg">OPTIONS</button>
</div>
</div>
<!-- Starter Selection -->
<div id="starter-screen" class="hidden text-center">
<h2 class="text-2xl mb-4">CHOOSE YOUR STARTER POKÉMON</h2>
<div class="flex justify-around mb-8">
<div class="cursor-pointer" onclick="selectStarter('charmander')">
<div class="sprite charmander-sprite mx-auto"></div>
<p class="mt-2">CHARMANDER</p>
</div>
<div class="cursor-pointer" onclick="selectStarter('squirtle')">
<div class="sprite squirtle-sprite mx-auto"></div>
<p class="mt-2">SQUIRTLE</p>
</div>
<div class="cursor-pointer" onclick="selectStarter('bulbasaur')">
<div class="sprite bulbasaur-sprite mx-auto"></div>
<p class="mt-2">BULBASAUR</p>
</div>
</div>
<div class="dialog-box p-4 mb-4">
<p>These are the three starter Pokémon available in this region. Choose wisely!</p>
</div>
</div>
<!-- World Map -->
<div id="world-screen" class="hidden">
<div class="flex justify-between mb-4">
<div>
<p>PLAYER: <span id="player-name">ASH</span></p>
<p>POKÉDEX: <span id="pokedex-count">1</span> SEEN</p>
</div>
<div>
<p>TIME: <span id="game-time">10:00</span></p>
<p>MONEY: $<span id="player-money">1000</span></p>
</div>
</div>
<div id="map-container" class="relative border-4 border-gray-800 bg-gray-800 mx-auto" style="width: 512px; height: 320px;">
<!-- Map tiles will be generated here -->
<div id="player" class="absolute trainer-sprite player-sprite" style="top: 144px; left: 240px;"></div>
<div id="rival" class="absolute trainer-sprite rival-sprite hidden" style="top: 96px; left: 192px;"></div>
<div id="wild-pokemon" class="absolute sprite hidden" style="top: 80px; left: 320px;"></div>
</div>
<div class="dialog-box p-4 mt-4">
<p id="map-message">You are in the tall grass. Wild Pokémon may appear!</p>
</div>
<div class="grid grid-cols-2 gap-4 mt-4">
<button onclick="openMenu('pokemon')" class="pixel-button px-4 py-2">POKÉMON</button>
<button onclick="openMenu('bag')" class="pixel-button px-4 py-2">BAG</button>
<button onclick="openMenu('player')" class="pixel-button px-4 py-2">PLAYER</button>
<button onclick="openMenu('save')" class="pixel-button px-4 py-2">SAVE</button>
</div>
</div>
<!-- Battle Screen -->
<div id="battle-screen" class="hidden battle-screen">
<div class="relative" style="height: 240px;">
<!-- Enemy Pokémon -->
<div id="enemy-pokemon" class="absolute sprite" style="top: 40px; right: 40px;"></div>
<div class="absolute bg-white bg-opacity-30 border-2 border-black" style="top: 20px; right: 20px; width: 120px; height: 40px;">
<p class="text-right px-2"><span id="enemy-name">PIDGEY</span> Lv.<span id="enemy-level">5</span></p>
<div class="health-bar mx-2" id="enemy-health" style="width: 100px;"></div>
</div>
<!-- Player Pokémon -->
<div id="player-pokemon" class="absolute sprite" style="bottom: 60px; left: 40px;"></div>
<div class="absolute bg-white bg-opacity-30 border-2 border-black" style="bottom: 20px; left: 20px; width: 160px; height: 60px;">
<p class="text-left px-2"><span id="player-pokemon-name">PIKACHU</span> Lv.<span id="player-pokemon-level">5</span></p>
<p class="text-left px-2">HP: <span id="player-pokemon-hp">20</span>/<span id="player-pokemon-max-hp">20</span></p>
<div class="health-bar mx-2" id="player-health" style="width: 140px;"></div>
</div>
</div>
<div id="battle-dialog" class="dialog-box p-4">
<p>A wild <span id="battle-pokemon-name">PIDGEY</span> appeared!</p>
</div>
<div id="battle-options" class="grid grid-cols-2 gap-4 mt-4">
<button onclick="battleAction('fight')" class="pixel-button px-4 py-2">FIGHT</button>
<button onclick="battleAction('pokemon')" class="pixel-button px-4 py-2">POKÉMON</button>
<button onclick="battleAction('bag')" class="pixel-button px-4 py-2">BAG</button>
<button onclick="battleAction('run')" class="pixel-button px-4 py-2">RUN</button>
</div>
<div id="move-options" class="hidden grid grid-cols-2 gap-4 mt-4">
<!-- Move buttons will be added here dynamically -->
</div>
</div>
<!-- Battle Result Screen -->
<div id="battle-result" class="hidden text-center">
<div class="dialog-box p-4 mb-4 mx-auto max-w-md">
<p id="result-message">PIKACHU gained 100 EXP. Points!</p>
</div>
<button onclick="returnToWorld()" class="pixel-button px-4 py-2">CONTINUE</button>
</div>
<!-- Pokémon Menu -->
<div id="pokemon-menu" class="hidden">
<h2 class="text-2xl mb-4">POKÉMON</h2>
<div id="pokemon-list" class="space-y-2 mb-4">
<!-- Pokémon list will be added here dynamically -->
</div>
<button onclick="closeMenu()" class="pixel-button px-4 py-2">BACK</button>
</div>
<!-- Bag Menu -->
<div id="bag-menu" class="hidden">
<h2 class="text-2xl mb-4">BAG</h2>
<div class="flex space-x-4 mb-4">
<button onclick="showBagCategory('pokeballs')" class="pixel-button px-4 py-2">POKÉBALLS</button>
<button onclick="showBagCategory('potions')" class="pixel-button px-4 py-2">POTIONS</button>
<button onclick="showBagCategory('other')" class="pixel-button px-4 py-2">OTHER</button>
</div>
<div id="bag-items" class="space-y-2 mb-4">
<!-- Bag items will be added here dynamically -->
</div>
<button onclick="closeMenu()" class="pixel-button px-4 py-2">BACK</button>
</div>
<!-- Player Menu -->
<div id="player-menu" class="hidden text-center">
<h2 class="text-2xl mb-4">PLAYER INFO</h2>
<div class="trainer-sprite player-sprite mx-auto mb-4"></div>
<div class="dialog-box p-4 mb-4 mx-auto max-w-md">
<p>NAME: <span id="menu-player-name">ASH</span></p>
<p>MONEY: $<span id="menu-player-money">1000</span></p>
<p>POKÉDEX: <span id="menu-pokedex-count">1</span> SEEN</p>
<p>PLAY TIME: <span id="menu-game-time">10:00</span></p>
</div>
<button onclick="closeMenu()" class="pixel-button px-4 py-2">BACK</button>
</div>
<!-- Save Menu -->
<div id="save-menu" class="hidden text-center">
<h2 class="text-2xl mb-4">SAVE GAME</h2>
<div class="dialog-box p-4 mb-4 mx-auto max-w-md">
<p>Would you like to save your game?</p>
</div>
<div class="flex justify-center space-x-4">
<button onclick="saveGame()" class="pixel-button px-4 py-2">YES</button>
<button onclick="closeMenu()" class="pixel-button px-4 py-2">NO</button>
</div>
</div>
<!-- Save Confirmation -->
<div id="save-confirm" class="hidden text-center">
<div class="dialog-box p-4 mb-4 mx-auto max-w-md">
<p>Game saved successfully!</p>
</div>
<button onclick="closeMenu()" class="pixel-button px-4 py-2">CONTINUE</button>
</div>
</div>
<script>
// Game state
const gameState = {
player: {
name: 'ASH',
money: 1000,
pokedex: [],
pokemon: [],
items: {
pokeballs: [
{ name: 'POKÉ BALL', quantity: 5 },
{ name: 'GREAT BALL', quantity: 2 }
],
potions: [
{ name: 'POTION', quantity: 3 },
{ name: 'SUPER POTION', quantity: 1 }
],
other: [
{ name: 'POKÉ DOLL', quantity: 1 },
{ name: 'ESCAPE ROPE', quantity: 1 }
]
}
},
currentScreen: 'title',
inBattle: false,
battle: {
enemy: null,
playerPokemon: null,
turn: 'player'
},
starterSelected: false,
gameTime: 10 * 60, // 10:00 in minutes
map: {
width: 16,
height: 10,
playerPosition: { x: 7, y: 4 },
rivalPosition: { x: 6, y: 3 },
wildPokemon: null
}
};
// Pokémon data
const pokemonData = {
pikachu: {
name: 'PIKACHU',
type: 'electric',
sprite: 'pikachu-sprite',
baseStats: { hp: 35, attack: 55, defense: 40, speed: 90 },
moves: [
{ name: 'TACKLE', power: 40, accuracy: 100, type: 'normal', pp: 35 },
{ name: 'THUNDERBOLT', power: 90, accuracy: 100, type: 'electric', pp: 15 }
]
},
charmander: {
name: 'CHARMANDER',
type: 'fire',
sprite: 'charmander-sprite',
baseStats: { hp: 39, attack: 52, defense: 43, speed: 65 },
moves: [
{ name: 'TACKLE', power: 40, accuracy: 100, type: 'normal', pp: 35 },
{ name: 'EMBER', power: 40, accuracy: 100, type: 'fire', pp: 25 }
]
},
squirtle: {
name: 'SQUIRTLE',
type: 'water',
sprite: 'squirtle-sprite',
baseStats: { hp: 44, attack: 48, defense: 65, speed: 43 },
moves: [
{ name: 'TACKLE', power: 40, accuracy: 100, type: 'normal', pp: 35 },
{ name: 'BUBBLE', power: 40, accuracy: 100, type: 'water', pp: 30 }
]
},
bulbasaur: {
name: 'BULBASAUR',
type: 'grass',
sprite: 'bulbasaur-sprite',
baseStats: { hp: 45, attack: 49, defense: 49, speed: 45 },
moves: [
{ name: 'TACKLE', power: 40, accuracy: 100, type: 'normal', pp: 35 },
{ name: 'VINE WHIP', power: 45, accuracy: 100, type: 'grass', pp: 25 }
]
},
rattata: {
name: 'RATTATA',
type: 'normal',
sprite: 'rattata-sprite',
baseStats: { hp: 30, attack: 56, defense: 35, speed: 72 },
moves: [
{ name: 'TACKLE', power: 40, accuracy: 100, type: 'normal', pp: 35 }
]
},
pidgey: {
name: 'PIDGEY',
type: 'normal',
sprite: 'pidgey-sprite',
baseStats: { hp: 40, attack: 45, defense: 40, speed: 56 },
moves: [
{ name: 'TACKLE', power: 40, accuracy: 100, type: 'normal', pp: 35 }
]
}
};
// Wild Pokémon encounter table
const wildPokemon = [
{ name: 'rattata', level: 2, chance: 0.5 },
{ name: 'pidgey', level: 3, chance: 0.3 },
{ name: 'pikachu', level: 5, chance: 0.2 }
];
// Type effectiveness chart
const typeEffectiveness = {
normal: { normal: 1, fire: 1, water: 1, electric: 1, grass: 1 },
fire: { normal: 1, fire: 0.5, water: 0.5, electric: 1, grass: 2 },
water: { normal: 1, fire: 2, water: 0.5, electric: 1, grass: 0.5 },
electric: { normal: 1, fire: 1, water: 2, electric: 0.5, grass: 0.5 },
grass: { normal: 1, fire: 0.5, water: 2, electric: 1, grass: 0.5 }
};
// Initialize game
function initGame() {
// Set up event listeners for movement
document.addEventListener('keydown', handleKeyPress);
// Start game clock
setInterval(updateGameTime, 1000);
// Generate initial map
generateMap();
}
// Start a new game
function startGame() {
document.getElementById('title-screen').classList.add('hidden');
document.getElementById('starter-screen').classList.remove('hidden');
gameState.currentScreen = 'starter';
}
// Load game (placeholder)
function loadGame() {
alert('Load game functionality not implemented in this demo.');
}
// Show options (placeholder)
function showOptions() {
alert('Options menu not implemented in this demo.');
}
// Select starter Pokémon
function selectStarter(starter) {
const starterPokemon = {
...pokemonData[starter],
level: 5,
currentHp: calculateStat(pokemonData[starter].baseStats.hp, 5),
experience: 0,
moves: pokemonData[starter].moves.map(move => ({ ...move, currentPp: move.pp }))
};
gameState.player.pokemon.push(starterPokemon);
gameState.player.pokedex.push(starterPokemon.name);
gameState.starterSelected = true;
document.getElementById('starter-screen').classList.add('hidden');
document.getElementById('world-screen').classList.remove('hidden');
gameState.currentScreen = 'world';
// Show welcome message
showDialog(`You chose ${starterPokemon.name}! Good luck on your journey!`);
}
// Generate a Pokémon with random level
function generatePokemon(pokemonName, level) {
const baseData = pokemonData[pokemonName];
return {
...baseData,
level: level,
currentHp: calculateStat(baseData.baseStats.hp, level),
maxHp: calculateStat(baseData.baseStats.hp, level),
moves: baseData.moves.map(move => ({ ...move, currentPp: move.pp }))
};
}
// Calculate a stat based on level
function calculateStat(base, level) {
return Math.floor((2 * base * level) / 100) + level + 10;
}
// Calculate damage
function calculateDamage(attacker, defender, move) {
const attackStat = attacker.baseStats.attack;
const defenseStat = defender.baseStats.defense;
const level = attacker.level;
const power = move.power;
const effectiveness = typeEffectiveness[move.type][defender.type] || 1;
// Simplified damage formula
const damage = Math.floor((((2 * level / 5 + 2) * attackStat * power / defenseStat) / 50 + 2) * effectiveness);
return damage;
}
// Generate the game map
function generateMap() {
const mapContainer = document.getElementById('map-container');
mapContainer.innerHTML = '';
// Add player sprite back
const player = document.createElement('div');
player.id = 'player';
player.className = 'absolute trainer-sprite player-sprite';
player.style.top = `${gameState.map.playerPosition.y * 32}px`;
player.style.left = `${gameState.map.playerPosition.x * 32}px`;
mapContainer.appendChild(player);
// Generate tiles
for (let y = 0; y < gameState.map.height; y++) {
for (let x = 0; x < gameState.map.width; x++) {
const tile = document.createElement('div');
tile.className = 'absolute map-tile';
// Simple map generation
if (x === 0 || y === 0 || x === gameState.map.width - 1 || y === gameState.map.height - 1) {
tile.classList.add('tree-tile');
} else if (x > 3 && x < 12 && y > 2 && y < 7) {
tile.classList.add('grass-tile');
} else if (x === 8 && y === 5) {
tile.classList.add('water-tile');
} else {
tile.classList.add('path-tile');
}
tile.style.top = `${y * 32}px`;
tile.style.left = `${x * 32}px`;
mapContainer.appendChild(tile);
}
}
// Add rival if not in battle
if (!gameState.inBattle) {
const rival = document.createElement('div');
rival.id = 'rival';
rival.className = 'absolute trainer-sprite rival-sprite';
rival.style.top = `${gameState.map.rivalPosition.y * 32}px`;
rival.style.left = `${gameState.map.rivalPosition.x * 32}px`;
mapContainer.appendChild(rival);
}
}
// Handle key presses for movement
function handleKeyPress(e) {
if (gameState.currentScreen !== 'world' || gameState.inBattle) return;
let newX = gameState.map.playerPosition.x;
let newY = gameState.map.playerPosition.y;
switch(e.key) {
case 'ArrowUp':
newY = Math.max(0, newY - 1);
break;
case 'ArrowDown':
newY = Math.min(gameState.map.height - 1, newY + 1);
break;
case 'ArrowLeft':
newX = Math.max(0, newX - 1);
break;
case 'ArrowRight':
newX = Math.min(gameState.map.width - 1, newX + 1);
break;
default:
return;
}
// Check if the new position is valid (not a tree)
const isTree = (newX === 0 || newY === 0 || newX === gameState.map.width - 1 || newY === gameState.map.height - 1);
if (!isTree) {
gameState.map.playerPosition.x = newX;
gameState.map.playerPosition.y = newY;
// Update player position on screen
const player = document.getElementById('player');
player.style.top = `${newY * 32}px`;
player.style.left = `${newX * 32}px`;
// Check for encounters
checkForEncounter();
// Check for rival battle
if (newX === gameState.map.rivalPosition.x && newY === gameState.map.rivalPosition.y) {
startRivalBattle();
}
}
}
// Check for wild Pokémon encounter
function checkForEncounter() {
const inGrass = (
gameState.map.playerPosition.x > 3 &&
gameState.map.playerPosition.x < 12 &&
gameState.map.playerPosition.y > 2 &&
gameState.map.playerPosition.y < 7
);
if (inGrass && Math.random() < 0.2) {
const encounter = getRandomEncounter();
startWildBattle(encounter.name, encounter.level);
}
}
// Get a random wild Pokémon encounter
function getRandomEncounter() {
const rand = Math.random();
let cumulativeChance = 0;
for (const pokemon of wildPokemon) {
cumulativeChance += pokemon.chance;
if (rand <= cumulativeChance) {
return pokemon;
}
}
return wildPokemon[0]; // Fallback
}
// Start a wild Pokémon battle
function startWildBattle(pokemonName, level) {
gameState.inBattle = true;
gameState.currentScreen = 'battle';
// Generate wild Pokémon
gameState.battle.enemy = generatePokemon(pokemonName, level);
gameState.battle.playerPokemon = gameState.player.pokemon[0];
// Add to Pokédex if not already seen
if (!gameState.player.pokedex.includes(gameState.battle.enemy.name)) {
gameState.player.pokedex.push(gameState.battle.enemy.name);
updatePokedexCount();
}
// Update UI
document.getElementById('world-screen').classList.add('hidden');
document.getElementById('battle-screen').classList.remove('hidden');
// Set up battle display
document.getElementById('enemy-pokemon').className = `sprite ${gameState.battle.enemy.sprite}`;
document.getElementById('enemy-name').textContent = gameState.battle.enemy.name;
document.getElementById('enemy-level').textContent = gameState.battle.enemy.level;
document.getElementById('enemy-health').style.width = '100px';
document.getElementById('player-pokemon').className = `sprite ${gameState.battle.playerPokemon.sprite}`;
document.getElementById('player-pokemon-name').textContent = gameState.battle.playerPokemon.name;
document.getElementById('player-pokemon-level').textContent = gameState.battle.playerPokemon.level;
document.getElementById('player-pokemon-hp').textContent = gameState.battle.playerPokemon.currentHp;
document.getElementById('player-pokemon-max-hp').textContent = calculateStat(gameState.battle.playerPokemon.baseStats.hp, gameState.battle.playerPokemon.level);
updateHealthBar('player-health', gameState.battle.playerPokemon.currentHp, calculateStat(gameState.battle.playerPokemon.baseStats.hp, gameState.battle.playerPokemon.level));
document.getElementById('battle-pokemon-name').textContent = gameState.battle.enemy.name;
document.getElementById('battle-dialog').innerHTML = `<p>A wild ${gameState.battle.enemy.name} appeared!</p>`;
// Show battle options
document.getElementById('battle-options').classList.remove('hidden');
document.getElementById('move-options').classList.add('hidden');
}
// Start a rival battle
function startRivalBattle() {
gameState.inBattle = true;
gameState.currentScreen = 'battle';
// Generate rival's Pokémon (always Squirtle for this demo)
gameState.battle.enemy = generatePokemon('squirtle', 5);
gameState.battle.playerPokemon = gameState.player.pokemon[0];
// Update UI
document.getElementById('world-screen').classList.add('hidden');
document.getElementById('battle-screen').classList.remove('hidden');
// Set up battle display
document.getElementById('enemy-pokemon').className = `sprite ${gameState.battle.enemy.sprite}`;
document.getElementById('enemy-name').textContent = gameState.battle.enemy.name;
document.getElementById('enemy-level').textContent = gameState.battle.enemy.level;
document.getElementById('enemy-health').style.width = '100px';
document.getElementById('player-pokemon').className = `sprite ${gameState.battle.playerPokemon.sprite}`;
document.getElementById('player-pokemon-name').textContent = gameState.battle.playerPokemon.name;
document.getElementById('player-pokemon-level').textContent = gameState.battle.playerPokemon.level;
document.getElementById('player-pokemon-hp').textContent = gameState.battle.playerPokemon.currentHp;
document.getElementById('player-pokemon-max-hp').textContent = calculateStat(gameState.battle.playerPokemon.baseStats.hp, gameState.battle.playerPokemon.level);
updateHealthBar('player-health', gameState.battle.playerPokemon.currentHp, calculateStat(gameState.battle.playerPokemon.baseStats.hp, gameState.battle.playerPokemon.level));
document.getElementById('battle-pokemon-name').textContent = 'RIVAL';
document.getElementById('battle-dialog').innerHTML = `<p>RIVAL wants to battle!</p><p>RIVAL sent out ${gameState.battle.enemy.name}!</p>`;
// Show battle options
document.getElementById('battle-options').classList.remove('hidden');
document.getElementById('move-options').classList.add('hidden');
}
// Handle battle actions
function battleAction(action) {
if (action === 'fight') {
// Show move selection
document.getElementById('battle-options').classList.add('hidden');
document.getElementById('move-options').classList.remove('hidden');
// Clear any existing move buttons
const moveOptions = document.getElementById('move-options');
moveOptions.innerHTML = '';
// Add move buttons
gameState.battle.playerPokemon.moves.forEach((move, index) => {
const button = document.createElement('button');
button.className = 'pixel-button px-4 py-2';
button.textContent = `${move.name} (${move.currentPp}/${move.pp})`;
button.onclick = () => useMove(index);
moveOptions.appendChild(button);
});
// Add back button
const backButton = document.createElement('button');
backButton.className = 'pixel-button px-4 py-2';
backButton.textContent = 'BACK';
backButton.onclick = () => {
document.getElementById('battle-options').classList.remove('hidden');
document.getElementById('move-options').classList.add('hidden');
};
moveOptions.appendChild(backButton);
} else if (action === 'pokemon') {
// Show Pokémon selection (simplified for demo)
showDialog("You can only use one Pokémon in this demo.");
} else if (action === 'bag') {
// Show bag (simplified for demo)
showDialog("Bag items not implemented in this demo.");
} else if (action === 'run') {
// Attempt to run (always succeeds in this demo)
showDialog("Got away safely!");
setTimeout(() => {
endBattle(false);
}, 1500);
}
}
// Use a move in battle
function useMove(moveIndex) {
const move = gameState.battle.playerPokemon.moves[moveIndex];
// Check if move has PP left
if (move.currentPp <= 0) {
showDialog("No PP left for this move!");
return;
}
// Deduct PP
move.currentPp--;
// Player's turn
playerAttack(move);
// Enemy's turn (if not defeated)
if (gameState.battle.enemy.currentHp > 0) {
setTimeout(() => {
enemyAttack();
}, 2000);
}
}
// Player attacks
function playerAttack(move) {
// Calculate damage
const damage = calculateDamage(
gameState.battle.playerPokemon,
gameState.battle.enemy,
move
);
// Apply damage
gameState.battle.enemy.currentHp = Math.max(0, gameState.battle.enemy.currentHp - damage);
// Update UI
showDialog(`${gameState.battle.playerPokemon.name} used ${move.name}!`);
// Add animation based on move type
const enemySprite = document.getElementById('enemy-pokemon');
enemySprite.classList.add('shake');
if (move.name === 'TACKLE') {
const playerSprite = document.getElementById('player-pokemon');
playerSprite.classList.add('tackle-animation');
} else if (move.name === 'EMBER') {
const playerSprite = document.getElementById('player-pokemon');
playerSprite.classList.add('ember-animation');
} else if (move.name === 'THUNDERBOLT') {
const playerSprite = document.getElementById('player-pokemon');
playerSprite.classList.add('thunderbolt-animation');
} else if (move.name === 'BUBBLE') {
const playerSprite = document.getElementById('player-pokemon');
playerSprite.classList.add('bubble-animation');
} else if (move.name === 'VINE WHIP') {
const playerSprite = document.getElementById('player-pokemon');
playerSprite.classList.add('vine-whip-animation');
}
// Update enemy health
setTimeout(() => {
const maxHp = calculateStat(gameState.battle.enemy.baseStats.hp, gameState.battle.enemy.level);
updateHealthBar('enemy-health', gameState.battle.enemy.currentHp, maxHp);
// Check if enemy fainted
if (gameState.battle.enemy.currentHp <= 0) {
showDialog(`${gameState.battle.enemy.name} fainted!`);
setTimeout(() => {
endBattle(true);
}, 1500);
}
// Remove animations
enemySprite.classList.remove('shake');
const playerSprite = document.getElementById('player-pokemon');
playerSprite.classList.remove('tackle-animation', 'ember-animation', 'thunderbolt-animation', 'bubble-animation', 'vine-whip-animation');
}, 500);
}
// Enemy attacks
function enemyAttack() {
// Simple AI - choose random move
const moveIndex = Math.floor(Math.random() * gameState.battle.enemy.moves.length);
const move = gameState.battle.enemy.moves[moveIndex];
// Calculate damage
const damage = calculateDamage(
gameState.battle.enemy,
gameState.battle.playerPokemon,
move
);
// Apply damage
gameState.battle.playerPokemon.currentHp = Math.max(0, gameState.battle.playerPokemon.currentHp - damage);
// Update UI
showDialog(`Enemy ${gameState.battle.enemy.name} used ${move.name}!`);
// Add animation
const playerSprite = document.getElementById('player-pokemon');
playerSprite.classList.add('shake', 'flash');
// Update player health
setTimeout(() => {
const maxHp = calculateStat(gameState.battle.playerPokemon.baseStats.hp, gameState.battle.playerPokemon.level);
updateHealthBar('player-health', gameState.battle.playerPokemon.currentHp, maxHp);
document.getElementById('player-pokemon-hp').textContent = gameState.battle.playerPokemon.currentHp;
// Check if player's Pokémon fainted
if (gameState.battle.playerPokemon.currentHp <= 0) {
showDialog(`${gameState.battle.playerPokemon.name} fainted!`);
setTimeout(() => {
endBattle(false);
}, 1500);
}
// Remove animations
playerSprite.classList.remove('shake', 'flash');
}, 500);
}
// End battle
function endBattle(playerWon) {
if (playerWon) {
// Calculate experience gained
const baseExp = gameState.battle.enemy.level * 10;
const exp = Math.floor(baseExp * 1.5); // Bonus for defeating a trainer
// Add experience
gameState.battle.playerPokemon.experience += exp;
// Check for level up (simplified)
if (gameState.battle.playerPokemon.experience >= gameState.battle.playerPokemon.level * 100) {
gameState.battle.playerPokemon.level++;
gameState.battle.playerPokemon.currentHp = calculateStat(gameState.battle.playerPokemon.baseStats.hp, gameState.battle.playerPokemon.level);
// Show result with level up
document.getElementById('battle-screen').classList.add('hidden');
document.getElementById('battle-result').classList.remove('hidden');
document.getElementById('result-message').textContent =
`${gameState.battle.playerPokemon.name} gained ${exp} EXP. Points! ${gameState.battle.playerPokemon.name} grew to LV. ${gameState.battle.playerPokemon.level}!`;
} else {
// Show result without level up
document.getElementById('battle-screen').classList.add('hidden');
document.getElementById('battle-result').classList.remove('hidden');
document.getElementById('result-message').textContent =
`${gameState.battle.playerPokemon.name} gained ${exp} EXP. Points!`;
}
// Add money (only from trainers in this demo)
if (gameState.battle.enemy.name === 'SQUIRTLE') { // Rival's Pokémon
gameState.player.money += 500;
updatePlayerMoney();
}
} else {
// Player lost
document.getElementById('battle-screen').classList.add('hidden');
document.getElementById('battle-result').classList.remove('hidden');
document.getElementById('result-message').textContent =
"You lost the battle!";
}
// Reset battle state
gameState.inBattle = false;
gameState.battle = {
enemy: null,
playerPokemon: null,
turn: 'player'
};
}
// Return to world after battle
function returnToWorld() {
document.getElementById('battle-result').classList.add('hidden');
document.getElementById('world-screen').classList.remove('hidden');
gameState.currentScreen = 'world';
// Regenerate map to show changes
generateMap();
}
// Update health bar display
function updateHealthBar(elementId, currentHp, maxHp) {
const healthBar = document.getElementById(elementId);
const percentage = Math.max(0, (currentHp / maxHp) * 100);
healthBar.style.width = `${percentage}%`;
// Change color based on health
if (percentage < 20) {
healthBar.style.background = '#ff0000';
} else if (percentage < 50) {
healthBar.style.background = '#ffcc00';
} else {
healthBar.style.background = '#00cc00';
}
}
// Show dialog message
function showDialog(message) {
const dialog = document.getElementById('battle-dialog');
dialog.innerHTML = `<p>${message}</p>`;
}
// Open menu
function openMenu(menu) {
document.getElementById('world-screen').classList.add('hidden');
if (menu === 'pokemon') {
document.getElementById('pokemon-menu').classList.remove('hidden');
showPokemonList();
} else if (menu === 'bag') {
document.getElementById('bag-menu').classList.remove('hidden');
showBagCategory('pokeballs');
} else if (menu === 'player') {
document.getElementById('player-menu').classList.remove('hidden');
} else if (menu === 'save') {
document.getElementById('save-menu').classList.remove('hidden');
}
}
// Close menu
function closeMenu() {
document.getElementById('pokemon-menu').classList.add('hidden');
document.getElementById('bag-menu').classList.add('hidden');
document.getElementById('player-menu').classList.add('hidden');
document.getElementById('save-menu').classList.add('hidden');
document.getElementById('save-confirm').classList.add('hidden');
document.getElementById('world-screen').classList.remove('hidden');
}
// Show Pokémon list
function showPokemonList() {
const listContainer = document.getElementById('pokemon-list');
listContainer.innerHTML = '';
gameState.player.pokemon.forEach(pokemon => {
const item = document.createElement('div');
item.className = 'flex items-center p-2 bg-white bg-opacity-10 rounded';
const sprite = document.createElement('div');
sprite.className = `sprite ${pokemon.sprite} mr-4`;
const info = document.createElement('div');
info.className = 'flex-1';
info.innerHTML = `
<p>${pokemon.name} Lv.${pokemon.level}</p>
<div class="flex items-center">
<span class="mr-2">HP:</span>
<div class="health-bar" style="width: 100px;"></div>
</div>
`;
// Update health bar for this Pokémon
const maxHp = calculateStat(pokemon.baseStats.hp, pokemon.level);
const healthBar = info.querySelector('.health-bar');
const percentage = Math.max(0, (pokemon.currentHp / maxHp) * 100);
healthBar.style.width = `${percentage}%`;
if (percentage < 20) {
healthBar.style.background = '#ff0000';
} else if (percentage < 50) {
healthBar.style.background = '#ffcc00';
} else {
healthBar.style.background = '#00cc00';
}
item.appendChild(sprite);
item.appendChild(info);
listContainer.appendChild(item);
});
}
// Show bag category
function showBagCategory(category) {
const itemsContainer = document.getElementById('bag-items');
itemsContainer.innerHTML = '';
gameState.player.items[category].forEach(item => {
const itemElement = document.createElement('div');
itemElement.className = 'flex justify-between items-center p-2 bg-white bg-opacity-10 rounded';
itemElement.innerHTML = `
<span>${item.name}</span>
<span>×${item.quantity}</span>
`;
itemsContainer.appendChild(itemElement);
});
}
// Save game (placeholder)
function saveGame() {
document.getElementById('save-menu').classList.add('hidden');
document.getElementById('save-confirm').classList.remove('hidden');
// In a real game, you would save to localStorage or a server here
localStorage.setItem('pokemonGameSave', JSON.stringify(gameState));
}
// Update game time
function updateGameTime() {
gameState.gameTime++;
const hours = Math.floor(gameState.gameTime / 60) % 24;
const minutes = gameState.gameTime % 60;
const timeString = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
document.getElementById('game-time').textContent = timeString;
document.getElementById('menu-game-time').textContent = timeString;
}
// Update Pokédex count
function updatePokedexCount() {
const count = gameState.player.pokedex.length;
document.getElementById('pokedex-count').textContent = count;
document.getElementById('menu-pokedex-count').textContent = count;
}
// Update player money
function updatePlayerMoney() {
document.getElementById('player-money').textContent = gameState.player.money;
document.getElementById('menu-player-money').textContent = gameState.player.money;
}
// Initialize the game when the page loads
window.onload = initGame;
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=vikassabbi/vspace" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>