mmy / lib /game /Camera.ts
Mohammad Shahid
first commit
3a7a84c
// FILE: lib/game/Camera.ts
import { lerp } from "../utils";
interface Target {
x: number;
y: number;
width: number;
height: number;
}
export class Camera {
// Current camera properties
x: number;
y: number;
zoom: number = 1;
// Target properties for smooth transitions
private targetX: number;
private targetY: number;
private targetZoom: number = 1;
private followTarget: Target | null = null;
// Smoothing factor for lerping
private readonly LERP_FACTOR = 0.08;
constructor(canvasWidth: number, canvasHeight: number) {
this.x = canvasWidth / 2;
this.y = canvasHeight / 2;
this.targetX = this.x;
this.targetY = this.y;
}
// --- Public methods for the sandbox API ---
panTo(x: number, y: number) {
this.followTarget = null; // Stop following any target when manually panning
this.targetX = x;
this.targetY = y;
}
setZoom(level: number) {
this.targetZoom = Math.max(0.5, Math.min(level, 3)); // Clamp zoom level
}
focusOn(target: Target) {
this.followTarget = target;
}
reset() {
this.followTarget = null;
this.targetX = 0; // Or initial canvas center
this.targetY = 0; // Or initial canvas center
this.targetZoom = 1;
}
// --- Internal update method for the game loop ---
update() {
if (this.followTarget) {
this.targetX = this.followTarget.x + this.followTarget.width / 2;
this.targetY = this.followTarget.y + this.followTarget.height / 2;
}
// Smoothly interpolate current values towards target values
this.x = lerp(this.x, this.targetX, this.LERP_FACTOR);
this.y = lerp(this.y, this.targetY, this.LERP_FACTOR);
this.zoom = lerp(this.zoom, this.targetZoom, this.LERP_FACTOR);
}
// --- Method to apply transformations to the canvas context ---
public applyTransform(ctx: CanvasRenderingContext2D, shake: { offsetX: number, offsetY: number }) {
const canvasWidth = ctx.canvas.width;
const canvasHeight = ctx.canvas.height;
// First, move the canvas origin to the center of the screen
ctx.translate(canvasWidth / 2, canvasHeight / 2);
// Then, apply the zoom
ctx.scale(this.zoom, this.zoom);
// Finally, pan the camera to the target coordinates
ctx.translate(-this.x, -this.y);
// NEW: Apply the camera shake as the very last translation
ctx.translate(shake.offsetX, shake.offsetY);
}
}