scottobear's picture
Add 3 files
2f49420 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GeoQuest Adventure</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 pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.pulse {
animation: pulse 2s infinite;
}
.weather-icon {
font-size: 3rem;
margin-bottom: 1rem;
}
.fade-in {
animation: fadeIn 1s;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.adventure-card {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
}
.progress-bar {
height: 10px;
border-radius: 5px;
transition: width 0.5s ease;
}
</style>
</head>
<body class="bg-gradient-to-br from-blue-900 to-purple-900 min-h-screen text-white font-sans">
<div class="container mx-auto px-4 py-8 max-w-md">
<header class="text-center mb-8 fade-in">
<h1 class="text-4xl font-bold mb-2">GeoQuest</h1>
<p class="text-lg opacity-80">A location-based adventure</p>
</header>
<div id="loading" class="text-center py-12 fade-in">
<div class="spinner mb-4">
<i class="fas fa-compass fa-spin text-4xl"></i>
</div>
<p class="mb-4">Loading your adventure...</p>
<p class="text-sm opacity-70">Please allow location access when prompted</p>
</div>
<div id="game-container" class="hidden">
<div class="flex justify-between items-center mb-6">
<div class="flex items-center">
<i class="fas fa-user mr-2"></i>
<span id="player-name" class="font-medium">Adventurer</span>
</div>
<div class="flex items-center">
<i class="fas fa-bolt mr-2"></i>
<span id="energy">100</span>%
</div>
</div>
<div class="progress-bar bg-yellow-400 mb-6 w-full" id="energy-bar"></div>
<div class="adventure-card p-6 mb-6 fade-in">
<div class="flex justify-between items-center mb-4">
<div>
<h2 id="location-name" class="text-xl font-bold">Current Location</h2>
<p id="location-coords" class="text-sm opacity-70">Loading coordinates...</p>
</div>
<div id="weather" class="text-center">
<i id="weather-icon" class="fas fa-sun weather-icon"></i>
<p id="weather-temp" class="text-lg">--°C</p>
</div>
</div>
<div id="time-display" class="flex justify-center items-center mb-6">
<i class="far fa-clock mr-2"></i>
<span id="current-time">Loading time...</span>
</div>
<div id="location-description" class="mb-6 text-center">
<p>Discovering your surroundings...</p>
</div>
<div id="quest-display" class="mb-6">
<h3 class="font-bold mb-2 text-center">Current Quest</h3>
<p id="quest-text" class="text-center italic">Finding your starting point...</p>
<div class="flex justify-between text-xs mt-2">
<span>Progress</span>
<span id="quest-progress">0%</span>
</div>
<div class="progress-bar bg-green-400 w-0 h-2 mt-1" id="quest-bar"></div>
</div>
</div>
<div id="action-buttons" class="grid grid-cols-2 gap-4 mb-6">
<button id="explore-btn" class="bg-blue-600 hover:bg-blue-700 rounded-lg py-3 px-4 flex items-center justify-center disabled:opacity-50" disabled>
<i class="fas fa-binoculars mr-2"></i> Explore
</button>
<button id="rest-btn" class="bg-purple-600 hover:bg-purple-700 rounded-lg py-3 px-4 flex items-center justify-center disabled:opacity-50" disabled>
<i class="fas fa-moon mr-2"></i> Rest
</button>
<button id="move-btn" class="bg-green-600 hover:bg-green-700 rounded-lg py-3 px-4 flex items-center justify-center disabled:opacity-50" disabled>
<i class="fas fa-walking mr-2"></i> Move
</button>
<button id="collect-btn" class="bg-yellow-600 hover:bg-yellow-700 rounded-lg py-3 px-4 flex items-center justify-center disabled:opacity-50" disabled>
<i class="fas fa-leaf mr-2"></i> Collect
</button>
</div>
<div id="event-log" class="bg-black bg-opacity-30 rounded-lg p-4 h-40 overflow-y-auto text-sm mb-6">
<p class="text-center opacity-70">Adventure log will appear here</p>
</div>
<div class="text-center">
<button id="new-game-btn" class="bg-red-600 hover:bg-red-700 rounded-lg py-2 px-6">
<i class="fas fa-redo mr-2"></i> New Game
</button>
</div>
</div>
<div id="start-screen" class="hidden text-center py-12 fade-in">
<h2 class="text-3xl font-bold mb-6">Begin Your Adventure</h2>
<div class="mb-6">
<label for="name-input" class="block mb-2">Your Adventurer Name:</label>
<input type="text" id="name-input" class="bg-gray-800 text-white rounded-lg px-4 py-2 w-full max-w-xs mx-auto" placeholder="Enter your name">
</div>
<button id="start-game-btn" class="bg-green-600 hover:bg-green-700 rounded-lg py-3 px-8 text-lg">
<i class="fas fa-play mr-2"></i> Start Journey
</button>
</div>
</div>
<script>
// Game state
const gameState = {
playerName: "Adventurer",
energy: 100,
location: null,
weather: null,
time: null,
quests: [
{ name: "Find the ancient artifact", progress: 0, target: 5 },
{ name: "Discover hidden landmarks", progress: 0, target: 3 },
{ name: "Collect rare items", progress: 0, target: 10 }
],
currentQuestIndex: 0,
inventory: [],
discoveredLocations: [],
gameStarted: false
};
// DOM elements
const loadingElement = document.getElementById('loading');
const gameContainer = document.getElementById('game-container');
const startScreen = document.getElementById('start-screen');
const playerNameElement = document.getElementById('player-name');
const energyElement = document.getElementById('energy');
const energyBar = document.getElementById('energy-bar');
const locationName = document.getElementById('location-name');
const locationCoords = document.getElementById('location-coords');
const weatherIcon = document.getElementById('weather-icon');
const weatherTemp = document.getElementById('weather-temp');
const currentTime = document.getElementById('current-time');
const locationDescription = document.getElementById('location-description');
const questText = document.getElementById('quest-text');
const questProgress = document.getElementById('quest-progress');
const questBar = document.getElementById('quest-bar');
const eventLog = document.getElementById('event-log');
const exploreBtn = document.getElementById('explore-btn');
const restBtn = document.getElementById('rest-btn');
const moveBtn = document.getElementById('move-btn');
const collectBtn = document.getElementById('collect-btn');
const newGameBtn = document.getElementById('new-game-btn');
const startGameBtn = document.getElementById('start-game-btn');
const nameInput = document.getElementById('name-input');
// Location types and descriptions
const locationTypes = {
urban: ["city center", "downtown district", "urban plaza", "shopping area"],
park: ["city park", "green space", "botanical garden", "nature reserve"],
water: ["lakefront", "riverbank", "harbor area", "beach"],
residential: ["neighborhood", "suburban area", "housing district"],
commercial: ["business district", "office park", "shopping center"]
};
const locationFeatures = {
day: ["sunny", "bright", "clear", "peaceful"],
night: ["moonlit", "quiet", "starlit", "serene"],
rain: ["wet", "damp", "misty", "rain-soaked"],
sunny: ["sun-drenched", "warm", "sunny", "bright"],
cloudy: ["overcast", "gray", "cloud-covered", "cool"],
cold: ["chilly", "crisp", "cold", "frosty"]
};
// Initialize game
function initGame() {
// Show start screen
loadingElement.classList.add('hidden');
startScreen.classList.remove('hidden');
// Set up event listeners
startGameBtn.addEventListener('click', startGame);
newGameBtn.addEventListener('click', resetGame);
exploreBtn.addEventListener('click', exploreLocation);
restBtn.addEventListener('click', rest);
moveBtn.addEventListener('click', moveLocation);
collectBtn.addEventListener('click', collectItem);
// Enable buttons when game starts
exploreBtn.disabled = false;
restBtn.disabled = false;
moveBtn.disabled = false;
collectBtn.disabled = false;
}
// Start game
function startGame() {
const name = nameInput.value.trim() || "Adventurer";
gameState.playerName = name;
playerNameElement.textContent = name;
startScreen.classList.add('hidden');
gameContainer.classList.remove('hidden');
gameState.gameStarted = true;
// Start location tracking
getLocation();
updateTime();
// Start periodic updates
setInterval(updateTime, 60000); // Update time every minute
setInterval(updateEnergy, 300000); // Update energy every 5 minutes
// Initial log entry
addToLog(`Welcome, ${name}! Your adventure begins now.`);
}
// Reset game
function resetGame() {
gameState.energy = 100;
gameState.location = null;
gameState.weather = null;
gameState.time = null;
gameState.currentQuestIndex = 0;
gameState.inventory = [];
gameState.discoveredLocations = [];
gameContainer.classList.add('hidden');
startScreen.classList.remove('hidden');
eventLog.innerHTML = '<p class="text-center opacity-70">Adventure log will appear here</p>';
// Reset UI
energyElement.textContent = '100';
energyBar.style.width = '100%';
questText.textContent = 'Finding your starting point...';
questProgress.textContent = '0%';
questBar.style.width = '0%';
}
// Get location
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
position => {
const lat = position.coords.latitude;
const lon = position.coords.longitude;
gameState.location = { lat, lon };
// Update location display
locationCoords.textContent = `${lat.toFixed(4)}, ${lon.toFixed(4)}`;
// Get location name (simplified for this demo)
getLocationName(lat, lon);
// Get weather
getWeather(lat, lon);
// Generate location description
generateLocationDescription();
// Update quest display
updateQuestDisplay();
},
error => {
console.error("Error getting location:", error);
addToLog("Could not determine your location. Using default location.");
// Fallback to default location (New York)
gameState.location = { lat: 40.7128, lon: -74.0060 };
locationCoords.textContent = "40.7128, -74.0060";
locationName.textContent = "New York City";
// Get weather for default location
getWeather(40.7128, -74.0060);
// Generate location description
generateLocationDescription();
}
);
} else {
addToLog("Geolocation is not supported by your browser. Using default location.");
// Fallback to default location (New York)
gameState.location = { lat: 40.7128, lon: -74.0060 };
locationCoords.textContent = "40.7128, -74.0060";
locationName.textContent = "New York City";
// Get weather for default location
getWeather(40.7128, -74.0060);
// Generate location description
generateLocationDescription();
}
}
// Get location name (simplified for demo)
function getLocationName(lat, lon) {
// In a real app, you would use a geocoding API here
// For demo purposes, we'll just show coordinates
locationName.textContent = `Area at ${lat.toFixed(2)}, ${lon.toFixed(2)}`;
}
// Get weather (simplified for demo)
function getWeather(lat, lon) {
// In a real app, you would use a weather API here
// For demo, we'll simulate weather based on time and location
const now = new Date();
const hour = now.getHours();
const month = now.getMonth();
// Simulate weather patterns
let weatherType, temp;
// Summer months (June-August)
if (month >= 5 && month <= 7) {
if (hour >= 6 && hour < 18) {
// Daytime in summer
weatherType = Math.random() > 0.7 ? "rain" : "sunny";
temp = Math.floor(Math.random() * 15) + 20; // 20-35°C
} else {
// Nighttime in summer
weatherType = Math.random() > 0.8 ? "rain" : "clear";
temp = Math.floor(Math.random() * 10) + 15; // 15-25°C
}
}
// Winter months (December-February)
else if (month === 11 || month <= 1) {
if (hour >= 6 && hour < 18) {
// Daytime in winter
weatherType = Math.random() > 0.6 ? "cloudy" : "sunny";
temp = Math.floor(Math.random() * 10) + 0; // 0-10°C
} else {
// Nighttime in winter
weatherType = Math.random() > 0.7 ? "snow" : "clear";
temp = Math.floor(Math.random() * 5) - 5; // -5 to 0°C
}
}
// Spring/Fall
else {
if (hour >= 6 && hour < 18) {
// Daytime
weatherType = Math.random() > 0.5 ? "cloudy" : "sunny";
temp = Math.floor(Math.random() * 15) + 10; // 10-25°C
} else {
// Nighttime
weatherType = Math.random() > 0.6 ? "cloudy" : "clear";
temp = Math.floor(Math.random() * 10) + 5; // 5-15°C
}
}
gameState.weather = {
type: weatherType,
temperature: temp
};
// Update weather display
updateWeatherDisplay();
}
// Update weather display
function updateWeatherDisplay() {
if (!gameState.weather) return;
const weather = gameState.weather;
let icon, description;
switch (weather.type) {
case "sunny":
icon = "fa-sun";
description = "Sunny";
break;
case "rain":
icon = "fa-cloud-rain";
description = "Rainy";
break;
case "cloudy":
icon = "fa-cloud";
description = "Cloudy";
break;
case "clear":
icon = "fa-moon";
description = "Clear";
break;
case "snow":
icon = "fa-snowflake";
description = "Snowy";
break;
default:
icon = "fa-cloud-sun";
description = "Fair";
}
weatherIcon.className = `fas ${icon} weather-icon`;
weatherTemp.textContent = `${weather.temperature}°C`;
}
// Update time
function updateTime() {
const now = new Date();
gameState.time = now;
const hours = now.getHours();
const minutes = now.getMinutes().toString().padStart(2, '0');
const ampm = hours >= 12 ? 'PM' : 'AM';
const displayHours = hours % 12 || 12;
currentTime.textContent = `${displayHours}:${minutes} ${ampm}`;
// Update time-based elements
if (gameState.location) {
generateLocationDescription();
}
}
// Generate location description
function generateLocationDescription() {
if (!gameState.location || !gameState.weather || !gameState.time) return;
const hour = gameState.time.getHours();
const weather = gameState.weather.type;
// Determine time of day
let timeOfDay;
if (hour >= 5 && hour < 12) timeOfDay = "morning";
else if (hour >= 12 && hour < 17) timeOfDay = "afternoon";
else if (hour >= 17 && hour < 21) timeOfDay = "evening";
else timeOfDay = "night";
// Determine location type (simplified)
const locationTypesArray = Object.keys(locationTypes);
const randomType = locationTypesArray[Math.floor(Math.random() * locationTypesArray.length)];
const typeFeatures = locationTypes[randomType];
const randomFeature = typeFeatures[Math.floor(Math.random() * typeFeatures.length)];
// Get weather features
const weatherFeatures = locationFeatures[weather] || locationFeatures.sunny;
const randomWeatherFeature = weatherFeatures[Math.floor(Math.random() * weatherFeatures.length)];
// Get time features
const timeFeatures = locationFeatures[timeOfDay] || locationFeatures.day;
const randomTimeFeature = timeFeatures[Math.floor(Math.random() * timeFeatures.length)];
// Construct description
const description = `You're in a ${randomWeatherFeature}, ${randomTimeFeature} ${randomFeature}.`;
locationDescription.innerHTML = `<p class="text-center">${description}</p>`;
// Add to discovered locations if not already there
const locationKey = `${gameState.location.lat.toFixed(2)},${gameState.location.lon.toFixed(2)}`;
if (!gameState.discoveredLocations.includes(locationKey)) {
gameState.discoveredLocations.push(locationKey);
addToLog(`Discovered new location: ${randomFeature}`);
}
}
// Update quest display
function updateQuestDisplay() {
if (gameState.quests.length === 0) return;
const currentQuest = gameState.quests[gameState.currentQuestIndex];
questText.textContent = currentQuest.name;
const progressPercent = (currentQuest.progress / currentQuest.target) * 100;
questProgress.textContent = `${Math.min(100, Math.round(progressPercent))}%`;
questBar.style.width = `${Math.min(100, progressPercent)}%`;
}
// Update energy
function updateEnergy() {
if (!gameState.gameStarted) return;
// Energy decreases over time
gameState.energy = Math.max(0, gameState.energy - 5);
energyElement.textContent = gameState.energy;
energyBar.style.width = `${gameState.energy}%`;
// Change color based on energy level
if (gameState.energy < 20) {
energyBar.className = "progress-bar bg-red-500 mb-6";
addToLog("Warning: Your energy is critically low!");
} else if (gameState.energy < 50) {
energyBar.className = "progress-bar bg-yellow-500 mb-6";
} else {
energyBar.className = "progress-bar bg-green-500 mb-6";
}
// Disable actions if energy is too low
exploreBtn.disabled = gameState.energy < 10;
moveBtn.disabled = gameState.energy < 15;
collectBtn.disabled = gameState.energy < 5;
}
// Explore location
function exploreLocation() {
if (gameState.energy < 10) {
addToLog("Not enough energy to explore!");
return;
}
gameState.energy = Math.max(0, gameState.energy - 10);
energyElement.textContent = gameState.energy;
energyBar.style.width = `${gameState.energy}%`;
// Random chance to find something
const foundSomething = Math.random() > 0.4;
if (foundSomething) {
const discoveries = [
"ancient artifact fragment",
"hidden path",
"rare flower",
"mysterious inscription",
"abandoned item"
];
const discovery = discoveries[Math.floor(Math.random() * discoveries.length)];
// Progress on collection quest
if (discovery === "rare flower" || discovery === "ancient artifact fragment") {
progressQuest(2);
}
addToLog(`You found ${discovery}!`);
// Small chance to increase energy from discovery
if (Math.random() > 0.8) {
gameState.energy = Math.min(100, gameState.energy + 5);
energyElement.textContent = gameState.energy;
energyBar.style.width = `${gameState.energy}%`;
addToLog("The discovery invigorates you! +5 energy");
}
} else {
addToLog("You explore the area but don't find anything noteworthy.");
}
// Progress on discovery quest
progressQuest(1);
updateEnergy();
}
// Rest
function rest() {
const hour = gameState.time.getHours();
// Resting at night is more effective
const energyGain = (hour >= 21 || hour < 6) ? 30 : 15;
gameState.energy = Math.min(100, gameState.energy + energyGain);
energyElement.textContent = gameState.energy;
energyBar.style.width = `${gameState.energy}%`;
addToLog(`You rest and recover ${energyGain} energy.`);
// Small chance to dream about a new location
if (Math.random() > 0.7) {
addToLog("While resting, you have a vivid dream about a distant location...");
}
}
// Move location
function moveLocation() {
if (gameState.energy < 15) {
addToLog("Not enough energy to move!");
return;
}
gameState.energy = Math.max(0, gameState.energy - 15);
energyElement.textContent = gameState.energy;
energyBar.style.width = `${gameState.energy}%`;
addToLog("You set out to explore a new area...");
// Simulate moving by getting a new location
setTimeout(() => {
// In a real app, this would track actual movement
// For demo, we'll just slightly adjust coordinates
if (gameState.location) {
const latChange = (Math.random() - 0.5) * 0.02;
const lonChange = (Math.random() - 0.5) * 0.02;
gameState.location.lat += latChange;
gameState.location.lon += lonChange;
locationCoords.textContent = `${gameState.location.lat.toFixed(4)}, ${gameState.location.lon.toFixed(4)}`;
getLocationName(gameState.location.lat, gameState.location.lon);
getWeather(gameState.location.lat, gameState.location.lon);
generateLocationDescription();
addToLog("You've arrived at a new location!");
// Progress on movement quest
progressQuest(0);
}
}, 1500);
updateEnergy();
}
// Collect item
function collectItem() {
if (gameState.energy < 5) {
addToLog("Not enough energy to collect items!");
return;
}
gameState.energy = Math.max(0, gameState.energy - 5);
energyElement.textContent = gameState.energy;
energyBar.style.width = `${gameState.energy}%`;
// Items available depend on location and weather
let items = [];
if (gameState.weather.type === "sunny") {
items = ["sunstone", "wildflower", "feather"];
} else if (gameState.weather.type === "rain") {
items = ["rainwater vial", "mushroom", "frog"];
} else if (gameState.weather.type === "snow") {
items = ["icicle", "frost crystal", "winter berry"];
} else {
items = ["pebble", "twig", "strange seed"];
}
const collectedItem = items[Math.floor(Math.random() * items.length)];
gameState.inventory.push(collectedItem);
addToLog(`You collected a ${collectedItem}!`);
// Progress on collection quest
progressQuest(2);
updateEnergy();
}
// Progress quest
function progressQuest(questIndex) {
if (questIndex >= gameState.quests.length) return;
const quest = gameState.quests[questIndex];
quest.progress = Math.min(quest.target, quest.progress + 1);
if (quest.progress >= quest.target) {
addToLog(`Quest completed: ${quest.name}!`);
// Reward for completing quest
gameState.energy = Math.min(100, gameState.energy + 20);
energyElement.textContent = gameState.energy;
energyBar.style.width = `${gameState.energy}%`;
addToLog("Quest reward: +20 energy");
// Move to next quest
gameState.currentQuestIndex = (gameState.currentQuestIndex + 1) % gameState.quests.length;
// Reset current quest progress
quest.progress = 0;
}
updateQuestDisplay();
}
// Add to event log
function addToLog(message) {
const now = new Date();
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const logEntry = document.createElement('p');
logEntry.innerHTML = `<span class="text-yellow-300">[${timeStr}]</span> ${message}`;
// Remove placeholder if it exists
if (eventLog.firstChild && eventLog.firstChild.classList.contains('text-center')) {
eventLog.removeChild(eventLog.firstChild);
}
eventLog.insertBefore(logEntry, eventLog.firstChild);
// Limit log entries
if (eventLog.children.length > 10) {
eventLog.removeChild(eventLog.lastChild);
}
}
// Initialize the game when page loads
window.addEventListener('load', () => {
// Simulate loading time
setTimeout(initGame, 2000);
});
</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=scottobear/test-builds-for-scottobear" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>