|
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; |
|
this.viewportHeight = 0; |
|
this.targetPosition = { x: 0, y: 0, z: 0 }; |
|
|
|
|
|
this.moveLerpFactor = 0.1; |
|
this.zoomLerpFactor = 0.1; |
|
|
|
|
|
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() { |
|
|
|
const centerMatrix = Matrix.translation( |
|
this.viewportWidth / 2, |
|
this.viewportHeight / 2, |
|
0 |
|
); |
|
|
|
|
|
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) { |
|
|
|
if (this._oldPos === undefined) { |
|
this._oldPos = { x: this.transform.position.x, y: this.transform.position.y }; |
|
} |
|
|
|
|
|
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); |
|
|
|
|
|
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; |
|
|
|
|
|
this.scale = lerp(this.scale, this.targetScale, this.zoomLerpFactor); |
|
} |
|
|
|
moveBy(dx, dy, dz = 0) { |
|
|
|
this.targetPosition.x += dx; |
|
this.targetPosition.y -= dy; |
|
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); |
|
} |
|
|
|
setZoom(scale) { |
|
this.targetScale = scale; |
|
this.scale = scale; |
|
} |
|
|
|
zoomBy(factor) { |
|
this.targetScale *= factor; |
|
} |
|
} |
|
|