Files
nage/engine/Viewport.ts
T
2026-09-26 14:12:35 +02:00

104 lines
2.7 KiB
TypeScript

import { createVector, type Vector } from "./Vector.ts";
export type Viewport = {
scale: number;
imageSmoothing: CanvasImageSmoothing;
translation: Vector;
ctx: CanvasRenderingContext2D;
canvas: HTMLCanvasElement;
gameContainer: HTMLElement;
canvasContainer: HTMLElement;
boundaries: {
minX: number;
minY: number;
maxX: number;
maxY: number;
};
};
export const viewport: Viewport = {
scale: 4,
imageSmoothing: {
imageSmoothingEnabled: false,
imageSmoothingQuality: "low",
},
translation: createVector(),
ctx: null as unknown as CanvasRenderingContext2D,
canvas: null as unknown as HTMLCanvasElement,
gameContainer: null as unknown as HTMLElement,
canvasContainer: null as unknown as HTMLElement,
boundaries: {
minX: 0,
minY: 0,
maxX: 0,
maxY: 0,
},
};
export function initViewport(container: HTMLElement = document.body): void {
const gameContainer = document.createElement("div");
gameContainer.id = "gameContainer";
const canvasContainer = document.createElement("div");
canvasContainer.id = "canvasContainer";
const canvas = document.createElement("canvas");
viewport.ctx = canvas.getContext("2d", {
alpha: false,
}) as CanvasRenderingContext2D;
viewport.canvas = canvas;
viewport.canvasContainer = canvasContainer;
viewport.gameContainer = gameContainer;
canvasContainer.appendChild(canvas);
gameContainer.appendChild(canvasContainer);
container.appendChild(gameContainer);
}
export function setScale(scale: number): void {
viewport.scale = scale;
self.dispatchEvent(new Event("resize"));
}
export function resizeCanvas(width: number, height: number): void {
const {
scale,
imageSmoothing,
ctx,
canvas,
canvasContainer,
gameContainer,
translation,
boundaries,
} = viewport;
const containerWidth = (gameContainer.offsetWidth / scale) | 0;
const containerHeight = (gameContainer.offsetHeight / scale) | 0;
canvas.width = Math.min(width, containerWidth);
canvas.height = Math.min(height, containerHeight);
ctx.imageSmoothingEnabled = imageSmoothing.imageSmoothingEnabled;
ctx.imageSmoothingQuality = imageSmoothing.imageSmoothingQuality;
const canvasWidth = canvas.width * scale - (containerWidth % scale);
const canvasHeight = canvas.height * scale - (containerHeight % scale);
canvasContainer.style = `width: ${canvasWidth}px; height: ${canvasHeight}px;`;
boundaries.minX = translation.x;
boundaries.minY = translation.y;
boundaries.maxX = translation.x + canvas.width;
boundaries.maxY = translation.y + canvas.height;
}
export function resetCtx() {
const { ctx, canvas, translation } = viewport;
ctx.restore();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(-(translation.x | 0), -(translation.y | 0));
}