a tapping game that user taps on a character and for teach taps it gives a coin and the coins are stored in the user balance
Browse files- README.md +8 -5
- components/confetti.js +54 -0
- index.html +53 -19
- script.js +88 -0
- style.css +24 -22
README.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
| 1 |
---
|
| 2 |
-
title: Tap
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Tap'n'Stack Coin Collector
|
| 3 |
+
colorFrom: pink
|
| 4 |
+
colorTo: yellow
|
| 5 |
+
emoji: 🐳
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite-v3
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Welcome to your new DeepSite project!
|
| 13 |
+
This project was created with [DeepSite](https://huggingface.co/deepsite).
|
components/confetti.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class ConfettiEffect extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
.confetti {
|
| 7 |
+
position: absolute;
|
| 8 |
+
width: 10px;
|
| 9 |
+
height: 10px;
|
| 10 |
+
background-color: #f00;
|
| 11 |
+
opacity: 0;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
@keyframes confetti-fall {
|
| 15 |
+
0% {
|
| 16 |
+
transform: translateY(0) rotate(0deg);
|
| 17 |
+
opacity: 1;
|
| 18 |
+
}
|
| 19 |
+
100% {
|
| 20 |
+
transform: translateY(100vh) rotate(360deg);
|
| 21 |
+
opacity: 0;
|
| 22 |
+
}
|
| 23 |
+
}
|
| 24 |
+
</style>
|
| 25 |
+
<div id="confetti-container"></div>
|
| 26 |
+
`;
|
| 27 |
+
|
| 28 |
+
this.container = this.shadowRoot.getElementById('confetti-container');
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
trigger() {
|
| 32 |
+
// Clear existing confetti
|
| 33 |
+
this.container.innerHTML = '';
|
| 34 |
+
|
| 35 |
+
// Create new confetti
|
| 36 |
+
const colors = ['#f00', '#0f0', '#00f', '#ff0', '#f0f', '#0ff'];
|
| 37 |
+
|
| 38 |
+
for (let i = 0; i < 50; i++) {
|
| 39 |
+
const confetti = document.createElement('div');
|
| 40 |
+
confetti.className = 'confetti';
|
| 41 |
+
confetti.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
|
| 42 |
+
confetti.style.left = `${Math.random() * 100}%`;
|
| 43 |
+
confetti.style.top = '0';
|
| 44 |
+
confetti.style.animation = `confetti-fall ${2 + Math.random() * 3}s linear forwards`;
|
| 45 |
+
confetti.style.animationDelay = `${Math.random() * 0.5}s`;
|
| 46 |
+
confetti.style.width = `${5 + Math.random() * 10}px`;
|
| 47 |
+
confetti.style.height = `${5 + Math.random() * 10}px`;
|
| 48 |
+
|
| 49 |
+
this.container.appendChild(confetti);
|
| 50 |
+
}
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
customElements.define('confetti-effect', ConfettiEffect);
|
index.html
CHANGED
|
@@ -1,19 +1,53 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
</
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Tap'n'Stack Coin Collector</title>
|
| 7 |
+
<link rel="stylesheet" href="style.css">
|
| 8 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 10 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 11 |
+
</head>
|
| 12 |
+
<body class="bg-gray-100 min-h-screen flex flex-col">
|
| 13 |
+
<header class="bg-indigo-600 text-white p-4 shadow-lg">
|
| 14 |
+
<div class="container mx-auto flex justify-between items-center">
|
| 15 |
+
<h1 class="text-2xl font-bold">Tap'n'Stack </h1>
|
| 16 |
+
<div id="balance" class="flex items-center gap-2 bg-indigo-700 px-4 py-2 rounded-full">
|
| 17 |
+
<i data-feather="dollar-sign"></i>
|
| 18 |
+
<span class="font-mono">0</span>
|
| 19 |
+
</div>
|
| 20 |
+
</div>
|
| 21 |
+
</header>
|
| 22 |
+
|
| 23 |
+
<main class="flex-grow flex flex-col items-center justify-center p-4 container mx-auto">
|
| 24 |
+
<div class="relative mb-8">
|
| 25 |
+
<div id="character" class="w-48 h-48 bg-indigo-500 rounded-full flex items-center justify-center cursor-pointer transform transition-transform hover:scale-105 active:scale-95 shadow-xl">
|
| 26 |
+
<i data-feather="smile" class="text-white w-24 h-24"></i>
|
| 27 |
+
</div>
|
| 28 |
+
<div id="coin-effect" class="absolute inset-0 pointer-events-none opacity-0 transition-opacity duration-300"></div>
|
| 29 |
+
</div>
|
| 30 |
+
|
| 31 |
+
<div class="stats bg-white p-6 rounded-xl shadow-lg w-full max-w-md">
|
| 32 |
+
<div class="grid grid-cols-2 gap-4">
|
| 33 |
+
<div class="stat-card bg-gray-50 p-4 rounded-lg">
|
| 34 |
+
<h3 class="text-gray-500 text-sm">Total Taps</h3>
|
| 35 |
+
<p id="total-taps" class="text-2xl font-bold">0</p>
|
| 36 |
+
</div>
|
| 37 |
+
<div class="stat-card bg-gray-50 p-4 rounded-lg">
|
| 38 |
+
<h3 class="text-gray-500 text-sm">Coins Per Tap</h3>
|
| 39 |
+
<p id="coins-per-tap" class="text-2xl font-bold">1</p>
|
| 40 |
+
</div>
|
| 41 |
+
</div>
|
| 42 |
+
</div>
|
| 43 |
+
</main>
|
| 44 |
+
|
| 45 |
+
<footer class="bg-gray-800 text-white p-4 text-center">
|
| 46 |
+
<p>Keep tapping to earn more coins! 🚀</p>
|
| 47 |
+
</footer>
|
| 48 |
+
|
| 49 |
+
<script src="script.js"></script>
|
| 50 |
+
<script>feather.replace();</script>
|
| 51 |
+
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 52 |
+
</body>
|
| 53 |
+
</html>
|
script.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 2 |
+
// Game state
|
| 3 |
+
let balance = localStorage.getItem('coinBalance') ? parseInt(localStorage.getItem('coinBalance')) : 0;
|
| 4 |
+
let totalTaps = localStorage.getItem('totalTaps') ? parseInt(localStorage.getItem('totalTaps')) : 0;
|
| 5 |
+
let coinsPerTap = 1;
|
| 6 |
+
|
| 7 |
+
// DOM elements
|
| 8 |
+
const character = document.getElementById('character');
|
| 9 |
+
const balanceDisplay = document.querySelector('#balance span');
|
| 10 |
+
const totalTapsDisplay = document.getElementById('total-taps');
|
| 11 |
+
const coinsPerTapDisplay = document.getElementById('coins-per-tap');
|
| 12 |
+
const coinEffect = document.getElementById('coin-effect');
|
| 13 |
+
|
| 14 |
+
// Initialize displays
|
| 15 |
+
updateDisplays();
|
| 16 |
+
|
| 17 |
+
// Tap handler
|
| 18 |
+
character.addEventListener('click', (e) => {
|
| 19 |
+
// Increment counters
|
| 20 |
+
totalTaps++;
|
| 21 |
+
balance += coinsPerTap;
|
| 22 |
+
|
| 23 |
+
// Save to localStorage
|
| 24 |
+
localStorage.setItem('coinBalance', balance);
|
| 25 |
+
localStorage.setItem('totalTaps', totalTaps);
|
| 26 |
+
|
| 27 |
+
// Update displays
|
| 28 |
+
updateDisplays();
|
| 29 |
+
|
| 30 |
+
// Create coin effect
|
| 31 |
+
createCoinEffect(e);
|
| 32 |
+
|
| 33 |
+
// Add temporary animation class
|
| 34 |
+
character.classList.add('animate-pulse');
|
| 35 |
+
setTimeout(() => {
|
| 36 |
+
character.classList.remove('animate-pulse');
|
| 37 |
+
}, 200);
|
| 38 |
+
});
|
| 39 |
+
|
| 40 |
+
function updateDisplays() {
|
| 41 |
+
balanceDisplay.textContent = balance.toLocaleString();
|
| 42 |
+
totalTapsDisplay.textContent = totalTaps.toLocaleString();
|
| 43 |
+
coinsPerTapDisplay.textContent = coinsPerTap;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
function createCoinEffect(e) {
|
| 47 |
+
// Get character position
|
| 48 |
+
const rect = character.getBoundingClientRect();
|
| 49 |
+
const centerX = rect.left + rect.width / 2;
|
| 50 |
+
const centerY = rect.top + rect.height / 2;
|
| 51 |
+
|
| 52 |
+
// Create multiple coins
|
| 53 |
+
for (let i = 0; i < 3; i++) {
|
| 54 |
+
const coin = document.createElement('div');
|
| 55 |
+
coin.classList.add('coin');
|
| 56 |
+
|
| 57 |
+
// Position randomly around the click point
|
| 58 |
+
const offsetX = (Math.random() - 0.5) * 40;
|
| 59 |
+
const offsetY = (Math.random() - 0.5) * 40;
|
| 60 |
+
|
| 61 |
+
coin.style.left = `${centerX + offsetX}px`;
|
| 62 |
+
coin.style.top = `${centerY + offsetY}px`;
|
| 63 |
+
|
| 64 |
+
// Random delay for animation
|
| 65 |
+
coin.style.animationDelay = `${i * 0.1}s`;
|
| 66 |
+
|
| 67 |
+
document.body.appendChild(coin);
|
| 68 |
+
|
| 69 |
+
// Remove coin after animation
|
| 70 |
+
setTimeout(() => {
|
| 71 |
+
coin.remove();
|
| 72 |
+
}, 800);
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
// Check for saved data on load
|
| 77 |
+
if (totalTaps > 0) {
|
| 78 |
+
// Show welcome back message
|
| 79 |
+
const welcomeBack = document.createElement('div');
|
| 80 |
+
welcomeBack.className = 'fixed top-4 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-4 py-2 rounded-full shadow-lg z-50 animate-bounce';
|
| 81 |
+
welcomeBack.textContent = `Welcome back! You have ${balance} coins!`;
|
| 82 |
+
document.body.appendChild(welcomeBack);
|
| 83 |
+
|
| 84 |
+
setTimeout(() => {
|
| 85 |
+
welcomeBack.remove();
|
| 86 |
+
}, 3000);
|
| 87 |
+
}
|
| 88 |
+
});
|
style.css
CHANGED
|
@@ -1,28 +1,30 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
}
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
}
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
margin-bottom: 10px;
|
| 15 |
-
margin-top: 5px;
|
| 16 |
}
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
padding: 16px;
|
| 22 |
-
border: 1px solid lightgray;
|
| 23 |
-
border-radius: 16px;
|
| 24 |
-
}
|
| 25 |
-
|
| 26 |
-
.card p:last-child {
|
| 27 |
-
margin-bottom: 0;
|
| 28 |
-
}
|
|
|
|
| 1 |
+
@keyframes coinBounce {
|
| 2 |
+
0% {
|
| 3 |
+
transform: translateY(0) scale(1);
|
| 4 |
+
opacity: 1;
|
| 5 |
+
}
|
| 6 |
+
100% {
|
| 7 |
+
transform: translateY(-100px) scale(0.5);
|
| 8 |
+
opacity: 0;
|
| 9 |
+
}
|
| 10 |
}
|
| 11 |
|
| 12 |
+
.coin {
|
| 13 |
+
position: absolute;
|
| 14 |
+
width: 24px;
|
| 15 |
+
height: 24px;
|
| 16 |
+
background-color: gold;
|
| 17 |
+
border-radius: 50%;
|
| 18 |
+
box-shadow: 0 0 10px rgba(255, 215, 0, 0.7);
|
| 19 |
+
animation: coinBounce 0.8s forwards;
|
| 20 |
+
pointer-events: none;
|
| 21 |
}
|
| 22 |
|
| 23 |
+
#character {
|
| 24 |
+
user-select: none;
|
| 25 |
+
-webkit-tap-highlight-color: transparent;
|
|
|
|
|
|
|
| 26 |
}
|
| 27 |
|
| 28 |
+
#character:active {
|
| 29 |
+
transform: scale(0.95);
|
| 30 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|