fiddle/src/camera.ts
2024-05-04 14:17:06 +02:00

125 lines
2.9 KiB
TypeScript

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);
}
}
}