diff --git a/index.html b/index.html
index 1af575e..ea90997 100644
--- a/index.html
+++ b/index.html
@@ -4480,8 +4480,8 @@
zoom: 13,
maxZoom: 22,
bearing: 0,
- pitch: 0, // Disable pitch to keep fog of war circles correct
- maxPitch: 0, // Prevent user from tilting map (fog doesn't work with perspective)
+ pitch: 45, // 3D building perspective
+ maxPitch: 60,
doubleClickZoom: false
});
@@ -5125,35 +5125,42 @@
fogCtx.fillStyle = 'rgba(0, 0, 0, 0.6)';
fogCtx.fillRect(0, 0, width, height);
+ // Helper function to draw a projected circle (handles rotation AND pitch)
+ function drawProjectedCircle(ctx, centerLngLat, radiusMeters, numPoints = 48) {
+ const points = [];
+ for (let i = 0; i < numPoints; i++) {
+ const angle = (i / numPoints) * 360;
+ const edgeLngLat = destinationPoint(centerLngLat, radiusMeters, angle);
+ const edgePoint = map.project(edgeLngLat);
+ points.push(edgePoint);
+ }
+
+ // Draw the projected shape
+ ctx.beginPath();
+ points.forEach((pt, i) => {
+ if (i === 0) ctx.moveTo(pt.x, pt.y);
+ else ctx.lineTo(pt.x, pt.y);
+ });
+ ctx.closePath();
+ }
+
// Homebase reveal (only if homebase exists)
if (playerStats && playerStats.homeBaseLat != null && playerStats.homeBaseLng != null) {
- // Calculate reveal circle center using container coordinates (viewport-relative)
- // MapLibre uses [lng, lat] order
const homeLngLat = [playerStats.homeBaseLng, playerStats.homeBaseLat];
- const centerPoint = map.project(homeLngLat);
-
- // Calculate radius in pixels using map projection (with multiplier)
- // Use actual distance between projected points to handle rotation correctly
const effectiveHomebaseRadius = playerRevealRadius * homebaseRadiusMultiplier;
- const edgeLngLat = destinationPoint(homeLngLat, effectiveHomebaseRadius, 90);
- const edgePoint = map.project(edgeLngLat);
- const radiusPixels = Math.hypot(edgePoint.x - centerPoint.x, edgePoint.y - centerPoint.y);
// Cut out revealed area using composite operation
fogCtx.save();
fogCtx.globalCompositeOperation = 'destination-out';
- // Create gradient for soft edge
- const gradient = fogCtx.createRadialGradient(
- centerPoint.x, centerPoint.y, radiusPixels * 0.85,
- centerPoint.x, centerPoint.y, radiusPixels
- );
- gradient.addColorStop(0, 'rgba(0, 0, 0, 1)');
- gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
+ // Draw outer edge with fade (slightly larger, semi-transparent)
+ fogCtx.fillStyle = 'rgba(0, 0, 0, 0.5)';
+ drawProjectedCircle(fogCtx, homeLngLat, effectiveHomebaseRadius * 1.05);
+ fogCtx.fill();
- fogCtx.beginPath();
- fogCtx.arc(centerPoint.x, centerPoint.y, radiusPixels, 0, Math.PI * 2);
- fogCtx.fillStyle = gradient;
+ // Draw main revealed area (solid cutout)
+ fogCtx.fillStyle = 'rgba(0, 0, 0, 1)';
+ drawProjectedCircle(fogCtx, homeLngLat, effectiveHomebaseRadius * 0.95);
fogCtx.fill();
fogCtx.restore();
@@ -5175,26 +5182,19 @@
}
if (isOutsideHomebase) {
- const playerPoint = map.project(playerLngLat);
const effectiveExploreRadius = playerExploreRadius * exploreRadiusMultiplier;
- const playerEdge = destinationPoint(playerLngLat, effectiveExploreRadius, 90);
- const playerEdgePoint = map.project(playerEdge);
- // Use actual distance to handle rotation correctly
- const playerRadiusPixels = Math.hypot(playerEdgePoint.x - playerPoint.x, playerEdgePoint.y - playerPoint.y);
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)');
+ // Draw outer edge with fade (slightly larger, semi-transparent)
+ fogCtx.fillStyle = 'rgba(0, 0, 0, 0.5)';
+ drawProjectedCircle(fogCtx, playerLngLat, effectiveExploreRadius * 1.1);
+ fogCtx.fill();
- fogCtx.beginPath();
- fogCtx.arc(playerPoint.x, playerPoint.y, playerRadiusPixels, 0, Math.PI * 2);
- fogCtx.fillStyle = playerGradient;
+ // Draw main revealed area (solid cutout)
+ fogCtx.fillStyle = 'rgba(0, 0, 0, 1)';
+ drawProjectedCircle(fogCtx, playerLngLat, effectiveExploreRadius * 0.85);
fogCtx.fill();
fogCtx.restore();