65 lines
1.8 KiB
TypeScript
65 lines
1.8 KiB
TypeScript
import { Component, World } from "@common/rpg/core/world";
|
|
import { component } from "@common/rpg/utils/decorators";
|
|
import { getPosition, Position } from "../position";
|
|
import type { Point } from "@common/geometry";
|
|
|
|
export interface ViewportData {
|
|
screenX: number;
|
|
screenY: number;
|
|
width: number;
|
|
height: number;
|
|
worldX: number;
|
|
worldY: number;
|
|
}
|
|
|
|
@component
|
|
export class Viewport extends Component<void> {
|
|
get screenX(): number {
|
|
return Math.round(getPosition(this.entity, 'screen')?.x ?? 0);
|
|
}
|
|
|
|
get screenY(): number {
|
|
return Math.round(getPosition(this.entity, 'screen')?.y ?? 0);
|
|
}
|
|
|
|
get width(): number {
|
|
return Math.round(getPosition(this.entity, 'size')?.x ?? Infinity);
|
|
}
|
|
|
|
get height(): number {
|
|
return Math.round(getPosition(this.entity, 'size')?.y ?? Infinity);
|
|
}
|
|
|
|
get worldX(): number {
|
|
return Math.round(getPosition(this.entity)?.x ?? 0);
|
|
}
|
|
|
|
get worldY(): number {
|
|
return Math.round(getPosition(this.entity)?.y ?? 0);
|
|
}
|
|
|
|
screenToWorld = ({ x, y }: Point): Point => {
|
|
return {
|
|
x: x - this.screenX + this.worldX,
|
|
y: y - this.screenY + this.worldY,
|
|
};
|
|
}
|
|
|
|
worldToScreen = ({ x, y }: Point): Point => {
|
|
return {
|
|
x: x - this.worldX + this.screenX,
|
|
y: y - this.worldY + this.screenY,
|
|
};
|
|
}
|
|
}
|
|
|
|
export const createViewport = (world: World, viewportData: ViewportData) => {
|
|
const viewport = world.createEntity();
|
|
viewport.add(new Viewport());
|
|
viewport.add(new Position(viewportData.worldX, viewportData.worldY));
|
|
viewport.add(new Position(viewportData.width, viewportData.height), 'size');
|
|
viewport.add(new Position(viewportData.screenX, viewportData.screenY), 'screen');
|
|
|
|
return viewport;
|
|
}
|