125 lines
2.9 KiB
TypeScript
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);
|
|
}
|
|
}
|
|
}
|