import { Canvas } from "@/canvas"; import { GameObject } from '@/common/gameobject'; import { Rect } from "@/common/rect"; import { Vec } from "@/common/vec"; export class Camera extends GameObject { canvas: Canvas; zoom: number = 1; rotateAngle: number = 0; lockedObject: GameObject | null = null; constructor(canvas: Canvas) { super(); this.canvas = canvas; } get ctx() { return this.canvas.ctx; } get width() { return this.canvas.width / this.zoom; } get height() { return this.canvas.height / this.zoom; } applyTransformation() { this.resetTransform(); this.ctx.scale(this.zoom, this.zoom); //this.ctx.rotate(this.rotateAngle); this.ctx.translate(-this.pos.x, -this.pos.y); } resetTransform() { this.ctx.resetTransform(); } withoutTransform(callback: () => void) { this.resetTransform(); callback(); this.applyTransformation(); } view() { return new Rect( this.pos.x, this.pos.y, this.width + this.pos.x, this.height + this.pos.y ); } moveTo(pos: Vec) { this.ctx.translate(this.pos.x - pos.x, this.pos.y - pos.y); this.pos = pos.clone(); } centerPos(pos: Vec) { this.moveTo(pos.sub(this.width / 2, this.height / 2)); } moveBy(dir: Vec) { this.moveTo(this.pos.sub(dir)); } rotateBy(angle: number) { this.rotateAround(this.canvas.center.x, this.canvas.center.y, angle); this.rotateAngle += angle; } rotateTo(angle: number) { this.rotateBy(angle - this.rotateAngle); this.rotateAngle = angle; } rotateAround(x: number, y: number, angle: number) { this.ctx.translate(x, y); this.ctx.rotate(angle); this.ctx.translate(-x, -y); } zoomTo(zoom: number, zoomPoint: Vec) { zoom = Math.max(0.1, Math.min(10, zoom)); this.pos = zoomPoint.scale(1 / this.zoom - 1 / zoom).add(this.pos); this.zoom = zoom; this.applyTransformation(); } zoomBy(zoom: number, zoomPoint: Vec) { this.zoomTo(this.zoom + zoom, zoomPoint); } lockToObj(object: GameObject) { this.lockedObject = object; console.log("Watching", object); } unlock() { this.lockedObject = null; } screenToScene(pos: Vec) { return pos .scale(1 / this.zoom) .add(this.pos); } update(canvas: Canvas) { if (null != this.lockedObject && canvas.objects.includes(this.lockedObject)) { this.centerPos(this.lockedObject.pos); } } render(canvas: Canvas) { if (false) { const { ctx } = canvas; const view = this.view(); ctx.strokeStyle = "white"; ctx.strokeRect(view.x + 10, view.y + 10, view.width - 10, view.height - 10); } } }