tcg-board-state / index.html
SUPSINNED's picture
Can you add the button for the change of bench size for each side of the board and have them operate seperately? The bench sizes can be diffrent per player. Can you also add a counter for Lost Zone next to the Discard counter? And please add a dark mode option too - Initial Deployment
d88656f verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pokemon TCG Board State</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>
.card {
width: 120px;
height: 170px;
perspective: 1000px;
cursor: pointer;
transition: transform 0.3s;
}
.card-inner {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.6s;
transform-style: preserve-3d;
}
.card.tapped .card-inner {
transform: rotateY(180deg);
}
.card-face {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.card-front {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border: 2px solid #4a5568;
}
.card-back {
background: linear-gradient(135deg, #4a5568 0%, #2d3748 100%);
color: white;
transform: rotateY(180deg);
}
.damage-counter {
position: absolute;
top: 10px;
right: 10px;
background-color: rgba(255,0,0,0.7);
color: white;
border-radius: 50%;
width: 30px;
height: 30px;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
}
.special-card {
width: 60px;
height: 90px;
}
.modal {
display: none;
position: fixed;
z-index: 100;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
}
.modal-content {
background-color: white;
margin: 15% auto;
padding: 20px;
border-radius: 10px;
width: 300px;
}
@media (max-width: 768px) {
.card {
width: 80px;
height: 120px;
}
.special-card {
width: 60px;
height: 90px;
}
}
</style>
</head>
<body class="bg-gray-100">
<div class="container mx-auto px-4 py-8">
<h1 class="text-3xl font-bold text-center mb-8">Pokemon TCG Board State</h1>
<div class="flex flex-col items-center">
<!-- Opponent's Side -->
<div class="w-full mb-8">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-center">Opponent's Side</h2>
<div class="relative group">
<button class="p-2 bg-gray-200 rounded-full shadow-md hover:bg-gray-300">
<i class="fas fa-cog"></i>
</button>
<div class="hidden group-hover:block absolute bottom-full right-0 mb-2 bg-white p-2 rounded shadow-lg">
<select id="opponent-bench-size" class="p-1 text-sm border rounded" onchange="changeBenchSize('opponent')">
<option value="3">3 Bench</option>
<option value="4">4 Bench</option>
<option value="5" selected>5 Bench</option>
<option value="8">8 Bench</option>
</select>
</div>
</div>
</div>
<!-- Opponent's Bench -->
<div class="flex flex-wrap justify-center mb-4" id="opponent-bench">
<!-- Bench cards will be added here -->
</div>
<!-- Opponent's Active and Special Zones -->
<div class="flex items-center justify-center space-x-4 mb-8">
<!-- Active Pokémon -->
<div class="card mx-2" id="opponent-active" onclick="handleCardClick(this)">
<div class="card-inner">
<div class="card-face card-front">
<i class="fas fa-paw text-4xl text-red-500"></i>
<p class="mt-2">Active</p>
</div>
<div class="card-face card-back">
<p>Tapped</p>
</div>
</div>
</div>
<!-- Special Zones -->
<div class="flex flex-col space-y-2">
<div class="card special-card mx-1" id="opponent-vstar" onclick="handleCardClick(this)">
<div class="card-inner">
<div class="card-face card-front">
<i class="fas fa-star text-2xl text-yellow-500"></i>
<p class="text-xs mt-1">VSTAR</p>
</div>
<div class="card-face card-back">
<p class="text-xs">Used</p>
</div>
</div>
</div>
<div class="card special-card mx-1" id="opponent-gz" onclick="handleCardClick(this)">
<div class="card-inner">
<div class="card-face card-front">
<i class="fas fa-radiation text-2xl text-green-500"></i>
<p class="text-xs mt-1">GZ</p>
</div>
<div class="card-face card-back">
<p class="text-xs">Used</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Divider -->
<div class="w-full h-1 bg-gray-300 my-4"></div>
<!-- Player's Side -->
<div class="w-full mt-8">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-center">Your Side</h2>
<div class="relative group">
<button class="p-2 bg-gray-200 rounded-full shadow-md hover:bg-gray-300">
<i class="fas fa-cog"></i>
</button>
<div class="hidden group-hover:block absolute bottom-full right-0 mb-2 bg-white p-2 rounded shadow-lg">
<select id="player-bench-size" class="p-1 text-sm border rounded" onchange="changeBenchSize('player')">
<option value="3">3 Bench</option>
<option value="4">4 Bench</option>
<option value="5" selected>5 Bench</option>
<option value="8">8 Bench</option>
</select>
</div>
</div>
</div>
<!-- Player's Active and Special Zones -->
<div class="flex items-center justify-center space-x-4 mb-8">
<!-- Active Pokémon -->
<div class="card mx-2" id="player-active" onclick="handleCardClick(this)">
<div class="card-inner">
<div class="card-face card-front">
<i class="fas fa-paw text-4xl text-blue-500"></i>
<p class="mt-2">Active</p>
</div>
<div class="card-face card-back">
<p>Tapped</p>
</div>
</div>
</div>
<!-- Special Zones -->
<div class="flex flex-col space-y-2">
<div class="card special-card mx-1" id="player-vstar" onclick="handleCardClick(this)">
<div class="card-inner">
<div class="card-face card-front">
<i class="fas fa-star text-2xl text-yellow-500"></i>
<p class="text-xs mt-1">VSTAR</p>
</div>
<div class="card-face card-back">
<p class="text-xs">Used</p>
</div>
</div>
</div>
<div class="card special-card mx-1" id="player-gz" onclick="handleCardClick(this)">
<div class="card-inner">
<div class="card-face card-front">
<i class="fas fa-radiation text-2xl text-green-500"></i>
<p class="text-xs mt-1">GZ</p>
</div>
<div class="card-face card-back">
<p class="text-xs">Used</p>
</div>
</div>
</div>
</div>
</div>
<!-- Player's Bench -->
<div class="flex flex-wrap justify-center mb-4" id="player-bench">
<!-- Bench cards will be added here -->
</div>
</div>
</div>
<!-- Shared Stadium in the middle -->
<div class="absolute left-1/2 transform -translate-x-1/2 top-1/2 -translate-y-1/2">
<div class="card special-card" id="stadium" onclick="handleCardClick(this)">
<div class="card-inner">
<div class="card-face card-front">
<i class="fas fa-landmark text-2xl text-purple-500"></i>
<p class="text-xs mt-1">Stadium</p>
</div>
<div class="card-face card-back">
<p class="text-xs">Tapped</p>
</div>
</div>
</div>
</div>
<!-- Counters -->
<div class="fixed bottom-4 left-4 flex space-x-4">
<!-- Discard Pile Counter -->
<div class="bg-white p-3 rounded-lg shadow-lg">
<div class="flex items-center space-x-2">
<i class="fas fa-trash-alt text-red-500"></i>
<span class="font-semibold">Discard:</span>
<span id="discard-count" class="bg-red-100 px-2 py-1 rounded">0</span>
<div class="flex space-x-1">
<button onclick="updateDiscardCount(-1)" class="w-8 h-8 bg-red-500 text-white rounded-full flex items-center justify-center">-</button>
<button onclick="updateDiscardCount(1)" class="w-8 h-8 bg-green-500 text-white rounded-full flex items-center justify-center">+</button>
</div>
</div>
</div>
<!-- Lost Zone Counter -->
<div class="bg-white p-3 rounded-lg shadow-lg">
<div class="flex items-center space-x-2">
<i class="fas fa-skull text-gray-700"></i>
<span class="font-semibold">Lost Zone:</span>
<span id="lostzone-count" class="bg-gray-200 px-2 py-1 rounded">0</span>
<div class="flex space-x-1">
<button onclick="updateLostZoneCount(-1)" class="w-8 h-8 bg-red-500 text-white rounded-full flex items-center justify-center">-</button>
<button onclick="updateLostZoneCount(1)" class="w-8 h-8 bg-green-500 text-white rounded-full flex items-center justify-center">+</button>
</div>
</div>
</div>
</div>
<!-- Controls -->
<div class="fixed bottom-4 right-4 flex space-x-2">
<!-- Dark Mode Toggle -->
<button id="dark-mode-toggle" class="p-2 bg-gray-800 text-white rounded-full shadow-md hover:bg-gray-700">
<i class="fas fa-moon"></i>
</button>
<button onclick="resetAll()" class="p-2 bg-red-500 text-white rounded-full shadow-md hover:bg-red-600">
<i class="fas fa-redo"></i>
</button>
</div>
</div>
<!-- Damage Counter Modal -->
<div id="damage-modal" class="modal">
<div class="modal-content">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">Damage Counter</h3>
<button onclick="closeModal()" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="flex flex-col space-y-2">
<button onclick="addDamage(10)" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Add 10 Damage
</button>
<button onclick="addDamage(20)" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
Add 20 Damage
</button>
<button onclick="addDamage(30)" class="px-4 py-2 bg-blue-700 text-white rounded hover:bg-blue-800">
Add 30 Damage
</button>
<button onclick="addDamage(50)" class="px-4 py-2 bg-blue-800 text-white rounded hover:bg-blue-900">
Add 50 Damage
</button>
<button onclick="addDamage(100)" class="px-4 py-2 bg-blue-900 text-white rounded hover:bg-black">
Add 100 Damage
</button>
<button onclick="resetDamage()" class="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 mt-4">
Reset Damage
</button>
</div>
</div>
</div>
<script>
// Current card being edited
let currentCard = null;
// Initialize the board
document.addEventListener('DOMContentLoaded', function() {
initializeBench('player-bench', 'player');
initializeBench('opponent-bench', 'opponent');
// Check for saved dark mode preference
if (localStorage.getItem('darkMode') === 'enabled') {
document.body.classList.add('dark');
document.getElementById('dark-mode-toggle').innerHTML = '<i class="fas fa-sun"></i>';
}
});
// Initialize bench with default 5 cards
function initializeBench(benchId, owner) {
const bench = document.getElementById(benchId);
bench.innerHTML = '';
const benchSizeSelect = document.getElementById(`${owner}-bench-size`);
const benchSize = parseInt(benchSizeSelect ? benchSizeSelect.value : 5);
for (let i = 0; i < benchSize; i++) {
const card = document.createElement('div');
card.className = 'card mx-2 mb-2';
card.id = `${owner}-bench-${i}`;
card.onclick = function() { handleCardClick(this); };
card.innerHTML = `
<div class="card-inner">
<div class="card-face card-front">
<i class="fas fa-paw text-4xl ${owner === 'player' ? 'text-blue-500' : 'text-red-500'}"></i>
<p class="mt-2">Bench ${i+1}</p>
</div>
<div class="card-face card-back">
<p>Tapped</p>
</div>
</div>
`;
bench.appendChild(card);
}
}
// Change bench size
function changeBenchSize(owner) {
initializeBench(`${owner}-bench`, owner);
}
// Handle card click (tap/untap or open damage modal)
function handleCardClick(card) {
// Check if the click is on a damage counter
if (event.target.classList.contains('damage-counter')) {
return;
}
// For active and bench cards, open damage modal
if (card.id.includes('active') || card.id.includes('bench')) {
currentCard = card;
document.getElementById('damage-modal').style.display = 'block';
} else {
// For other cards (special zones), just toggle tapped state
card.classList.toggle('tapped');
}
}
// Close modal
function closeModal() {
document.getElementById('damage-modal').style.display = 'none';
currentCard = null;
}
// Add damage to current card
function addDamage(amount) {
if (!currentCard) return;
// Remove existing damage counter if any
const existingCounter = currentCard.querySelector('.damage-counter');
if (existingCounter) {
existingCounter.remove();
}
// Get current damage
const currentDamage = parseInt(currentCard.getAttribute('data-damage') || '0');
const newDamage = currentDamage + amount;
// Update damage attribute
currentCard.setAttribute('data-damage', newDamage);
// Create or update damage counter
const damageCounter = document.createElement('div');
damageCounter.className = 'damage-counter';
damageCounter.textContent = newDamage;
damageCounter.onclick = function(e) {
e.stopPropagation();
currentCard = this.parentElement;
document.getElementById('damage-modal').style.display = 'block';
};
currentCard.querySelector('.card-front').appendChild(damageCounter);
}
// Reset damage for current card
function resetDamage() {
if (!currentCard) return;
const counter = currentCard.querySelector('.damage-counter');
if (counter) {
counter.remove();
}
currentCard.removeAttribute('data-damage');
closeModal();
}
// Reset all cards
function resetAll() {
// Reset active and bench cards
const allCards = document.querySelectorAll('.card');
allCards.forEach(card => {
card.classList.remove('tapped');
const counter = card.querySelector('.damage-counter');
if (counter) {
counter.remove();
}
card.removeAttribute('data-damage');
});
// Close modal if open
closeModal();
}
</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=SUPSINNED/tcg-board-state" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>