cat / index.html
velja3's picture
can u add a button for sleep and lights goes off - Initial Deployment
167b0c0 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Virtual Cat Companion</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>
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}
@keyframes shake {
0% { transform: rotate(-5deg); }
50% { transform: rotate(5deg); }
100% { transform: rotate(-5deg); }
}
@keyframes eat {
0% { transform: scale(1); }
50% { transform: scale(1.05) rotate(2deg); }
100% { transform: scale(1); }
}
@keyframes walk {
0% { transform: translateX(0); }
50% { transform: translateX(10px); }
100% { transform: translateX(0); }
}
@keyframes bubble {
0% { transform: scale(0); opacity: 0; }
50% { transform: scale(1.1); opacity: 1; }
100% { transform: scale(1); opacity: 1; }
}
.bounce { animation: bounce 1s infinite; }
.shake { animation: shake 0.5s infinite; }
.eat { animation: eat 0.5s infinite; }
.walk { animation: walk 1s infinite; }
.bubble { animation: bubble 0.5s forwards; }
.cat-status-bar {
transition: width 0.5s ease;
}
.game-container {
background: linear-gradient(to bottom, #f0f9ff 0%, #cbebff 100%);
}
.cat-bath {
background: linear-gradient(to bottom, #e0f7ff 0%, #b3e0ff 100%);
}
.cat-park {
background: linear-gradient(to bottom, #e8f5e9 0%, #c8e6c9 100%);
}
.cat-room {
background: linear-gradient(to bottom, #fff3e0 0%, #ffe0b2 100%);
}
.hidden {
display: none !important;
}
.tooltip {
position: relative;
}
.tooltip:hover::after {
content: attr(data-tooltip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: #333;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
z-index: 10;
}
</style>
</head>
<body class="font-sans bg-pink-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-4xl">
<!-- Header -->
<header class="text-center mb-8">
<h1 class="text-4xl font-bold text-pink-600 mb-2">Virtual Cat Companion</h1>
<p class="text-gray-600">A cute friend to make you feel better ❤️</p>
</header>
<!-- Name Input Screen -->
<div id="name-screen" class="bg-white rounded-xl shadow-lg p-8 text-center mb-8">
<h2 class="text-2xl font-semibold text-pink-500 mb-4">What would you like to name your cat?</h2>
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">
<input type="text" id="cat-name-input" placeholder="Enter cat name" class="px-4 py-2 border border-pink-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-pink-400 w-full sm:w-64">
<button id="name-submit" class="bg-pink-500 hover:bg-pink-600 text-white px-6 py-2 rounded-lg transition duration-200">Create Cat</button>
</div>
<div class="mt-6">
<p class="text-gray-500 mb-2">Choose a color for your cat:</p>
<div class="flex justify-center gap-3">
<div class="w-10 h-10 rounded-full bg-orange-300 border-2 border-orange-400 cursor-pointer cat-color" data-color="orange"></div>
<div class="w-10 h-10 rounded-full bg-gray-300 border-2 border-gray-400 cursor-pointer cat-color" data-color="gray"></div>
<div class="w-10 h-10 rounded-full bg-white border-2 border-gray-200 cursor-pointer cat-color" data-color="white"></div>
<div class="w-10 h-10 rounded-full bg-black border-2 border-gray-800 cursor-pointer cat-color" data-color="black"></div>
<div class="w-10 h-10 rounded-full bg-yellow-100 border-2 border-yellow-200 cursor-pointer cat-color" data-color="cream"></div>
</div>
</div>
</div>
<!-- Main Game Screen -->
<div id="game-screen" class="hidden">
<!-- Cat Info Bar -->
<div class="bg-white rounded-xl shadow-md p-4 mb-6 flex flex-col sm:flex-row justify-between items-center">
<div class="flex items-center mb-3 sm:mb-0">
<h2 id="cat-name-display" class="text-2xl font-bold text-pink-600 mr-4"></h2>
<div class="flex items-center">
<span class="text-yellow-500 mr-1"><i class="fas fa-star"></i></span>
<span id="happiness-level" class="font-medium">100</span>
</div>
</div>
<div class="flex space-x-4">
<button id="settings-btn" class="text-gray-500 hover:text-pink-500 transition">
<i class="fas fa-cog text-xl"></i>
</button>
</div>
</div>
<!-- Game Area -->
<div id="game-area" class="game-container rounded-xl shadow-lg overflow-hidden relative h-96 mb-6">
<!-- Default Room -->
<div id="cat-room" class="cat-room h-full w-full flex flex-col items-center justify-center p-4">
<div id="cat-container" class="relative">
<div id="cat" class="relative">
<!-- Cat will be dynamically generated here -->
</div>
<div id="speech-bubble" class="absolute -top-20 left-1/2 transform -translate-x-1/2 bg-white rounded-lg p-3 shadow-md hidden bubble">
<p id="cat-speech" class="text-sm"></p>
</div>
</div>
<div id="room-items" class="flex mt-8 gap-4">
<div class="bg-pink-100 rounded-lg p-3 cursor-pointer hover:bg-pink-200 transition tooltip" data-tooltip="Food Bowl" id="food-btn">
<i class="fas fa-utensils text-2xl text-pink-600"></i>
</div>
<div class="bg-blue-100 rounded-lg p-3 cursor-pointer hover:bg-blue-200 transition tooltip" data-tooltip="Bath Time" id="bath-btn">
<i class="fas fa-shower text-2xl text-blue-600"></i>
</div>
<div class="bg-green-100 rounded-lg p-3 cursor-pointer hover:bg-green-200 transition tooltip" data-tooltip="Go Outside" id="walk-btn">
<i class="fas fa-tree text-2xl text-green-600"></i>
</div>
<div class="bg-yellow-100 rounded-lg p-3 cursor-pointer hover:bg-yellow-200 transition tooltip" data-tooltip="Play Games" id="play-btn">
<i class="fas fa-gamepad text-2xl text-yellow-600"></i>
</div>
</div>
</div>
<!-- Bath Room -->
<div id="cat-bath" class="cat-bath h-full w-full hidden flex flex-col items-center justify-center p-4">
<div id="bath-cat" class="relative">
<!-- Cat with bath effects -->
</div>
<div class="flex gap-4 mt-8">
<button id="use-soap" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-soap mr-2"></i> Use Soap
</button>
<button id="rinse" class="bg-blue-400 hover:bg-blue-500 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-shower mr-2"></i> Rinse
</button>
<button id="dry" class="bg-yellow-400 hover:bg-yellow-500 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-wind mr-2"></i> Dry
</button>
<button id="exit-bath" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-door-open mr-2"></i> Exit
</button>
</div>
</div>
<!-- Park Scene -->
<div id="cat-park" class="cat-park h-full w-full hidden flex flex-col items-center justify-center p-4">
<div id="walking-cat" class="relative">
<!-- Cat with walking animation -->
</div>
<div class="flex gap-4 mt-8">
<button id="play-fetch" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-dog mr-2"></i> Play Fetch
</button>
<button id="chase-butterflies" class="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-butterfly mr-2"></i> Chase Butterflies
</button>
<button id="exit-park" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-door-open mr-2"></i> Go Home
</button>
</div>
</div>
<!-- Mini Games -->
<div id="mini-games" class="bg-indigo-50 h-full w-full hidden flex flex-col items-center justify-center p-4">
<h3 class="text-2xl font-semibold text-indigo-600 mb-6">Choose a Game to Play</h3>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 w-full max-w-md">
<button id="memory-game-btn" class="bg-indigo-500 hover:bg-indigo-600 text-white px-6 py-4 rounded-lg transition flex flex-col items-center">
<i class="fas fa-brain text-3xl mb-2"></i>
<span>Memory Game</span>
</button>
<button id="whack-a-mouse-btn" class="bg-red-500 hover:bg-red-600 text-white px-6 py-4 rounded-lg transition flex flex-col items-center">
<i class="fas fa-chess-pawn text-3xl mb-2"></i>
<span>Whack-a-Mouse</span>
</button>
<button id="laser-pointer-btn" class="bg-yellow-500 hover:bg-yellow-600 text-white px-6 py-4 rounded-lg transition flex flex-col items-center">
<i class="fas fa-lightbulb text-3xl mb-2"></i>
<span>Laser Pointer</span>
</button>
<button id="exit-games" class="bg-gray-500 hover:bg-gray-600 text-white px-6 py-4 rounded-lg transition flex flex-col items-center">
<i class="fas fa-home text-3xl mb-2"></i>
<span>Back Home</span>
</button>
</div>
</div>
<!-- Memory Game -->
<div id="memory-game" class="h-full w-full hidden flex flex-col items-center justify-center p-4 bg-blue-50">
<h3 class="text-2xl font-semibold text-blue-600 mb-4">Memory Game</h3>
<p class="text-gray-600 mb-6">Match all the pairs of cat pictures!</p>
<div id="memory-board" class="grid grid-cols-4 gap-3 mb-6">
<!-- Cards will be generated here -->
</div>
<div class="flex items-center gap-4">
<span id="memory-score" class="font-bold text-lg">Matches: 0/6</span>
<button id="exit-memory-game" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-times mr-2"></i> Exit Game
</button>
</div>
</div>
<!-- Whack-a-Mouse Game -->
<div id="whack-a-mouse" class="h-full w-full hidden flex flex-col items-center justify-center p-4 bg-red-50">
<h3 class="text-2xl font-semibold text-red-600 mb-4">Whack-a-Mouse</h3>
<p class="text-gray-600 mb-2">Click the mice when they pop up!</p>
<p id="whack-timer" class="text-xl font-bold mb-4">Time: 30s</p>
<div id="whack-score-display" class="text-xl font-bold mb-6">Score: 0</div>
<div id="whack-game-area" class="relative w-64 h-64 bg-amber-100 rounded-full border-4 border-amber-300 mb-6">
<!-- Holes and mice will appear here -->
</div>
<button id="exit-whack-game" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-times mr-2"></i> Exit Game
</button>
</div>
<!-- Laser Pointer Game -->
<div id="laser-pointer" class="h-full w-full hidden flex flex-col items-center justify-center p-4 bg-yellow-50">
<h3 class="text-2xl font-semibold text-yellow-600 mb-4">Laser Pointer</h3>
<p class="text-gray-600 mb-6">Move your mouse to make the cat chase the laser!</p>
<div id="laser-game-area" class="relative w-full h-64 bg-gray-100 rounded-lg mb-6">
<div id="laser-dot" class="w-4 h-4 bg-red-500 rounded-full absolute hidden"></div>
<div id="laser-cat" class="absolute bottom-0 left-1/2 transform -translate-x-1/2">
<!-- Cat will be here -->
</div>
</div>
<div class="flex items-center gap-4">
<span id="laser-score" class="font-bold text-lg">Points: 0</span>
<button id="exit-laser-game" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-times mr-2"></i> Exit Game
</button>
</div>
</div>
</div>
<!-- Cat Status Bars -->
<div class="bg-white rounded-xl shadow-md p-4 mb-6">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<div class="flex justify-between mb-1">
<span class="font-medium text-gray-700"><i class="fas fa-heart text-red-500 mr-2"></i> Happiness</span>
<span id="happiness-percent" class="font-medium">100%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="happiness-bar" class="cat-status-bar bg-pink-500 h-2.5 rounded-full" style="width: 100%"></div>
</div>
</div>
<div>
<div class="flex justify-between mb-1">
<span class="font-medium text-gray-700"><i class="fas fa-utensils text-yellow-500 mr-2"></i> Hunger</span>
<span id="hunger-percent" class="font-medium">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="hunger-bar" class="cat-status-bar bg-yellow-500 h-2.5 rounded-full" style="width: 0%"></div>
</div>
</div>
<div>
<div class="flex justify-between mb-1">
<span class="font-medium text-gray-700"><i class="fas fa-shower text-blue-500 mr-2"></i> Cleanliness</span>
<span id="clean-percent" class="font-medium">100%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="clean-bar" class="cat-status-bar bg-blue-500 h-2.5 rounded-full" style="width: 100%"></div>
</div>
</div>
<div>
<div class="flex justify-between mb-1">
<span class="font-medium text-gray-700"><i class="fas fa-bolt text-green-500 mr-2"></i> Energy</span>
<span id="energy-percent" class="font-medium">100%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="energy-bar" class="cat-status-bar bg-green-500 h-2.5 rounded-full" style="width: 100%"></div>
</div>
</div>
</div>
</div>
<!-- Food Selection -->
<div id="food-selection" class="hidden bg-white rounded-xl shadow-md p-4 mb-6">
<h3 class="text-xl font-semibold text-gray-700 mb-4">What would you like to feed your cat?</h3>
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4">
<div class="food-item bg-pink-50 rounded-lg p-4 text-center cursor-pointer hover:bg-pink-100 transition" data-food="fish" data-energy="10">
<i class="fas fa-fish text-3xl text-blue-500 mb-2"></i>
<p class="font-medium">Fish</p>
</div>
<div class="food-item bg-yellow-50 rounded-lg p-4 text-center cursor-pointer hover:bg-yellow-100 transition" data-food="chicken" data-energy="15">
<i class="fas fa-drumstick-bite text-3xl text-yellow-600 mb-2"></i>
<p class="font-medium">Chicken</p>
</div>
<div class="food-item bg-green-50 rounded-lg p-4 text-center cursor-pointer hover:bg-green-100 transition" data-food="treat" data-energy="5">
<i class="fas fa-cookie text-3xl text-brown-500 mb-2"></i>
<p class="font-medium">Treat</p>
</div>
<div class="food-item bg-blue-50 rounded-lg p-4 text-center cursor-pointer hover:bg-blue-100 transition" data-food="milk" data-energy="7">
<i class="fas fa-wine-bottle text-3xl text-blue-300 mb-2"></i>
<p class="font-medium">Milk</p>
</div>
</div>
<button id="cancel-food" class="mt-4 bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-times mr-2"></i> Cancel
</button>
</div>
</div>
<!-- Settings Modal -->
<div id="settings-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
<div class="bg-white rounded-xl p-6 max-w-md w-full mx-4">
<h3 class="text-xl font-semibold mb-4">Settings</h3>
<div class="mb-4">
<label class="block text-gray-700 mb-2">Change Cat Name</label>
<div class="flex">
<input type="text" id="rename-input" class="px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-pink-400 w-full">
<button id="rename-btn" class="bg-pink-500 hover:bg-pink-600 text-white px-4 py-2 rounded-r-lg transition">Change</button>
</div>
</div>
<div class="mb-6">
<label class="block text-gray-700 mb-2">Change Cat Color</label>
<div class="flex gap-3">
<div class="w-10 h-10 rounded-full bg-orange-300 border-2 border-orange-400 cursor-pointer cat-color-setting" data-color="orange"></div>
<div class="w-10 h-10 rounded-full bg-gray-300 border-2 border-gray-400 cursor-pointer cat-color-setting" data-color="gray"></div>
<div class="w-10 h-10 rounded-full bg-white border-2 border-gray-200 cursor-pointer cat-color-setting" data-color="white"></div>
<div class="w-10 h-10 rounded-full bg-black border-2 border-gray-800 cursor-pointer cat-color-setting" data-color="black"></div>
<div class="w-10 h-10 rounded-full bg-yellow-100 border-2 border-yellow-200 cursor-pointer cat-color-setting" data-color="cream"></div>
</div>
</div>
<div class="flex justify-between">
<button id="reset-game" class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-trash-alt mr-2"></i> Reset Game
</button>
<button id="close-settings" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition">
<i class="fas fa-times mr-2"></i> Close
</button>
</div>
</div>
</div>
<!-- Reset Confirmation Modal -->
<div id="reset-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
<div class="bg-white rounded-xl p-6 max-w-md w-full mx-4">
<h3 class="text-xl font-semibold mb-4">Reset Game</h3>
<p class="text-gray-700 mb-6">Are you sure you want to reset your game? All progress will be lost.</p>
<div class="flex justify-end gap-4">
<button id="cancel-reset" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-lg transition">
Cancel
</button>
<button id="confirm-reset" class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition">
Reset
</button>
</div>
</div>
</div>
</div>
<script>
// Game State
const gameState = {
catName: "",
catColor: "orange",
happiness: 100,
hunger: 0,
cleanliness: 100,
energy: 100,
lastFed: null,
lastPlayed: null,
lastCleaned: null,
speechTimeout: null,
needs: {
hungry: false,
dirty: false,
lonely: false,
tired: false
},
gameActive: false
};
// DOM Elements
const nameScreen = document.getElementById('name-screen');
const gameScreen = document.getElementById('game-screen');
const catNameInput = document.getElementById('cat-name-input');
const nameSubmit = document.getElementById('name-submit');
const catNameDisplay = document.getElementById('cat-name-display');
const catContainer = document.getElementById('cat');
const bathCat = document.getElementById('bath-cat');
const walkingCat = document.getElementById('walking-cat');
const laserCat = document.getElementById('laser-cat');
const speechBubble = document.getElementById('speech-bubble');
const catSpeech = document.getElementById('cat-speech');
const happinessBar = document.getElementById('happiness-bar');
const hungerBar = document.getElementById('hunger-bar');
const cleanBar = document.getElementById('clean-bar');
const energyBar = document.getElementById('energy-bar');
const happinessPercent = document.getElementById('happiness-percent');
const hungerPercent = document.getElementById('hunger-percent');
const cleanPercent = document.getElementById('clean-percent');
const energyPercent = document.getElementById('energy-percent');
const happinessLevel = document.getElementById('happiness-level');
const foodBtn = document.getElementById('food-btn');
const bathBtn = document.getElementById('bath-btn');
const walkBtn = document.getElementById('walk-btn');
const playBtn = document.getElementById('play-btn');
const catRoom = document.getElementById('cat-room');
const catBath = document.getElementById('cat-bath');
const catPark = document.getElementById('cat-park');
const miniGames = document.getElementById('mini-games');
const foodSelection = document.getElementById('food-selection');
const cancelFood = document.getElementById('cancel-food');
const useSoap = document.getElementById('use-soap');
const rinse = document.getElementById('rinse');
const dry = document.getElementById('dry');
const exitBath = document.getElementById('exit-bath');
const playFetch = document.getElementById('play-fetch');
const chaseButterflies = document.getElementById('chase-butterflies');
const exitPark = document.getElementById('exit-park');
const exitGames = document.getElementById('exit-games');
const memoryGameBtn = document.getElementById('memory-game-btn');
const whackAMouseBtn = document.getElementById('whack-a-mouse-btn');
const laserPointerBtn = document.getElementById('laser-pointer-btn');
const memoryGame = document.getElementById('memory-game');
const whackAMouse = document.getElementById('whack-a-mouse');
const laserPointer = document.getElementById('laser-pointer');
const memoryBoard = document.getElementById('memory-board');
const memoryScore = document.getElementById('memory-score');
const exitMemoryGame = document.getElementById('exit-memory-game');
const whackGameArea = document.getElementById('whack-game-area');
const whackTimer = document.getElementById('whack-timer');
const whackScoreDisplay = document.getElementById('whack-score-display');
const exitWhackGame = document.getElementById('exit-whack-game');
const laserGameArea = document.getElementById('laser-game-area');
const laserDot = document.getElementById('laser-dot');
const laserScore = document.getElementById('laser-score');
const exitLaserGame = document.getElementById('exit-laser-game');
const settingsBtn = document.getElementById('settings-btn');
const settingsModal = document.getElementById('settings-modal');
const closeSettings = document.getElementById('close-settings');
const renameInput = document.getElementById('rename-input');
const renameBtn = document.getElementById('rename-btn');
const resetGame = document.getElementById('reset-game');
const resetModal = document.getElementById('reset-modal');
const cancelReset = document.getElementById('cancel-reset');
const confirmReset = document.getElementById('confirm-reset');
const colorButtons = document.querySelectorAll('.cat-color');
const colorSettingButtons = document.querySelectorAll('.cat-color-setting');
const foodItems = document.querySelectorAll('.food-item');
// Initialize game
function initGame() {
// Load saved game if exists
const savedGame = localStorage.getItem('virtualCatGame');
if (savedGame) {
const parsedGame = JSON.parse(savedGame);
Object.assign(gameState, parsedGame);
// Show game screen
nameScreen.classList.add('hidden');
gameScreen.classList.remove('hidden');
// Set cat name and color
catNameDisplay.textContent = gameState.catName;
renameInput.value = gameState.catName;
updateCatColor();
// Update stats
updateStats();
gameState.gameActive = true;
startNeedsDecay();
}
}
// Start the game
nameSubmit.addEventListener('click', () => {
const name = catNameInput.value.trim();
if (name) {
gameState.catName = name;
catNameDisplay.textContent = name;
renameInput.value = name;
nameScreen.classList.add('hidden');
gameScreen.classList.remove('hidden');
updateCatColor();
gameState.gameActive = true;
saveGame();
startNeedsDecay();
// Welcome message
setTimeout(() => {
makeCatTalk(`Hi ${name}! I'm so happy to meet you!`);
}, 1000);
}
});
// Cat color selection
colorButtons.forEach(button => {
button.addEventListener('click', () => {
gameState.catColor = button.dataset.color;
updateCatColor();
});
});
colorSettingButtons.forEach(button => {
button.addEventListener('click', () => {
gameState.catColor = button.dataset.color;
updateCatColor();
saveGame();
});
});
// Update cat color
function updateCatColor() {
let catColorClass = '';
switch(gameState.catColor) {
case 'orange':
catColorClass = 'bg-orange-300';
break;
case 'gray':
catColorClass = 'bg-gray-300';
break;
case 'white':
catColorClass = 'bg-white';
break;
case 'black':
catColorClass = 'bg-gray-800';
break;
case 'cream':
catColorClass = 'bg-yellow-100';
break;
}
// Update main cat
catContainer.innerHTML = `
<div class="relative w-32 h-24 ${catColorClass} rounded-tl-full rounded-tr-full rounded-br-full rounded-bl-full">
<div class="absolute -top-2 -left-2 w-8 h-6 ${catColorClass} rounded-full transform rotate-45"></div>
<div class="absolute -top-2 -right-2 w-8 h-6 ${catColorClass} rounded-full transform -rotate-45"></div>
<div class="absolute top-6 left-4 w-4 h-4 bg-white rounded-full"></div>
<div class="absolute top-6 right-4 w-4 h-4 bg-white rounded-full"></div>
<div class="absolute top-7 left-5 w-2 h-2 bg-black rounded-full"></div>
<div class="absolute top-7 right-5 w-2 h-2 bg-black rounded-full"></div>
<div class="absolute top-10 left-1/2 transform -translate-x-1/2 w-3 h-2 bg-pink-300 rounded-full"></div>
<div class="absolute -bottom-4 left-1/2 transform -translate-x-1/2 w-24 h-8 ${catColorClass} rounded-b-full"></div>
<div class="absolute -bottom-8 left-6 w-4 h-6 ${catColorClass} rounded-b-full"></div>
<div class="absolute -bottom-8 right-6 w-4 h-6 ${catColorClass} rounded-b-full"></div>
</div>
`;
// Update bath cat
bathCat.innerHTML = `
<div class="relative w-32 h-24 ${catColorClass} rounded-tl-full rounded-tr-full rounded-br-full rounded-bl-full">
<div class="absolute -top-2 -left-2 w-8 h-6 ${catColorClass} rounded-full transform rotate-45"></div>
<div class="absolute -top-2 -right-2 w-8 h-6 ${catColorClass} rounded-full transform -rotate-45"></div>
<div class="absolute top-6 left-4 w-4 h-4 bg-white rounded-full"></div>
<div class="absolute top-6 right-4 w-4 h-4 bg-white rounded-full"></div>
<div class="absolute top-7 left-5 w-2 h-2 bg-black rounded-full"></div>
<div class="absolute top-7 right-5 w-2 h-2 bg-black rounded-full"></div>
<div class="absolute top-10 left-1/2 transform -translate-x-1/2 w-3 h-2 bg-pink-300 rounded-full"></div>
<div class="absolute -bottom-4 left-1/2 transform -translate-x-1/2 w-24 h-8 ${catColorClass} rounded-b-full"></div>
<div class="absolute -bottom-8 left-6 w-4 h-6 ${catColorClass} rounded-b-full"></div>
<div class="absolute -bottom-8 right-6 w-4 h-6 ${catColorClass} rounded-b-full"></div>
</div>
`;
// Update walking cat
walkingCat.innerHTML = `
<div class="relative w-32 h-24 ${catColorClass} rounded-tl-full rounded-tr-full rounded-br-full rounded-bl-full walk">
<div class="absolute -top-2 -left-2 w-8 h-6 ${catColorClass} rounded-full transform rotate-45"></div>
<div class="absolute -top-2 -right-2 w-8 h-6 ${catColorClass} rounded-full transform -rotate-45"></div>
<div class="absolute top-6 left-4 w-4 h-4 bg-white rounded-full"></div>
<div class="absolute top-6 right-4 w-4 h-4 bg-white rounded-full"></div>
<div class="absolute top-7 left-5 w-2 h-2 bg-black rounded-full"></div>
<div class="absolute top-7 right-5 w-2 h-2 bg-black rounded-full"></div>
<div class="absolute top-10 left-1/2 transform -translate-x-1/2 w-3 h-2 bg-pink-300 rounded-full"></div>
<div class="absolute -bottom-4 left-1/2 transform -translate-x-1/2 w-24 h-8 ${catColorClass} rounded-b-full"></div>
<div class="absolute -bottom-8 left-6 w-4 h-6 ${catColorClass} rounded-b-full"></div>
<div class="absolute -bottom-8 right-6 w-4 h-6 ${catColorClass} rounded-b-full"></div>
</div>
`;
// Update laser cat
laserCat.innerHTML = `
<div class="relative w-32 h-24 ${catColorClass} rounded-tl-full rounded-tr-full rounded-br-full rounded-bl-full">
<div class="absolute -top-2 -left-2 w-8 h-6 ${catColorClass} rounded-full transform rotate-45"></div>
<div class="absolute -top-2 -right-2 w-8 h-6 ${catColorClass} rounded-full transform -rotate-45"></div>
<div class="absolute top-6 left-4 w-4 h-4 bg-white rounded-full"></div>
<div class="absolute top-6 right-4 w-4 h-4 bg-white rounded-full"></div>
<div class="absolute top-7 left-5 w-2 h-2 bg-black rounded-full"></div>
<div class="absolute top-7 right-5 w-2 h-2 bg-black rounded-full"></div>
<div class="absolute top-10 left-1/2 transform -translate-x-1/2 w-3 h-2 bg-pink-300 rounded-full"></div>
<div class="absolute -bottom-4 left-1/2 transform -translate-x-1/2 w-24 h-8 ${catColorClass} rounded-b-full"></div>
<div class="absolute -bottom-8 left-6 w-4 h-6 ${catColorClass} rounded-b-full"></div>
<div class="absolute -bottom-8 right-6 w-4 h-6 ${catColorClass} rounded-b-full"></div>
</div>
`;
}
// Make cat talk
function makeCatTalk(message) {
if (gameState.speechTimeout) {
clearTimeout(gameState.speechTimeout);
}
catSpeech.textContent = message;
speechBubble.classList.remove('hidden');
speechBubble.classList.add('bubble');
// Remove bubble after 3 seconds
gameState.speechTimeout = setTimeout(() => {
speechBubble.classList.add('hidden');
}, 3000);
}
// Update stats display
function updateStats() {
happinessBar.style.width = `${gameState.happiness}%`;
hungerBar.style.width = `${gameState.hunger}%`;
cleanBar.style.width = `${gameState.cleanliness}%`;
energyBar.style.width = `${gameState.energy}%`;
happinessPercent.textContent = `${gameState.happiness}%`;
hungerPercent.textContent = `${gameState.hunger}%`;
cleanPercent.textContent = `${gameState.cleanliness}%`;
energyPercent.textContent = `${gameState.energy}%`;
happinessLevel.textContent = gameState.happiness;
// Check needs
checkNeeds();
}
// Check cat needs
function checkNeeds() {
gameState.needs.hungry = gameState.hunger > 70;
gameState.needs.dirty = gameState.cleanliness < 30;
gameState.needs.lonely = gameState.happiness < 30;
gameState.needs.tired = gameState.energy < 20;
// Make cat complain about needs
if (gameState.needs.hungry && Math.random() > 0.7) {
makeCatTalk("I'm so hungry...");
} else if (gameState.needs.dirty && Math.random() > 0.7) {
makeCatTalk("I feel dirty...");
} else if (gameState.needs.lonely && Math.random() > 0.7) {
makeCatTalk("Play with me!");
} else if (gameState.needs.tired && Math.random() > 0.7) {
makeCatTalk("I'm so tired...");
} else if (Math.random() > 0.95) {
const randomMessages = [
"I love you!",
"Pet me please!",
"You're the best!",
"Meow!",
"Purrrrr...",
`Hi ${gameState.catName}!`
];
makeCatTalk(randomMessages[Math.floor(Math.random() * randomMessages.length)]);
}
}
// Start needs decay
function startNeedsDecay() {
setInterval(() => {
if (!gameState.gameActive) return;
// Happiness decays slowly over time
if (gameState.happiness > 0) {
gameState.happiness = Math.max(0, gameState.happiness - 0.2);
}
// Hunger increases over time
if (gameState.hunger < 100) {
gameState.hunger = Math.min(100, gameState.hunger + 0.3);
}
// Cleanliness decreases over time
if (gameState.cleanliness > 0) {
gameState.cleanliness = Math.max(0, gameState.cleanliness - 0.1);
}
// Energy recovers slowly when not playing
if (gameState.energy < 100) {
gameState.energy = Math.min(100, gameState.energy + 0.1);
}
updateStats();
saveGame();
}, 1000);
}
// Save game state
function saveGame() {
localStorage.setItem('virtualCatGame', JSON.stringify(gameState));
}
// Food button
foodBtn.addEventListener('click', () => {
catRoom.classList.add('hidden');
foodSelection.classList.remove('hidden');
});
// Food selection
foodItems.forEach(item => {
item.addEventListener('click', () => {
const foodType = item.dataset.food;
const energyGain = parseInt(item.dataset.energy);
// Reduce hunger
gameState.hunger = Math.max(0, gameState.hunger - 30);
// Increase energy
gameState.energy = Math.min(100, gameState.energy + energyGain);
// Small happiness boost
gameState.happiness = Math.min(100, gameState.happiness + 5);
// Update stats
updateStats();
saveGame();
// Show eating animation
catContainer.classList.add('eat');
makeCatTalk(`Yummy ${foodType}!`);
// Hide food selection
foodSelection.classList.add('hidden');
catRoom.classList.remove('hidden');
// Stop eating animation after 2 seconds
setTimeout(() => {
catContainer.classList.remove('eat');
}, 2000);
});
});
// Cancel food
cancelFood.addEventListener('click', () => {
foodSelection.classList.add('hidden');
catRoom.classList.remove('hidden');
});
// Bath button
bathBtn.addEventListener('click', () => {
catRoom.classList.add('hidden');
catBath.classList.remove('hidden');
makeCatTalk("Do I really need a bath?");
});
// Use soap
useSoap.addEventListener('click', () => {
makeCatTalk("Bubbles everywhere!");
bathCat.innerHTML += `
<div class="absolute top-0 left-0 w-full h-full flex justify-center items-center">
<div class="bubble w-8 h-8 bg-white rounded-full opacity-70"></div>
<div class="bubble w-6 h-6 bg-white rounded-full opacity-70" style="animation-delay: 0.2s"></div>
<div class="bubble w-5 h-5 bg-white rounded-full opacity-70" style="animation-delay: 0.4s"></div>
</div>
`;
// Increase cleanliness
gameState.cleanliness = Math.min(100, gameState.cleanliness + 20);
updateStats();
saveGame();
});
// Rinse
rinse.addEventListener('click', () => {
makeCatTalk("That feels nice!");
bathCat.innerHTML += `
<div class="absolute top-0 left-0 w-full h-full flex justify-center items-center">
<div class="absolute top-0 left-1/2 transform -translate-x-1/2 w-4 h-16 bg-blue-200 rounded-full"></div>
</div>
`;
// Increase cleanliness more
gameState.cleanliness = Math.min(100, gameState.cleanliness + 30);
updateStats();
saveGame();
});
// Dry
dry.addEventListener('click', () => {
makeCatTalk("Ahhh, all dry now!");
// Max cleanliness
gameState.cleanliness = 100;
updateStats();
saveGame();
// Exit bath after drying
setTimeout(() => {
catBath.classList.add('hidden');
catRoom.classList.remove('hidden');
}, 1000);
});
// Exit bath
exitBath.addEventListener('click', () => {
catBath.classList.add('hidden');
catRoom.classList.remove('hidden');
});
// Walk button
walkBtn.addEventListener('click', () => {
if (gameState.energy < 20) {
makeCatTalk("I'm too tired to go outside...");
return;
}
catRoom.classList.add('hidden');
catPark.classList.remove('hidden');
makeCatTalk("Yay! Outside time!");
// Small happiness boost
gameState.happiness = Math.min(100, gameState.happiness + 10);
updateStats();
saveGame();
});
// Play fetch
playFetch.addEventListener('click', () => {
if (gameState.energy < 15) {
makeCatTalk("I need to rest first...");
return;
}
makeCatTalk("Throw the ball! Throw the ball!");
// Add ball to park
const ball = document.createElement('div');
ball.className = 'absolute bottom-10 left-1/2 transform -translate-x-1/2 w-8 h-8 bg-red-500 rounded-full bounce';
walkingCat.parentNode.appendChild(ball);
// Reduce energy but increase happiness
gameState.energy = Math.max(0, gameState.energy - 15);
gameState.happiness = Math.min(100, gameState.happiness + 15);
updateStats();
saveGame();
// Remove ball after animation
setTimeout(() => {
ball.remove();
}, 2000);
});
// Chase butterflies
chaseButterflies.addEventListener('click', () => {
if (gameState.energy < 10) {
makeCatTalk("Maybe later...");
return;
}
makeCatTalk("Butterflies! I must catch them!");
// Add butterflies
for (let i = 0; i < 3; i++) {
const butterfly = document.createElement('div');
butterfly.className = `absolute top-${10 + i*10} left-${20 + i*20} text-2xl text-pink-400 fas fa-butterfly`;
butterfly.style.animation = `fly${i+1} 3s infinite`;
walkingCat.parentNode.appendChild(butterfly);
// Add fly animation
const style = document.createElement('style');
style.textContent = `
@keyframes fly${i+1} {
0% { transform: translate(0, 0); }
25% { transform: translate(${20 + i*10}px, ${10 + i*5}px); }
50% { transform: translate(${40 + i*20}px, 0); }
75% { transform: translate(${20 + i*10}px, ${-10 - i*5}px); }
100% { transform: translate(0, 0); }
}
`;
document.head.appendChild(style);
}
// Reduce energy but increase happiness more
gameState.energy = Math.max(0, gameState.energy - 10);
gameState.happiness = Math.min(100, gameState.happiness + 20);
updateStats();
saveGame();
// Remove butterflies after some time
setTimeout(() => {
const butterflies = document.querySelectorAll('.fa-butterfly');
butterflies.forEach(b => b.remove());
}, 3000);
});
// Exit park
exitPark.addEventListener('click', () => {
catPark.classList.add('hidden');
catRoom.classList.remove('hidden');
});
// Play button
playBtn.addEventListener('click', () => {
catRoom.classList.add('hidden');
miniGames.classList.remove('hidden');
});
// Exit games
exitGames.addEventListener('click', () => {
miniGames.classList.add('hidden');
catRoom.classList.remove('hidden');
});
// Memory game
memoryGameBtn.addEventListener('click', () => {
if (gameState.energy < 20) {
makeCatTalk("I'm too tired to play right now...");
miniGames.classList.add('hidden');
catRoom.classList.remove('hidden');
return;
}
miniGames.classList.add('hidden');
memoryGame.classList.remove('hidden');
setupMemoryGame();
});
// Setup memory game
function setupMemoryGame() {
memoryBoard.innerHTML = '';
const emojis = ['😺', '🐱', '😸', '🐈', '😹', '🐾'];
const cards = [...emojis, ...emojis].sort(() => 0.5 - Math.random());
let flippedCards = [];
let matchedPairs = 0;
cards.forEach((emoji, index) => {
const card = document.createElement('div');
card.className = 'w-16 h-16 bg-white rounded-lg flex items-center justify-center text-3xl cursor-pointer shadow-md hover:bg-gray-100 transition';
card.dataset.emoji = emoji;
card.dataset.index = index;
card.innerHTML = '<div class="w-full h-full bg-pink-400 rounded-lg flex items-center justify-center">?</div>';
card.addEventListener('click', () => {
if (flippedCards.length < 2 && !card.classList.contains('flipped') && !card.classList.contains('matched')) {
flipCard(card);
if (flippedCards.length === 2) {
checkForMatch();
}
}
});
memoryBoard.appendChild(card);
});
memoryScore.textContent = 'Matches: 0/6';
function flipCard(card) {
card.classList.add('flipped');
card.innerHTML = card.dataset.emoji;
flippedCards.push(card);
}
function checkForMatch() {
const [card1, card2] = flippedCards;
if (card1.dataset.emoji === card2.dataset.emoji) {
card1.classList.add('matched');
card2.classList.add('matched');
matchedPairs++;
memoryScore.textContent = `Matches: ${matchedPairs}/6`;
flippedCards = [];
if (matchedPairs === 6) {
// Game completed
gameState.happiness = Math.min(100, gameState.happiness + 25);
gameState.energy = Math.max(0, gameState.energy - 20);
updateStats();
saveGame();
setTimeout(() => {
makeCatTalk("I won! That was fun!");
memoryGame.classList.add('hidden');
catRoom.classList.remove('hidden');
}, 1000);
}
} else {
setTimeout(() => {
card1.innerHTML = '<div class="w-full h-full bg-pink-400 rounded-lg flex items-center justify-center">?</div>';
card2.innerHTML = '<div class="w-full h-full bg-pink-400 rounded-lg flex items-center justify-center">?</div>';
card1.classList.remove('flipped');
card2.classList.remove('flipped');
flippedCards = [];
}, 1000);
}
}
}
// Exit memory game
exitMemoryGame.addEventListener('click', () => {
memoryGame.classList.add('hidden');
catRoom.classList.remove('hidden');
});
// Whack-a-mouse game
whackAMouseBtn.addEventListener('click', () => {
if (gameState.energy < 25) {
makeCatTalk("I need a nap first...");
miniGames.classList.add('hidden');
catRoom.classList.remove('hidden');
return;
}
miniGames.classList.add('hidden');
whackAMouse.classList.remove('hidden');
setupWhackGame();
});
// Setup whack-a-mouse game
function setupWhackGame() {
whackGameArea.innerHTML = '';
let score = 0;
let timeLeft = 30;
whackScoreDisplay.textContent = 'Score: 0';
whackTimer.textContent = `Time: ${timeLeft}s`;
// Create holes
for (let i = 0; i < 6; i++) {
const hole = document.createElement('div');
hole.className = 'absolute w-10 h-10 bg-gray-700 rounded-full';
// Position holes in a circle
const angle = (i / 6) * Math.PI * 2;
const radius = 80;
hole.style.left = `calc(50% + ${Math.cos(angle) * radius}px - 20px)`;
hole.style.top = `calc(50% + ${Math.sin(angle) * radius}px - 20px)`;
whackGameArea.appendChild(hole);
}
// Game timer
const timer = setInterval(() => {
timeLeft--;
whackTimer.textContent = `Time: ${timeLeft}s`;
if (timeLeft <= 0) {
clearInterval(timer);
clearInterval(mouseInterval);
// Game over
gameState.happiness = Math.min(100, gameState.happiness + score * 2);
gameState.energy = Math.max(0, gameState.energy - 25);
updateStats();
saveGame();
setTimeout(() => {
makeCatTalk(`I got ${score} mice!`);
whackAMouse.classList.add('hidden');
catRoom.classList.remove('hidden');
}, 1000);
}
}, 1000);
// Mouse appearing
let mouseInterval = setInterval(() => {
if (timeLeft <= 0) return;
const holes = document.querySelectorAll('#whack-game-area > div');
const randomHole = holes[Math.floor(Math.random() * holes.length)];
// Create mouse
const mouse = document.createElement('div');
mouse.className = 'absolute w-8 h-6 bg-gray-500 rounded-full cursor-pointer';
mouse.style.left = '6px';
mouse.style.top = '-10px';
// Add mouse to hole
randomHole.appendChild(mouse);
// Click to whack
mouse.addEventListener('click', () => {
score++;
whackScoreDisplay.textContent = `Score: ${score}`;
// Show whacked mouse
mouse.className = 'absolute w-8 h-6 bg-red-500 rounded-full';
mouse.innerHTML = '<div class="absolute top-0 left-0 w-full h-full flex justify-center items-center text-white">X</div>';
setTimeout(() => {
mouse.remove();
}, 500);
});
// Mouse disappears after some time
setTimeout(() => {
if (mouse.parentNode) {
mouse.remove();
}
}, 1000);
}, 800);
}
// Exit whack game
exitWhackGame.addEventListener('click', () => {
whackAMouse.classList.add('hidden');
catRoom.classList.remove('hidden');
});
// Laser pointer game
laserPointerBtn.addEventListener('click', () => {
if (gameState.energy < 15) {
makeCatTalk("Maybe after a short nap...");
miniGames.classList.add('hidden');
catRoom.classList.remove('hidden');
return;
}
miniGames.classList.add('hidden');
laserPointer.classList.remove('hidden');
setupLaserGame();
});
// Setup laser pointer game
function setupLaserGame() {
let score = 0;
let gameTime = 20;
laserScore.textContent = 'Points: 0';
// Show laser dot
laserDot.classList.remove('hidden');
// Move laser with mouse
laserGameArea.addEventListener('mousemove', (e) => {
const rect = laserGameArea.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
laserDot.style.left = `${x - 8}px`;
laserDot.style.top = `${y - 8}px`;
// Move cat towards laser
const catRect = laserCat.getBoundingClientRect();
const catX = catRect.left - rect.left + catRect.width / 2;
const catY = catRect.top - rect.top + catRect.height / 2;
const dx = x - catX;
const dy = y - catY;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
// Cat is close to laser
const angle = Math.atan2(dy, dx);
const moveX = Math.cos(angle) * 5;
const moveY = Math.sin(angle) * 5;
laserCat.style.transform = `translateX(-50%) translate(${moveX}px, ${moveY}px)`;
// Increase score when cat is chasing
score++;
laserScore.textContent = `Points: ${score}`;
}
});
// Game timer
const timer = setInterval(() => {
gameTime--;
if (gameTime <= 0) {
clearInterval(timer);
// Game over
gameState.happiness = Math.min(100, gameState.happiness + score / 10);
gameState.energy = Math.max(0, gameState.energy - 15);
updateStats();
saveGame();
laserDot.classList.add('hidden');
setTimeout(() => {
makeCatTalk("That was exhausting but fun!");
laserPointer.classList.add('hidden');
catRoom.classList.remove('hidden');
}, 1000);
}
}, 1000);
}
// Exit laser game
exitLaserGame.addEventListener('click', () => {
laserPointer.classList.add('hidden');
catRoom.classList.remove('hidden');
});
// Settings button
settingsBtn.addEventListener('click', () => {
settingsModal.classList.remove('hidden');
});
// Close settings
closeSettings.addEventListener('click', () => {
settingsModal.classList.add('hidden');
});
// Rename cat
renameBtn.addEventListener('click', () => {
const newName = renameInput.value.trim();
if (newName) {
gameState.catName = newName;
catNameDisplay.textContent = newName;
saveGame();
makeCatTalk(`I like my new name, ${newName}!`);
}
});
// Reset game
resetGame.addEventListener('click', () => {
settingsModal.classList.add('hidden');
resetModal.classList.remove('hidden');
});
// Cancel reset
cancelReset.addEventListener('click', () => {
resetModal.classList.add('hidden');
});
// Confirm reset
confirmReset.addEventListener('click', () => {
localStorage.removeItem('virtualCatGame');
resetModal.classList.add('hidden');
gameScreen.classList.add('hidden');
nameScreen.classList.remove('hidden');
catNameInput.value = '';
gameState.catName = "";
gameState.happiness = 100;
gameState.hunger = 0;
gameState.cleanliness = 100;
gameState.energy = 100;
gameState.gameActive = false;
});
// Pet the cat
catContainer.addEventListener('click', () => {
if (!catContainer.classList.contains('shake')) {
catContainer.classList.add('shake');
gameState.happiness = Math.min(100, gameState.happiness + 5);
updateStats();
saveGame();
setTimeout(() => {
catContainer.classList.remove('shake');
}, 500);
const happyMessages = [
"Purrrrr...",
"That feels nice!",
"More pets please!",
"I love you!",
"You're the best!"
];
makeCatTalk(happyMessages[Math.floor(Math.random() * happyMessages.length)]);
}
});
// Initialize the game
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=velja3/cat" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>