(() => {
'use strict';
document.addEventListener("DOMContentLoaded", () => {
const START_POS = [38.891, 139.824];
const REVEAL_RADIUS = 40; // メートル
const GRID_SIZE = 0.0005; // 霧管理用グリッド
let map;
let playerMarker;
let fogLayer;
// 探索済みグリッド管理
const revealedCells = new Set();
const holes = [];
function initMap() {
map = L.map("locationmap").setView(START_POS, 16);
L.tileLayer("https://{s}.tile.osm.org/{z}/{x}/{y}.png", {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
playerMarker = L.marker(START_POS).addTo(map);
createFog();
map.on("click", (e) => {
updateLocation(e.latlng);
});
}
/** ===== 霧を1回だけ作成 ===== */
function createFog() {
const world = [
[-90, -180],
[-90, 180],
[90, 180],
[90, -180]
];
fogLayer = L.polygon([world], {
color: "#000",
fillColor: "#000",
fillOpacity: 0.6,
stroke: false
}).addTo(map);
}
/** ===== 位置更新 ===== */
function updateLocation(latlng) {
playerMarker.setLatLng(latlng);
revealFog(latlng);
}
/** ===== 霧解除(チカチカしない核心部分) ===== */
function revealFog(latlng) {
const key = gridKey(latlng);
// すでに解除済みなら何もしない
if (revealedCells.has(key)) return;
revealedCells.add(key);
const hole = createCircle(latlng, REVEAL_RADIUS);
holes.push(hole);
// 🔑 ポリゴンは作り直さず、穴だけ更新
fogLayer.setLatLngs([
fogLayer.getLatLngs()[0], // 外枠
...holes
]);
}
/** ===== グリッド判定 ===== */
function gridKey(latlng) {
const x = Math.floor(latlng.lat / GRID_SIZE);
const y = Math.floor(latlng.lng / GRID_SIZE);
return `${x}_${y}`;
}
/** ===== 円形穴生成 ===== */
function createCircle(center, radius) {
const points = [];
const steps = 24;
for (let i = 0; i < steps; i++) {
const angle = (i / steps) * Math.PI * 2;
const dx = (radius * Math.cos(angle)) / 111320;
const dy = (radius * Math.sin(angle)) /
(111320 * Math.cos(center.lat * Math.PI / 180));
points.push([
center.lat + dy,
center.lng + dx
]);
}
return points;
}
initMap();
});
})();