445 lines
10 KiB
Markdown
445 lines
10 KiB
Markdown
# 🎬 ADVANCED CAMERA FEATURES - IMPLEMENTATION PLAN
|
|
|
|
**Datum:** 12. December 2025
|
|
**Prioriteta:** MEDIUM
|
|
**Estimated Time:** 2-3 ure
|
|
|
|
---
|
|
|
|
## 🎯 **CILJI:**
|
|
|
|
Razširitev Camera System z naprednimi funkcionalnostmi za profesionalne trailerje:
|
|
- Smooth camera movement (Bezier curves)
|
|
- Recording Mode (UI hide, slow-mo)
|
|
- Cinematic Sequences (pre-made cutscenes)
|
|
- Demo Recording (60s gameplay loops)
|
|
|
|
---
|
|
|
|
## 📋 **FAZA 1: SMOOTH CAMERA MOVEMENT** (45 min)
|
|
|
|
### **1.1 Bezier Curve Paths**
|
|
**Dodaj v CameraSystem.js:**
|
|
|
|
```javascript
|
|
// Bezier curve camera path
|
|
createBezierPath(points, duration = 5000) {
|
|
// points = [{ x, y, zoom }, { x, y, zoom }, ...]
|
|
|
|
const path = new Phaser.Curves.Spline(points.map(p => [p.x, p.y]));
|
|
|
|
let progress = 0;
|
|
const tween = this.scene.tweens.add({
|
|
targets: { t: 0 },
|
|
t: 1,
|
|
duration: duration,
|
|
ease: 'Sine.easeInOut',
|
|
onUpdate: (tween) => {
|
|
const t = tween.getValue();
|
|
const point = path.getPoint(t);
|
|
|
|
// Interpolate zoom
|
|
const zoomIndex = Math.floor(t * (points.length - 1));
|
|
const zoomT = (t * (points.length - 1)) - zoomIndex;
|
|
const zoom = Phaser.Math.Linear(
|
|
points[zoomIndex].zoom,
|
|
points[Math.min(zoomIndex + 1, points.length - 1)].zoom,
|
|
zoomT
|
|
);
|
|
|
|
this.camera.scrollX = point.x - this.camera.width / 2;
|
|
this.camera.scrollY = point.y - this.camera.height / 2;
|
|
this.camera.setZoom(zoom);
|
|
}
|
|
});
|
|
|
|
return tween;
|
|
}
|
|
|
|
// Example usage:
|
|
// cameraSystem.createBezierPath([
|
|
// { x: 100, y: 100, zoom: 1.0 },
|
|
// { x: 200, y: 150, zoom: 1.5 },
|
|
// { x: 300, y: 100, zoom: 1.0 }
|
|
// ], 5000);
|
|
```
|
|
|
|
### **1.2 Cinematic Zoom Controls**
|
|
```javascript
|
|
cinematicZoom(targetZoom, duration = 2000, ease = 'Sine.easeInOut') {
|
|
return this.scene.tweens.add({
|
|
targets: this.camera,
|
|
zoom: targetZoom,
|
|
duration: duration,
|
|
ease: ease
|
|
});
|
|
}
|
|
|
|
// Zoom presets
|
|
zoomPresets = {
|
|
'extreme_closeup': 2.5,
|
|
'closeup': 1.8,
|
|
'medium': 1.2,
|
|
'wide': 0.8,
|
|
'extreme_wide': 0.4
|
|
};
|
|
|
|
applyZoomPreset(preset) {
|
|
const zoom = this.zoomPresets[preset];
|
|
if (zoom) {
|
|
this.cinematicZoom(zoom);
|
|
}
|
|
}
|
|
```
|
|
|
|
### **1.3 Camera Shake Intensity Controls**
|
|
```javascript
|
|
cinematicShake(intensity = 'medium', duration = 500) {
|
|
const intensities = {
|
|
'subtle': 0.002,
|
|
'medium': 0.005,
|
|
'strong': 0.01,
|
|
'extreme': 0.02
|
|
};
|
|
|
|
const value = intensities[intensity] || intensities.medium;
|
|
this.camera.shake(duration, value);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 **FAZA 2: RECORDING MODE** (30 min)
|
|
|
|
### **2.1 Hide UI Toggle (F4)**
|
|
**Že implementirano kot F7!** ✅
|
|
|
|
### **2.2 Free Camera Mode (noclip)**
|
|
**Že implementirano kot F6!** ✅
|
|
|
|
### **2.3 Time Slow-Mo**
|
|
```javascript
|
|
setTimeScale(scale) {
|
|
// scale: 1.0 = normal, 0.5 = half speed, 0.25 = quarter speed
|
|
this.scene.time.timeScale = scale;
|
|
|
|
// Also affect physics
|
|
if (this.scene.physics && this.scene.physics.world) {
|
|
this.scene.physics.world.timeScale = scale;
|
|
}
|
|
|
|
console.log(`⏱️ Time scale: ${scale}x`);
|
|
}
|
|
|
|
// Keyboard shortcuts
|
|
// F11 - Slow-mo 0.5x
|
|
// F12 - Slow-mo 0.25x
|
|
// Shift+F12 - Normal speed
|
|
```
|
|
|
|
### **2.4 Screenshot Mode (High-Res)**
|
|
```javascript
|
|
captureHighResScreenshot(scale = 2) {
|
|
// Temporarily increase resolution
|
|
const originalZoom = this.camera.zoom;
|
|
this.camera.setZoom(originalZoom * scale);
|
|
|
|
// Capture after next frame
|
|
this.scene.time.delayedCall(100, () => {
|
|
this.scene.game.renderer.snapshot((image) => {
|
|
// Download image
|
|
const link = document.createElement('a');
|
|
link.download = `novafarma_${Date.now()}.png`;
|
|
link.href = image.src;
|
|
link.click();
|
|
|
|
console.log('📸 High-res screenshot captured!');
|
|
});
|
|
|
|
// Restore zoom
|
|
this.camera.setZoom(originalZoom);
|
|
});
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 **FAZA 3: CINEMATIC SEQUENCES** (60 min)
|
|
|
|
### **3.1 Intro Cutscene (Farm Arrival)**
|
|
```javascript
|
|
playIntroCutscene() {
|
|
console.log('🎬 Playing intro cutscene...');
|
|
|
|
// Hide UI
|
|
this.toggleScreenshotMode();
|
|
|
|
// Sequence
|
|
const sequence = [
|
|
// 1. Fade in from black
|
|
() => this.fadeIn(2000),
|
|
|
|
// 2. Wide shot of farm (3 seconds)
|
|
() => {
|
|
this.panTo(400, 400, 2000);
|
|
this.zoomTo(0.5, 2000);
|
|
},
|
|
|
|
// 3. Zoom to player (2 seconds)
|
|
() => {
|
|
this.panTo(this.scene.player.sprite.x, this.scene.player.sprite.y, 2000);
|
|
this.zoomTo(1.2, 2000);
|
|
},
|
|
|
|
// 4. Follow player
|
|
() => {
|
|
this.mode = 'follow';
|
|
this.camera.startFollow(this.scene.player.sprite);
|
|
this.toggleScreenshotMode(); // Restore UI
|
|
}
|
|
];
|
|
|
|
this.playSequence(sequence, [0, 3000, 5000, 7000]);
|
|
}
|
|
|
|
playSequence(actions, timings) {
|
|
actions.forEach((action, i) => {
|
|
this.scene.time.delayedCall(timings[i], action);
|
|
});
|
|
}
|
|
```
|
|
|
|
### **3.2 Boss Encounter Intro**
|
|
```javascript
|
|
playBossIntroCutscene(bossX, bossY) {
|
|
const sequence = [
|
|
// Dramatic zoom out
|
|
() => this.zoomTo(0.3, 1000),
|
|
|
|
// Pan to boss
|
|
() => this.panTo(bossX, bossY, 2000),
|
|
|
|
// Zoom to boss face
|
|
() => this.zoomTo(1.5, 1500),
|
|
|
|
// Shake
|
|
() => this.cinematicShake('strong', 500),
|
|
|
|
// Flash red
|
|
() => this.flash(0xff0000, 300),
|
|
|
|
// Return to player
|
|
() => {
|
|
this.panTo(this.scene.player.sprite.x, this.scene.player.sprite.y, 1500);
|
|
this.zoomTo(1.0, 1500);
|
|
}
|
|
];
|
|
|
|
this.playSequence(sequence, [0, 1000, 3000, 4500, 5000, 5500]);
|
|
}
|
|
```
|
|
|
|
### **3.3 Day/Night Transition Showcase**
|
|
```javascript
|
|
playDayNightShowcase() {
|
|
// Speed up time temporarily
|
|
const originalTimeScale = this.scene.timeSystem.timeScale;
|
|
this.scene.timeSystem.timeScale = 10.0; // 10x speed
|
|
|
|
// Wide shot
|
|
this.zoomTo(0.6, 2000);
|
|
|
|
// Wait for full day/night cycle
|
|
this.scene.time.delayedCall(12000, () => {
|
|
// Restore time
|
|
this.scene.timeSystem.timeScale = originalTimeScale;
|
|
this.zoomTo(1.0, 2000);
|
|
});
|
|
}
|
|
```
|
|
|
|
### **3.4 Season Change Sequence**
|
|
```javascript
|
|
playSeasonShowcase() {
|
|
// Cycle through seasons
|
|
const seasons = ['spring', 'summer', 'autumn', 'winter'];
|
|
|
|
seasons.forEach((season, i) => {
|
|
this.scene.time.delayedCall(i * 3000, () => {
|
|
if (this.scene.weatherSystem) {
|
|
this.scene.weatherSystem.setSeason(season);
|
|
}
|
|
|
|
// Flash transition
|
|
this.flash(0xffffff, 500);
|
|
});
|
|
});
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 **FAZA 4: DEMO RECORDING** (45 min)
|
|
|
|
### **4.1 60-Second Gameplay Loop**
|
|
```javascript
|
|
recordGameplayLoop() {
|
|
console.log('🎥 Recording 60-second gameplay loop...');
|
|
|
|
const script = [
|
|
// 0-10s: Farming
|
|
{ time: 0, action: () => this.showcaseFarming() },
|
|
|
|
// 10-20s: Building
|
|
{ time: 10000, action: () => this.showcaseBuilding() },
|
|
|
|
// 20-30s: Combat
|
|
{ time: 20000, action: () => this.showcaseCombat() },
|
|
|
|
// 30-40s: Crafting
|
|
{ time: 30000, action: () => this.showcaseCrafting() },
|
|
|
|
// 40-50s: NPCs
|
|
{ time: 40000, action: () => this.showcaseNPCs() },
|
|
|
|
// 50-60s: Day/Night
|
|
{ time: 50000, action: () => this.playDayNightShowcase() }
|
|
];
|
|
|
|
script.forEach(({ time, action }) => {
|
|
this.scene.time.delayedCall(time, action);
|
|
});
|
|
}
|
|
|
|
showcaseFarming() {
|
|
// Pan to farm area
|
|
this.panTo(400, 400, 2000);
|
|
this.zoomTo(1.2, 2000);
|
|
|
|
// Simulate farming actions
|
|
// (Player would do this manually or via AI)
|
|
}
|
|
|
|
showcaseBuilding() {
|
|
// Show building mode
|
|
if (this.scene.buildSystem) {
|
|
this.scene.buildSystem.toggleBuildMode();
|
|
}
|
|
}
|
|
|
|
showcaseCombat() {
|
|
// Spawn enemy for demo
|
|
// Show combat
|
|
}
|
|
|
|
showcaseCrafting() {
|
|
// Open crafting menu
|
|
const uiScene = this.scene.scene.get('UIScene');
|
|
if (uiScene) {
|
|
uiScene.toggleCraftingMenu();
|
|
}
|
|
}
|
|
|
|
showcaseNPCs() {
|
|
// Pan to NPCs
|
|
if (this.scene.npcs && this.scene.npcs.length > 0) {
|
|
const npc = this.scene.npcs[0];
|
|
this.panTo(npc.sprite.x, npc.sprite.y, 2000);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📝 **KEYBOARD SHORTCUTS:**
|
|
|
|
```
|
|
F6 - Free Camera Mode
|
|
F7 - Screenshot Mode (Hide UI)
|
|
F8 - Save Camera Position
|
|
F10 - Cinematic Mode
|
|
F11 - Slow-mo 0.5x
|
|
F12 - Slow-mo 0.25x
|
|
Shift+F12 - Normal speed
|
|
Ctrl+S - High-res screenshot
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 **INTEGRATION:**
|
|
|
|
**GameScene.js:**
|
|
```javascript
|
|
// In create():
|
|
this.cameraSystem = new CameraSystem(this);
|
|
|
|
// In update():
|
|
if (this.cameraSystem) {
|
|
this.cameraSystem.update(delta);
|
|
}
|
|
|
|
// Keyboard shortcuts:
|
|
this.input.keyboard.on('keydown-F11', () => {
|
|
this.cameraSystem.setTimeScale(0.5);
|
|
});
|
|
|
|
this.input.keyboard.on('keydown-F12', () => {
|
|
this.cameraSystem.setTimeScale(0.25);
|
|
});
|
|
|
|
this.input.keyboard.on('keydown', (event) => {
|
|
if (event.shiftKey && event.key === 'F12') {
|
|
this.cameraSystem.setTimeScale(1.0);
|
|
}
|
|
if (event.ctrlKey && event.key === 's') {
|
|
event.preventDefault();
|
|
this.cameraSystem.captureHighResScreenshot();
|
|
}
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 **IMPLEMENTATION STEPS:**
|
|
|
|
1. **Razširi CameraSystem.js** (45 min)
|
|
- Bezier curves
|
|
- Cinematic zoom
|
|
- Shake controls
|
|
|
|
2. **Dodaj Recording Mode** (30 min)
|
|
- Time slow-mo
|
|
- High-res screenshots
|
|
|
|
3. **Ustvari Cinematic Sequences** (60 min)
|
|
- Intro cutscene
|
|
- Boss intro
|
|
- Day/night showcase
|
|
- Season showcase
|
|
|
|
4. **Implementiraj Demo Recording** (45 min)
|
|
- 60s gameplay loop
|
|
- Feature showcases
|
|
|
|
5. **Integration \u0026 Testing** (30 min)
|
|
|
|
**Total:** 3h 30min
|
|
|
|
---
|
|
|
|
## 🎯 **PRIORITETA:**
|
|
|
|
**MEDIUM** - Pomembno za marketing, ampak ne kritično za gameplay.
|
|
|
|
**Priporočam:** Implementacija po dokončanju core funkcionalnosti.
|
|
|
|
---
|
|
|
|
**Status:** ⏳ **PLAN PRIPRAVLJEN**
|
|
|
|
**CameraSystem.js že obstaja** - samo razširitev potrebna!
|
|
|
|
**Estimated time:** 3h 30min
|
|
|
|
Želite implementacijo zdaj ali kasneje? 🎬
|