picnic-panic-pals / index.html
Pappak's picture
Promote version 8955b94 to main
e39a142 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Picnic Panic Pals</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cannon-es@0.19.0/dist/cannon-es.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.globe.min.js"></script>
<style>
#gameCanvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.ragdoll {
transition: all 0.3s ease;
}
.food-item {
cursor: grab;
transition: transform 0.2s;
}
.food-item:active {
cursor: grabbing;
transform: scale(1.1);
}
</style>
</head>
<body class="bg-green-50 overflow-hidden">
<canvas id="gameCanvas"></canvas>
<div class="min-h-screen flex flex-col items-center justify-center p-4">
<div class="bg-white bg-opacity-90 rounded-3xl shadow-2xl p-8 max-w-4xl w-full">
<div class="flex justify-between items-center mb-6">
<h1 class="text-4xl font-bold text-green-700">Picnic Panic Pals</h1>
<div class="flex items-center space-x-4">
<div class="bg-yellow-100 px-4 py-2 rounded-full flex items-center">
<i data-feather="clock" class="text-yellow-600 mr-2"></i>
<span class="font-bold text-yellow-800" id="timer">03:00</span>
</div>
<div class="bg-red-100 px-4 py-2 rounded-full flex items-center">
<i data-feather="heart" class="text-red-600 mr-2"></i>
<span class="font-bold text-red-800" id="dateMeter">❤️ 100%</span>
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<div class="bg-green-100 rounded-2xl p-6">
<h2 class="text-2xl font-semibold text-green-800 mb-4">Your Picnic Setup</h2>
<div class="grid grid-cols-3 gap-3">
<div class="food-item bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="coffee" class="text-amber-700 w-8 h-8"></i>
<span class="text-xs mt-1">Thermos</span>
</div>
<div class="food-item bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="pie-chart" class="text-red-500 w-8 h-8"></i>
<span class="text-xs mt-1">Pie</span>
</div>
<div class="food-item bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="box" class="text-yellow-600 w-8 h-8"></i>
<span class="text-xs mt-1">Basket</span>
</div>
<div class="food-item bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="glass" class="text-blue-400 w-8 h-8"></i>
<span class="text-xs mt-1">Glass</span>
</div>
<div class="food-item bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="wine" class="text-purple-600 w-8 h-8"></i>
<span class="text-xs mt-1">Bottle</span>
</div>
<div class="food-item bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="utensils" class="text-gray-700 w-8 h-8"></i>
<span class="text-xs mt-1">Utensils</span>
</div>
</div>
</div>
<div class="bg-amber-100 rounded-2xl p-6 relative">
<h2 class="text-2xl font-semibold text-amber-800 mb-4">Picnic Blanket</h2>
<div id="picnicBlanket" class="bg-white bg-opacity-70 border-2 border-dashed border-amber-400 rounded-xl h-64 flex items-center justify-center">
<p class="text-amber-600 text-center">Drag items here to set up your perfect date picnic!</p>
</div>
<div class="absolute bottom-4 right-4">
<button id="startDateBtn" class="bg-pink-500 hover:bg-pink-600 text-white px-6 py-2 rounded-full shadow-lg transform transition hover:scale-105">
<i data-feather="heart" class="inline mr-2"></i> Start Date
</button>
</div>
</div>
</div>
<div class="mt-8 bg-red-100 rounded-2xl p-6">
<h2 class="text-2xl font-semibold text-red-800 mb-4">Animal Intruders</h2>
<div class="flex flex-wrap gap-4">
<div class="animal bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="github" class="text-gray-800 w-8 h-8"></i>
<span class="text-xs mt-1">Squirrel</span>
</div>
<div class="animal bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="twitter" class="text-blue-400 w-8 h-8"></i>
<span class="text-xs mt-1">Bird</span>
</div>
<div class="animal bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="codesandbox" class="text-amber-700 w-8 h-8"></i>
<span class="text-xs mt-1">Raccoon</span>
</div>
<div class="animal bg-white p-3 rounded-lg shadow-md flex flex-col items-center justify-center ragdoll" draggable="true">
<i data-feather="cpu" class="text-gray-600 w-8 h-8"></i>
<span class="text-xs mt-1">Dog</span>
</div>
</div>
<p class="mt-4 text-red-700">Drag and throw them away from your picnic!</p>
</div>
</div>
</div>
<script>
// Initialize Vanta.js background
VANTA.GLOBE({
el: "#gameCanvas",
mouseControls: true,
touchControls: true,
gyroControls: false,
minHeight: 200.00,
minWidth: 200.00,
scale: 1.00,
scaleMobile: 1.00,
color: 0x3a5a40,
backgroundColor: 0xe9ecef
});
// Initialize feather icons
feather.replace();
// Game state
let gameTime = 180; // 3 minutes in seconds
let dateMeter = 100;
let gameActive = false;
let itemsPlaced = 0;
const totalItems = 6;
// Timer function
function updateTimer() {
if (!gameActive) return;
gameTime--;
const minutes = Math.floor(gameTime / 60);
const seconds = gameTime % 60;
document.getElementById('timer').textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
if (gameTime <= 0) {
endGame();
} else {
setTimeout(updateTimer, 1000);
}
}
// Date meter function
function updateDateMeter(change) {
dateMeter = Math.max(0, Math.min(100, dateMeter + change));
const hearts = Math.ceil(dateMeter / 20);
document.getElementById('dateMeter').textContent = '❤️'.repeat(hearts) + ` ${dateMeter}%`;
}
// Start game function
function startGame() {
gameActive = true;
gameTime = 180;
dateMeter = 100;
itemsPlaced = 0;
updateTimer();
document.getElementById('startDateBtn').textContent = "Date in Progress!";
document.getElementById('startDateBtn').classList.remove('bg-pink-500', 'hover:bg-pink-600');
document.getElementById('startDateBtn').classList.add('bg-purple-500', 'hover:bg-purple-600');
// Start animal intrusions
startAnimalIntrusions();
}
// End game function
function endGame() {
gameActive = false;
clearInterval(animalInterval);
let message;
if (dateMeter >= 80) {
message = "Perfect Date! ❤️";
} else if (dateMeter >= 50) {
message = "Nice Try! 😊";
} else {
message = "Better Luck Next Time! 😅";
}
alert(`Game Over!\n${message}\nFinal Date Meter: ${dateMeter}%`);
document.getElementById('startDateBtn').innerHTML = '<i data-feather="heart" class="inline mr-2"></i> Try Again';
document.getElementById('startDateBtn').classList.remove('bg-purple-500', 'hover:bg-purple-600');
document.getElementById('startDateBtn').classList.add('bg-pink-500', 'hover:bg-pink-600');
feather.replace();
}
// Animal intrusion function
let animalInterval;
function startAnimalIntrusions() {
animalInterval = setInterval(() => {
if (!gameActive) return;
// Random chance to decrease date meter
if (Math.random() < 0.3) {
updateDateMeter(-5);
}
// Add random animal to picnic
const animals = document.querySelectorAll('.animal');
const randomAnimal = animals[Math.floor(Math.random() * animals.length)].cloneNode(true);
const blanket = document.getElementById('picnicBlanket');
randomAnimal.style.position = 'absolute';
randomAnimal.style.left = `${Math.random() * 80 + 10}%`;
randomAnimal.style.top = `${Math.random() * 80 + 10}%`;
randomAnimal.classList.add('animate-bounce');
blanket.appendChild(randomAnimal);
feather.replace();
// Remove animal after some time
setTimeout(() => {
if (randomAnimal.parentNode) {
randomAnimal.remove();
updateDateMeter(2); // Small bonus for animal leaving
}
}, 3000);
}, 2000);
}
// Drag and drop functionality
document.addEventListener('DOMContentLoaded', () => {
const foodItems = document.querySelectorAll('.food-item');
const blanket = document.getElementById('picnicBlanket');
const startBtn = document.getElementById('startDateBtn');
// Setup drag for food items
foodItems.forEach(item => {
item.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', item.innerHTML);
e.dataTransfer.effectAllowed = 'copy';
});
});
// Setup drop for picnic blanket
blanket.addEventListener('dragover', (e) => {
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
blanket.classList.add('bg-amber-50');
});
blanket.addEventListener('dragleave', () => {
blanket.classList.remove('bg-amber-50');
});
blanket.addEventListener('drop', (e) => {
e.preventDefault();
blanket.classList.remove('bg-amber-50');
if (!gameActive && e.dataTransfer.getData('text/plain')) {
const data = e.dataTransfer.getData('text/plain');
const newItem = document.createElement('div');
newItem.className = 'food-item bg-white p-3 rounded-lg shadow-md absolute flex flex-col items-center justify-center';
newItem.innerHTML = data;
newItem.style.left = `${e.offsetX - 25}px`;
newItem.style.top = `${e.offsetY - 25}px`;
newItem.draggable = true;
// Make placed items draggable within blanket
newItem.addEventListener('dragstart', (ev) => {
ev.dataTransfer.setData('text/plain', newItem.innerHTML);
ev.dataTransfer.effectAllowed = 'move';
});
blanket.appendChild(newItem);
feather.replace();
// Count placed items
itemsPlaced++;
if (itemsPlaced >= totalItems) {
startBtn.disabled = false;
}
}
});
// Start date button
startBtn.addEventListener('click', () => {
if (!gameActive && itemsPlaced >= totalItems) {
startGame();
} else if (!gameActive) {
alert('Please set up your picnic with all items first!');
}
});
// Setup animal throwing
document.addEventListener('dragover', (e) => {
if (e.target.classList.contains('animal')) {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
}
});
document.addEventListener('drop', (e) => {
if (e.target.classList.contains('animal')) {
e.preventDefault();
const animal = e.target;
animal.style.transform = `translate(${Math.random() * 200 - 100}px, ${Math.random() * 200 - 100}px) rotate(${Math.random() * 360}deg)`;
setTimeout(() => {
animal.remove();
if (gameActive) {
updateDateMeter(5); // Bonus for throwing animal
}
}, 500);
}
});
});
</script>
</body>
</html>