File size: 3,078 Bytes
df38526
e1243e2
7ffaa9e
 
e1243e2
 
 
df38526
7ffaa9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1243e2
 
df38526
7ffaa9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df38526
e1243e2
7ffaa9e
e1243e2
 
7ffaa9e
 
 
 
 
 
 
df38526
7ffaa9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1243e2
 
7ffaa9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1243e2
 
df38526
7ffaa9e
e1243e2
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { Transform } from './transform.js';
import { Matrix } from './matrix.js';
import { lerp } from './math.js';
import { getConfig } from './config.js';

export class Camera {
    constructor() {
        this.transform = new Transform();
        this.scale = 1;
        this.targetScale = 1;
        this.viewportWidth = 0;   // Initialize to 0, will be set by setViewport
        this.viewportHeight = 0;  // Initialize to 0, will be set by setViewport
        this.targetPosition = { x: 0, y: 0, z: 0 };

        // Set default values in case config isn't ready
        this.moveLerpFactor = 0.1;
        this.zoomLerpFactor = 0.1;

        // Try to get config
        const config = getConfig();
        if (config?.camera) {
            this.moveLerpFactor = config.camera.moveLerpFactor;
            this.zoomLerpFactor = config.camera.zoomLerpFactor;
        }
    }

    setViewport(width, height) {
        this.viewportWidth = width;
        this.viewportHeight = height;
    }

    getViewMatrix() {
        // First translate to center of viewport
        const centerMatrix = Matrix.translation(
            this.viewportWidth / 2,
            this.viewportHeight / 2,
            0
        );

        // Then apply camera transform
        const cameraMatrix = Matrix.multiply(
            Matrix.scaling(this.scale, this.scale, 1),
            Matrix.translation(
                -this.transform.position.x,
                -this.transform.position.y,
                0
            )
        );

        return Matrix.multiply(cameraMatrix, centerMatrix);
    }

    update(deltaTime) {
        // Store old position to calculate velocity
        if (this._oldPos === undefined) {
            this._oldPos = { x: this.transform.position.x, y: this.transform.position.y };
        }

        // Smooth position movement
        const pos = this.transform.position;
        pos.x = lerp(pos.x, this.targetPosition.x, this.moveLerpFactor);
        pos.y = lerp(pos.y, this.targetPosition.y, this.moveLerpFactor);

        // Calculate velocity in units/s
        const dx = pos.x - this._oldPos.x;
        const dy = pos.y - this._oldPos.y;
        this.currentVelocity = {
            x: dx / deltaTime,
            y: dy / deltaTime
        };
        this._oldPos.x = pos.x;
        this._oldPos.y = pos.y;

        // Smooth scale/zoom
        this.scale = lerp(this.scale, this.targetScale, this.zoomLerpFactor);
    }

    moveBy(dx, dy, dz = 0) {
        // Invert dy for natural camera movement (up is negative, down is positive)
        this.targetPosition.x += dx;
        this.targetPosition.y -= dy;  // Invert dy here
        this.targetPosition.z += dz;
    }

    moveTo(x, y, z = 0) {
        this.targetPosition.x = x;
        this.targetPosition.y = y;
        this.targetPosition.z = z;
        this.transform.setPosition(x, y, z);  // Immediate for reset
    }

    setZoom(scale) {
        this.targetScale = scale;
        this.scale = scale;  // Immediate for reset
    }

    zoomBy(factor) {
        this.targetScale *= factor;
    }
}