Browse Source

Add secondary fog clearing zone for player exploration

- Add 50m explore radius that follows player when outside homebase
- Secondary reveal circle only appears when player is outside 800m homebase radius
- Update isInRevealedArea() to check both homebase and player position
- Update fog of war on GPS position changes and after combat
- Geocaches within player's explore radius now become visible

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
master
HikeMap User 4 weeks ago
parent
commit
48422c1617
  1. 79
      index.html

79
index.html

@ -4185,7 +4185,8 @@
// Fog of War state variables (must be declared before use) // Fog of War state variables (must be declared before use)
let fogCanvas = null; let fogCanvas = null;
let fogCtx = null; let fogCtx = null;
let playerRevealRadius = 800;
let playerRevealRadius = 800; // Homebase reveal radius (meters)
let playerExploreRadius = 50; // Player's personal reveal radius when exploring (meters)
// Initialize fog of war canvas (directly in map container for simple viewport alignment) // Initialize fog of war canvas (directly in map container for simple viewport alignment)
function initFogOfWar() { function initFogOfWar() {
@ -4260,11 +4261,8 @@
fogCtx.fillStyle = 'rgba(0, 0, 0, 0.6)'; fogCtx.fillStyle = 'rgba(0, 0, 0, 0.6)';
fogCtx.fillRect(0, 0, width, height); fogCtx.fillRect(0, 0, width, height);
// If no homebase set, full fog
if (!playerStats || playerStats.homeBaseLat == null || playerStats.homeBaseLng == null) {
return;
}
// Homebase reveal (only if homebase exists)
if (playerStats && playerStats.homeBaseLat != null && playerStats.homeBaseLng != null) {
// Calculate reveal circle center using container coordinates (viewport-relative) // Calculate reveal circle center using container coordinates (viewport-relative)
const homeLatLng = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng); const homeLatLng = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng);
const centerPoint = map.latLngToContainerPoint(homeLatLng); const centerPoint = map.latLngToContainerPoint(homeLatLng);
@ -4294,18 +4292,65 @@
fogCtx.restore(); fogCtx.restore();
} }
// Check if a location is within the revealed area
// Secondary reveal: Player's explore radius when outside homebase
if (userLocation) {
const playerLatLng = L.latLng(userLocation.lat, userLocation.lng);
// Check if player is outside homebase radius (or no homebase)
let isOutsideHomebase = true;
if (playerStats && playerStats.homeBaseLat != null && playerStats.homeBaseLng != null) {
const homeLatLng = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng);
const distToHome = playerLatLng.distanceTo(homeLatLng);
isOutsideHomebase = distToHome > playerRevealRadius;
}
if (isOutsideHomebase) {
const playerPoint = map.latLngToContainerPoint(playerLatLng);
const playerEdge = destinationPoint(playerLatLng, playerExploreRadius, 90);
const playerEdgePoint = map.latLngToContainerPoint(playerEdge);
const playerRadiusPixels = Math.abs(playerEdgePoint.x - playerPoint.x);
fogCtx.save();
fogCtx.globalCompositeOperation = 'destination-out';
const playerGradient = fogCtx.createRadialGradient(
playerPoint.x, playerPoint.y, playerRadiusPixels * 0.85,
playerPoint.x, playerPoint.y, playerRadiusPixels
);
playerGradient.addColorStop(0, 'rgba(0, 0, 0, 1)');
playerGradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
fogCtx.beginPath();
fogCtx.arc(playerPoint.x, playerPoint.y, playerRadiusPixels, 0, Math.PI * 2);
fogCtx.fillStyle = playerGradient;
fogCtx.fill();
fogCtx.restore();
}
}
}
// Check if a location is within the revealed area (homebase or player explore radius)
function isInRevealedArea(lat, lng) { function isInRevealedArea(lat, lng) {
// If no homebase, nothing is revealed
if (!playerStats || playerStats.homeBaseLat == null || playerStats.homeBaseLng == null) {
return false;
const checkPoint = L.latLng(lat, lng);
// Check homebase radius
if (playerStats && playerStats.homeBaseLat != null && playerStats.homeBaseLng != null) {
const homeLatLng = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng);
if (homeLatLng.distanceTo(checkPoint) <= playerRevealRadius) {
return true;
}
} }
// Calculate distance from homebase
const distance = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng)
.distanceTo(L.latLng(lat, lng));
// Check player's explore radius
if (userLocation) {
const playerLatLng = L.latLng(userLocation.lat, userLocation.lng);
if (playerLatLng.distanceTo(checkPoint) <= playerExploreRadius) {
return true;
}
}
return distance <= playerRevealRadius;
return false;
} }
// Hook fog updates to map events (fog will be initialized lazily) // Hook fog updates to map events (fog will be initialized lazily)
@ -5586,9 +5631,10 @@
// Check for monster clear at home base // Check for monster clear at home base
checkHomeBaseMonsterClear(); checkHomeBaseMonsterClear();
// Update geocache visibility based on new location
// Update geocache visibility and fog of war based on new location
if (navMode) { if (navMode) {
updateGeocacheVisibility(); updateGeocacheVisibility();
updateFogOfWar();
} }
// Update or create marker // Update or create marker
@ -15680,6 +15726,9 @@
statsSyncState.inCombat = false; statsSyncState.inCombat = false;
flushStatsSync(); flushStatsSync();
// Update fog of war to reflect current position after combat
updateFogOfWar();
// If victory music isn't playing, switch to appropriate ambient music // If victory music isn't playing, switch to appropriate ambient music
if (gameMusic.currentTrack !== 'victory' || gameMusic.victory.paused) { if (gameMusic.currentTrack !== 'victory' || gameMusic.victory.paused) {
const distToHome = getDistanceToHome(); const distToHome = getDistanceToHome();

Loading…
Cancel
Save