Browse Source

Add combat camera animation with drone-style zoom and pitch

When initiating combat, the camera now flies to the monster position
with zoom 19 and pitch 60 for a dramatic drone-style effect. After
combat ends, the camera smoothly returns to its pre-combat position.

🤖 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
bce8bbd363
  1. 43
      index.html

43
index.html

@ -15790,6 +15790,32 @@
if (monsterEntourage.length === 0) return; if (monsterEntourage.length === 0) return;
if (playerStats.isDead) return; // Can't fight when dead if (playerStats.isDead) return; // Can't fight when dead
// Store current camera state for later restoration
const preCombatCamera = {
center: map.getCenter(),
zoom: map.getZoom(),
pitch: map.getPitch(),
bearing: map.getBearing()
};
// Animate camera to zoom in on monster (drone-style)
if (clickedMonster.position) {
const monsterPos = [clickedMonster.position.lng, clickedMonster.position.lat];
// Fly to monster with dramatic zoom and pitch
map.flyTo({
center: monsterPos,
zoom: 19, // Close zoom
pitch: 60, // Tilt camera down like a drone
bearing: map.getBearing(), // Keep current rotation
duration: 1200, // 1.2 second animation
easing: (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2 // Ease in-out
});
// Wait for animation to complete before showing combat UI
await new Promise(resolve => setTimeout(resolve, 1200));
}
// Mark sync engine as in combat (suppresses non-critical save errors) // Mark sync engine as in combat (suppresses non-critical save errors)
statsSyncState.inCombat = true; statsSyncState.inCombat = true;
@ -15847,7 +15873,8 @@
targetingMode: false, // True when selecting targets for multi-hit skill targetingMode: false, // True when selecting targets for multi-hit skill
pendingSkill: null, // The skill waiting to be executed pendingSkill: null, // The skill waiting to be executed
pendingTargets: [], // Array of target indices for each hit pendingTargets: [], // Array of target indices for each hit
totalHitsToSelect: 0 // Total number of hits to select targets for
totalHitsToSelect: 0, // Total number of hits to select targets for
preCombatCamera: preCombatCamera // Store camera state for restoration after combat
}; };
showCombatUI(); showCombatUI();
@ -17027,6 +17054,20 @@
function closeCombatUI() { function closeCombatUI() {
console.log('[DEBUG] closeCombatUI called'); console.log('[DEBUG] closeCombatUI called');
document.getElementById('combatOverlay').style.display = 'none'; document.getElementById('combatOverlay').style.display = 'none';
// Restore camera to pre-combat position with smooth animation
if (combatState && combatState.preCombatCamera) {
const cam = combatState.preCombatCamera;
map.flyTo({
center: cam.center,
zoom: cam.zoom,
pitch: cam.pitch,
bearing: cam.bearing,
duration: 800, // Slightly faster return
easing: (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2
});
}
combatState = null; combatState = null;
monsterActiveAnimations = {}; // Clear animation tracking monsterActiveAnimations = {}; // Clear animation tracking

Loading…
Cancel
Save