Files
novafarma/src/systems/CameraSystem.js
2025-12-12 13:40:51 +01:00

321 lines
8.7 KiB
JavaScript

class CameraSystem {
constructor(scene) {
this.scene = scene;
this.camera = scene.cameras.main;
// Camera modes
this.mode = 'follow'; // 'follow', 'free', 'cinematic', 'screenshot'
// Free camera controls
this.freeCamSpeed = 5;
this.freeCamZoom = 1.0;
// Cinematic mode
this.cinematicPath = [];
this.cinematicIndex = 0;
this.cinematicPlaying = false;
// Screenshot mode
this.screenshotMode = false;
this.uiHidden = false;
// Saved camera positions
this.savedPositions = [];
this.setupControls();
console.log('📷 CameraSystem: Initialized');
}
setupControls() {
// F6 - Free Camera Mode
this.scene.input.keyboard.on('keydown-F6', () => {
this.toggleFreeCamera();
});
// F7 - Screenshot Mode (hide UI)
this.scene.input.keyboard.on('keydown-F7', () => {
this.toggleScreenshotMode();
});
// F8 - Save Camera Position
this.scene.input.keyboard.on('keydown-F8', () => {
this.saveCameraPosition();
});
// F9 - Cinematic Mode
this.scene.input.keyboard.on('keydown-F10', () => {
this.toggleCinematicMode();
});
// Arrow keys for free camera
this.cursors = this.scene.input.keyboard.createCursorKeys();
// Page Up/Down for zoom
this.scene.input.keyboard.on('keydown-PAGEUP', () => {
this.adjustZoom(0.1);
});
this.scene.input.keyboard.on('keydown-PAGEDOWN', () => {
this.adjustZoom(-0.1);
});
}
// FREE CAMERA MODE
toggleFreeCamera() {
if (this.mode === 'free') {
this.mode = 'follow';
this.camera.startFollow(this.scene.player.sprite);
console.log('📷 Camera: Follow mode');
} else {
this.mode = 'free';
this.camera.stopFollow();
console.log('📷 Camera: Free mode (Arrow keys to move, PgUp/PgDn to zoom)');
}
}
updateFreeCamera(delta) {
if (this.mode !== 'free') return;
const speed = this.freeCamSpeed * (delta / 16);
if (this.cursors.left.isDown) {
this.camera.scrollX -= speed;
}
if (this.cursors.right.isDown) {
this.camera.scrollX += speed;
}
if (this.cursors.up.isDown) {
this.camera.scrollY -= speed;
}
if (this.cursors.down.isDown) {
this.camera.scrollY += speed;
}
}
adjustZoom(delta) {
this.freeCamZoom = Phaser.Math.Clamp(this.freeCamZoom + delta, 0.3, 3.0);
this.camera.setZoom(this.freeCamZoom);
console.log(`📷 Zoom: ${this.freeCamZoom.toFixed(2)}x`);
}
// SCREENSHOT MODE
toggleScreenshotMode() {
this.screenshotMode = !this.screenshotMode;
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
if (this.screenshotMode) {
// Hide all UI
uiScene.children.list.forEach(child => {
if (child.setVisible) {
child.wasVisible = child.visible;
child.setVisible(false);
}
});
this.uiHidden = true;
console.log('📷 Screenshot mode: UI hidden (F7 to restore)');
} else {
// Restore UI
uiScene.children.list.forEach(child => {
if (child.setVisible && child.wasVisible !== undefined) {
child.setVisible(child.wasVisible);
}
});
this.uiHidden = false;
console.log('📷 Screenshot mode: UI restored');
}
}
// SAVE CAMERA POSITION
saveCameraPosition() {
const pos = {
x: this.camera.scrollX,
y: this.camera.scrollY,
zoom: this.camera.zoom
};
this.savedPositions.push(pos);
console.log(`📷 Camera position saved (${this.savedPositions.length}): x=${pos.x.toFixed(0)}, y=${pos.y.toFixed(0)}, zoom=${pos.zoom.toFixed(2)}`);
}
loadCameraPosition(index) {
if (index < 0 || index >= this.savedPositions.length) return;
const pos = this.savedPositions[index];
this.scene.tweens.add({
targets: this.camera,
scrollX: pos.x,
scrollY: pos.y,
zoom: pos.zoom,
duration: 1000,
ease: 'Sine.easeInOut'
});
console.log(`📷 Camera position loaded (${index + 1})`);
}
// CINEMATIC MODE
toggleCinematicMode() {
if (this.cinematicPlaying) {
this.stopCinematic();
} else {
this.startCinematic();
}
}
startCinematic() {
if (this.savedPositions.length < 2) {
console.log('📷 Need at least 2 saved positions for cinematic!');
return;
}
this.cinematicPlaying = true;
this.cinematicIndex = 0;
this.mode = 'cinematic';
this.playCinematicStep();
console.log('📷 Cinematic mode: Playing...');
}
playCinematicStep() {
if (!this.cinematicPlaying) return;
if (this.cinematicIndex >= this.savedPositions.length) {
this.stopCinematic();
return;
}
const pos = this.savedPositions[this.cinematicIndex];
this.scene.tweens.add({
targets: this.camera,
scrollX: pos.x,
scrollY: pos.y,
zoom: pos.zoom,
duration: 3000,
ease: 'Sine.easeInOut',
onComplete: () => {
this.cinematicIndex++;
this.scene.time.delayedCall(500, () => {
this.playCinematicStep();
});
}
});
}
stopCinematic() {
this.cinematicPlaying = false;
this.mode = 'follow';
this.camera.startFollow(this.scene.player.sprite);
console.log('📷 Cinematic mode: Stopped');
}
// PRESET CAMERA ANGLES
setPresetAngle(preset) {
const presets = {
'overview': { zoom: 0.5, y: -200 },
'closeup': { zoom: 1.5, y: 0 },
'wide': { zoom: 0.3, y: -300 },
'action': { zoom: 1.2, y: -50 }
};
const p = presets[preset];
if (!p) return;
this.scene.tweens.add({
targets: this.camera,
zoom: p.zoom,
scrollY: this.camera.scrollY + p.y,
duration: 1000,
ease: 'Sine.easeInOut'
});
console.log(`📷 Preset angle: ${preset}`);
}
// SHAKE EFFECTS
shake(intensity = 0.005, duration = 200) {
this.camera.shake(duration, intensity);
}
// FLASH EFFECTS
flash(color = 0xffffff, duration = 200) {
this.camera.flash(duration,
(color >> 16) & 0xff,
(color >> 8) & 0xff,
color & 0xff
);
}
// FADE EFFECTS
fadeOut(duration = 1000, callback) {
this.camera.fadeOut(duration, 0, 0, 0);
if (callback) {
this.camera.once('camerafadeoutcomplete', callback);
}
}
fadeIn(duration = 1000, callback) {
this.camera.fadeIn(duration, 0, 0, 0);
if (callback) {
this.camera.once('camerafadeincomplete', callback);
}
}
// PAN TO LOCATION
panTo(x, y, duration = 2000) {
this.scene.tweens.add({
targets: this.camera,
scrollX: x - this.camera.width / 2,
scrollY: y - this.camera.height / 2,
duration: duration,
ease: 'Sine.easeInOut'
});
}
// ZOOM TO
zoomTo(zoom, duration = 1000) {
this.scene.tweens.add({
targets: this.camera,
zoom: zoom,
duration: duration,
ease: 'Sine.easeInOut'
});
}
// UPDATE
update(delta) {
this.updateFreeCamera(delta);
}
// EXPORT CAMERA DATA (for trailer editing)
exportCameraData() {
const data = {
savedPositions: this.savedPositions,
timestamp: Date.now()
};
const json = JSON.stringify(data, null, 2);
console.log('📷 Camera data:', json);
// Copy to clipboard (if available)
if (navigator.clipboard) {
navigator.clipboard.writeText(json);
console.log('📷 Camera data copied to clipboard!');
}
return data;
}
// IMPORT CAMERA DATA
importCameraData(data) {
if (data.savedPositions) {
this.savedPositions = data.savedPositions;
console.log(`📷 Imported ${this.savedPositions.length} camera positions`);
}
}
}