hugging-clicker / index.html
FranckAbgrall's picture
undefined - Initial Deployment
ab76739 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hugs Clicker - Get Virtual Hugs!</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<style>
.hugger {
transition: all 0.1s ease;
cursor: pointer;
}
.hugger:active {
transform: scale(0.95);
}
.floating-hug {
position: absolute;
pointer-events: none;
animation: floatUp 2s forwards;
opacity: 0.8;
}
@keyframes floatUp {
0% {
transform: translateY(0) rotate(0deg);
opacity: 1;
}
100% {
transform: translateY(-100px) rotate(10deg);
opacity: 0;
}
}
.progress-bar {
transition: width 0.3s ease;
}
.unlock-notification {
animation: bounce 0.5s ease;
}
@keyframes bounce {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
</style>
</head>
<body class="bg-gradient-to-b from-pink-100 to-purple-100 min-h-screen font-sans">
<div class="container mx-auto px-4 py-8">
<header class="text-center mb-8">
<h1 class="text-4xl md:text-5xl font-bold text-purple-800 mb-2">Hugs Clicker</h1>
<p class="text-lg text-purple-600">Spread love one hug at a time!</p>
</header>
<div class="flex flex-col lg:flex-row gap-8">
<!-- Main hugger section -->
<div class="flex-1 flex flex-col items-center">
<div class="relative mb-4">
<div id="hug-counter" class="text-3xl font-bold text-purple-700 mb-4 text-center">0 Hugs</div>
<div id="hugger" class="hugger w-64 h-64 md:w-80 md:h-80 bg-white rounded-full shadow-xl flex items-center justify-center overflow-hidden">
<img id="hugger-image" src="https://em-content.zobj.net/source/microsoft-teams/363/hugging-face_1f917.png" alt="Hugging face" class="w-full h-full object-contain p-6">
</div>
<div id="hug-effects" class="absolute inset-0 pointer-events-none"></div>
</div>
<div class="text-center text-purple-600 mb-6">
<p id="hugs-per-second" class="text-lg">0 hugs per second</p>
</div>
<div class="w-full max-w-md bg-white bg-opacity-70 rounded-lg p-4 shadow-md mb-6">
<h3 class="text-xl font-semibold text-purple-800 mb-2">Hug Power</h3>
<div class="h-4 bg-purple-200 rounded-full mb-2">
<div id="power-bar" class="h-full bg-purple-500 rounded-full progress-bar" style="width: 0%"></div>
</div>
<p id="power-text" class="text-sm text-purple-600">Click faster to increase your hug power!</p>
</div>
</div>
<!-- Upgrades section -->
<div class="flex-1 bg-white bg-opacity-80 rounded-xl p-6 shadow-lg">
<h2 class="text-2xl font-bold text-purple-800 mb-4 border-b-2 border-purple-100 pb-2">Hug Upgrades</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="upgrade-card" data-cost="20" data-id="auto-hugger" data-cps="1">
<div class="flex items-center gap-3">
<img src="https://em-content.zobj.net/source/microsoft-teams/363/smiling-face-with-hearts_1f970.png" alt="Auto hugger" class="w-12 h-12">
<div>
<h3 class="font-semibold text-purple-700">Auto Hugger</h3>
<p class="text-sm text-purple-600">Gives 1 hug per second</p>
</div>
</div>
<div class="ml-auto text-right">
<p class="cost text-lg font-bold text-purple-800">20 Hugs</p>
<p class="owned text-xs text-purple-600">Owned: 0</p>
</div>
</div>
<div class="upgrade-card" data-cost="100" data-id="hug-buddy" data-cps="5">
<div class="flex items-center gap-3">
<img src="https://em-content.zobj.net/source/microsoft-teams/363/smiling-face-with-smiling-eyes_1f60a.png" alt="Hug buddy" class="w-12 h-12">
<div>
<h3 class="font-semibold text-purple-700">Hug Buddy</h3>
<p class="text-sm text-purple-600">Gives 5 hugs per second</p>
</div>
</div>
<div class="ml-auto text-right">
<p class="cost text-lg font-bold text-purple-800">100 Hugs</p>
<p class="owned text-xs text-purple-600">Owned: 0</p>
</div>
</div>
<div class="upgrade-card" data-cost="500" data-id="hug-team" data-cps="10">
<div class="flex items-center gap-3">
<img src="https://em-content.zobj.net/source/microsoft-teams/363/smiling-face-with-heart-eyes_1f60d.png" alt="Hug team" class="w-12 h-12">
<div>
<h3 class="font-semibold text-purple-700">Hug Team</h3>
<p class="text-sm text-purple-600">Gives 10 hugs per second</p>
</div>
</div>
<div class="ml-auto text-right">
<p class="cost text-lg font-bold text-purple-800">500 Hugs</p>
<p class="owned text-xs text-purple-600">Owned: 0</p>
</div>
</div>
<div class="upgrade-card" data-cost="2000" data-id="hug-factory" data-cps="50">
<div class="flex items-center gap-3">
<img src="https://em-content.zobj.net/source/microsoft-teams/363/star-struck_1f929.png" alt="Hug factory" class="w-12 h-12">
<div>
<h3 class="font-semibold text-purple-700">Hug Factory</h3>
<p class="text-sm text-purple-600">Gives 50 hugs per second</p>
</div>
</div>
<div class="ml-auto text-right">
<p class="cost text-lg font-bold text-purple-800">2000 Hugs</p>
<p class="owned text-xs text-purple-600">Owned: 0</p>
</div>
</div>
</div>
</div>
</div>
<!-- Achievements section -->
<div class="mt-8 bg-white bg-opacity-80 rounded-xl p-6 shadow-lg">
<h2 class="text-2xl font-bold text-purple-800 mb-4 border-b-2 border-purple-100 pb-2">Hug Achievements</h2>
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
<div class="achievement" data-threshold="10">
<div class="achievement-icon bg-purple-200 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-2">
<img src="https://em-content.zobj.net/source/microsoft-teams/363/smiling-face_263a-fe0f.png" alt="First Hugs" class="w-10 h-10">
</div>
<p class="text-center text-sm font-medium text-purple-700">First Hugs</p>
<p class="text-center text-xs text-purple-500">10 hugs</p>
</div>
<div class="achievement" data-threshold="50">
<div class="achievement-icon bg-purple-200 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-2">
<img src="https://em-content.zobj.net/source/microsoft-teams/363/smiling-face-with-halo_1f607.png" alt="Hug Apprentice" class="w-10 h-10">
</div>
<p class="text-center text-sm font-medium text-purple-700">Hug Apprentice</p>
<p class="text-center text-xs text-purple-500">50 hugs</p>
</div>
<div class="achievement" data-threshold="100">
<div class="achievement-icon bg-purple-200 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-2">
<img src="https://em-content.zobj.net/source/microsoft-teams/363/smiling-face-with-sunglasses_1f60e.png" alt="Hug Expert" class="w-10 h-10">
</div>
<p class="text-center text-sm font-medium text-purple-700">Hug Expert</p>
<p class="text-center text-xs text-purple-500">100 hugs</p>
</div>
<div class="achievement" data-threshold="500">
<div class="achievement-icon bg-purple-200 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-2">
<img src="https://em-content.zobj.net/source/microsoft-teams/363/partying-face_1f973.png" alt="Hug Master" class="w-10 h-10">
</div>
<p class="text-center text-sm font-medium text-purple-700">Hug Master</p>
<p class="text-center text-xs text-purple-500">500 hugs</p>
</div>
</div>
</div>
</div>
<!-- Unlock notification -->
<div id="unlock-notification" class="fixed top-4 left-1/2 transform -translate-x-1/2 bg-purple-600 text-white px-6 py-3 rounded-full shadow-lg hidden unlock-notification">
New hugger unlocked!
</div>
<script>
// Game state
let hugs = 0;
let hugsPerSecond = 0;
let clickPower = 1;
let powerLevel = 0;
let maxPower = 100;
let powerDecayRate = 0.5;
// Upgrades data
const upgrades = {
'auto-hugger': { cost: 20, cps: 1, owned: 0 },
'hug-buddy': { cost: 100, cps: 5, owned: 0 },
'hug-team': { cost: 500, cps: 10, owned: 0 },
'hug-factory': { cost: 2000, cps: 50, owned: 0 }
};
// Achievements data
const achievements = {
10: { unlocked: false, name: "First Hugs" },
50: { unlocked: false, name: "Hug Apprentice" },
100: { unlocked: false, name: "Hug Expert" },
500: { unlocked: false, name: "Hug Master" }
};
// Different hugger images
const huggerImages = [
'https://em-content.zobj.net/source/microsoft-teams/363/hugging-face_1f917.png',
'https://em-content.zobj.net/source/microsoft-teams/363/smiling-face-with-hearts_1f970.png',
'https://em-content.zobj.net/source/microsoft-teams/363/smiling-face-with-smiling-eyes_1f60a.png',
'https://em-content.zobj.net/source/microsoft-teams/363/smiling-face-with-heart-eyes_1f60d.png',
'https://em-content.zobj.net/source/microsoft-teams/363/star-struck_1f929.png'
];
let currentHuggerIndex = 0;
// DOM elements
const hugCounter = document.getElementById('hug-counter');
const hugsPerSecondDisplay = document.getElementById('hugs-per-second');
const hugger = document.getElementById('hugger');
const hugEffects = document.getElementById('hug-effects');
const powerBar = document.getElementById('power-bar');
const powerText = document.getElementById('power-text');
const upgradeCards = document.querySelectorAll('.upgrade-card');
const achievementElements = document.querySelectorAll('.achievement');
const unlockNotification = document.getElementById('unlock-notification');
// Initialize the game
function init() {
loadGame();
updateDisplay();
setupEventListeners();
startGameLoop();
}
// Set up event listeners
function setupEventListeners() {
// Click on hugger
hugger.addEventListener('click', () => {
addHugs(clickPower);
powerLevel = Math.min(powerLevel + 2, maxPower);
updatePower();
createClickEffect(event);
// Random chance to change hugger image
if (Math.random() < 0.05 && currentHuggerIndex < huggerImages.length - 1) {
currentHuggerIndex++;
document.getElementById('hugger-image').src = huggerImages[currentHuggerIndex];
showUnlockNotification();
}
});
// Buy upgrades
upgradeCards.forEach(card => {
card.addEventListener('click', () => {
const upgradeId = card.dataset.id;
buyUpgrade(upgradeId);
});
});
}
// Game loop
function startGameLoop() {
setInterval(() => {
// Add passive hugs
if (hugsPerSecond > 0) {
addHugs(hugsPerSecond / 10);
}
// Power decay
if (powerLevel > 0) {
powerLevel = Math.max(0, powerLevel - powerDecayRate);
updatePower();
}
// Check achievements
checkAchievements();
// Save game every 5 seconds
if (Date.now() % 5000 < 50) {
saveGame();
}
}, 100);
}
// Add hugs to the total
function addHugs(amount) {
hugs += amount;
updateDisplay();
}
// Buy an upgrade
function buyUpgrade(upgradeId) {
const upgrade = upgrades[upgradeId];
if (hugs >= upgrade.cost) {
hugs -= upgrade.cost;
upgrade.owned++;
hugsPerSecond += upgrade.cps;
// Increase cost for next purchase
upgrade.cost = Math.floor(upgrade.cost * 1.15);
updateDisplay();
updateUpgradeCards();
}
}
// Check for unlocked achievements
function checkAchievements() {
for (const threshold in achievements) {
if (!achievements[threshold].unlocked && hugs >= parseInt(threshold)) {
achievements[threshold].unlocked = true;
showAchievement(threshold);
}
}
}
// Show achievement notification
function showAchievement(threshold) {
const achievement = achievements[threshold];
const achievementElements = document.querySelectorAll(`.achievement[data-threshold="${threshold}"]`);
achievementElements.forEach(el => {
el.classList.add('animate__animated', 'animate__bounce');
setTimeout(() => {
el.classList.remove('animate__animated', 'animate__bounce');
}, 1000);
// Change style to show it's unlocked
const icon = el.querySelector('.achievement-icon');
icon.classList.remove('bg-purple-200');
icon.classList.add('bg-purple-400', 'shadow-md');
});
}
// Show unlock notification
function showUnlockNotification() {
unlockNotification.classList.remove('hidden');
unlockNotification.classList.add('animate__animated', 'animate__bounce');
setTimeout(() => {
unlockNotification.classList.add('hidden');
unlockNotification.classList.remove('animate__animated', 'animate__bounce');
}, 2000);
}
// Create visual effect when clicking
function createClickEffect(event) {
const effect = document.createElement('div');
effect.className = 'floating-hug';
// Random hug emoji
const hugEmojis = ['❤️', '🤗', '🫂', '💕', '😊'];
const randomEmoji = hugEmojis[Math.floor(Math.random() * hugEmojis.length)];
effect.textContent = `+${clickPower} ${randomEmoji}`;
effect.style.left = `${event.clientX - 20}px`;
effect.style.top = `${event.clientY - 20}px`;
effect.style.color = ['#8b5cf6', '#ec4899', '#6366f1', '#f43f5e'][Math.floor(Math.random() * 4)];
effect.style.fontSize = `${14 + Math.random() * 10}px`;
hugEffects.appendChild(effect);
// Remove after animation
setTimeout(() => {
effect.remove();
}, 2000);
}
// Update power display
function updatePower() {
const percentage = (powerLevel / maxPower) * 100;
powerBar.style.width = `${percentage}%`;
// Update click power based on power level
clickPower = 1 + Math.floor(powerLevel / 20);
powerText.textContent = powerLevel > 0
? `Hug Power: ${clickPower}x (${Math.floor(powerLevel)}%)`
: 'Click faster to increase your hug power!';
}
// Update all displays
function updateDisplay() {
// Update hug counter
hugCounter.textContent = `${Math.floor(hugs)} Hug${hugs !== 1 ? 's' : ''}`;
// Update HPS display
hugsPerSecondDisplay.textContent = `${hugsPerSecond.toFixed(1)} hugs per second`;
// Update upgrade cards
updateUpgradeCards();
}
// Update upgrade cards state
function updateUpgradeCards() {
upgradeCards.forEach(card => {
const upgradeId = card.dataset.id;
const upgrade = upgrades[upgradeId];
// Update cost display
card.querySelector('.cost').textContent = `${Math.floor(upgrade.cost)} Hugs`;
// Update owned count
card.querySelector('.owned').textContent = `Owned: ${upgrade.owned}`;
// Disable if can't afford
if (hugs < upgrade.cost) {
card.classList.add('opacity-50');
} else {
card.classList.remove('opacity-50');
}
});
}
// Save game to localStorage
function saveGame() {
const gameData = {
hugs,
hugsPerSecond,
upgrades,
achievements,
currentHuggerIndex,
lastSave: Date.now()
};
localStorage.setItem('hugsClickerSave', JSON.stringify(gameData));
}
// Load game from localStorage
function loadGame() {
const savedData = localStorage.getItem('hugsClickerSave');
if (savedData) {
const gameData = JSON.parse(savedData);
hugs = gameData.hugs || 0;
hugsPerSecond = gameData.hugsPerSecond || 0;
// Merge upgrades
for (const id in gameData.upgrades) {
if (upgrades[id]) {
upgrades[id].cost = gameData.upgrades[id].cost;
upgrades[id].owned = gameData.upgrades[id].owned;
}
}
// Merge achievements
for (const threshold in gameData.achievements) {
if (achievements[threshold]) {
achievements[threshold].unlocked = gameData.achievements[threshold].unlocked;
}
}
currentHuggerIndex = gameData.currentHuggerIndex || 0;
document.getElementById('hugger-image').src = huggerImages[currentHuggerIndex];
// Calculate offline progress (up to 24 hours)
if (gameData.lastSave) {
const offlineTime = Math.min(Date.now() - gameData.lastSave, 86400000); // Max 24 hours
const offlineHugs = (hugsPerSecond * offlineTime) / 1000;
if (offlineHugs > 0) {
addHugs(offlineHugs);
alert(`Welcome back! You earned ${Math.floor(offlineHugs)} hugs while you were away!`);
}
}
// Update achievements display
for (const threshold in achievements) {
if (achievements[threshold].unlocked) {
const achievementElements = document.querySelectorAll(`.achievement[data-threshold="${threshold}"]`);
achievementElements.forEach(el => {
const icon = el.querySelector('.achievement-icon');
icon.classList.remove('bg-purple-200');
icon.classList.add('bg-purple-400', 'shadow-md');
});
}
}
}
}
// Start the game
init();
</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=FranckAbgrall/hugging-clicker" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>