99 lines
2.3 KiB
TypeScript
99 lines
2.3 KiB
TypeScript
export interface CameraState {
|
|
centerWorldX: number
|
|
centerWorldY: number
|
|
viewportWidth: number
|
|
viewportHeight: number
|
|
visibleColumns: number
|
|
translateX?: number
|
|
translateY?: number
|
|
rotationRad?: number
|
|
}
|
|
|
|
export interface ScreenPoint {
|
|
x: number
|
|
y: number
|
|
}
|
|
|
|
export interface WorldPoint {
|
|
x: number
|
|
y: number
|
|
}
|
|
|
|
export function getTileSizePx(camera: CameraState): number {
|
|
if (!camera.viewportWidth || !camera.visibleColumns) {
|
|
return 0
|
|
}
|
|
|
|
return camera.viewportWidth / camera.visibleColumns
|
|
}
|
|
|
|
export function rotateScreenPoint(point: ScreenPoint, centerX: number, centerY: number, rotationRad: number): ScreenPoint {
|
|
if (!rotationRad) {
|
|
return point
|
|
}
|
|
|
|
const deltaX = point.x - centerX
|
|
const deltaY = point.y - centerY
|
|
const cos = Math.cos(rotationRad)
|
|
const sin = Math.sin(rotationRad)
|
|
|
|
return {
|
|
x: centerX + deltaX * cos - deltaY * sin,
|
|
y: centerY + deltaX * sin + deltaY * cos,
|
|
}
|
|
}
|
|
|
|
export function worldToScreen(
|
|
camera: CameraState,
|
|
world: WorldPoint,
|
|
includeTranslate = false,
|
|
): ScreenPoint {
|
|
const tileSize = getTileSizePx(camera)
|
|
const translateX = includeTranslate ? (camera.translateX || 0) : 0
|
|
const translateY = includeTranslate ? (camera.translateY || 0) : 0
|
|
const centerX = camera.viewportWidth / 2
|
|
const centerY = camera.viewportHeight / 2
|
|
|
|
const rotated = rotateScreenPoint(
|
|
{
|
|
x: centerX + (world.x - camera.centerWorldX) * tileSize,
|
|
y: centerY + (world.y - camera.centerWorldY) * tileSize,
|
|
},
|
|
centerX,
|
|
centerY,
|
|
camera.rotationRad || 0,
|
|
)
|
|
|
|
return {
|
|
x: rotated.x + translateX,
|
|
y: rotated.y + translateY,
|
|
}
|
|
}
|
|
|
|
export function screenToWorld(
|
|
camera: CameraState,
|
|
screen: ScreenPoint,
|
|
includeTranslate = true,
|
|
): WorldPoint {
|
|
const tileSize = getTileSizePx(camera)
|
|
const translateX = includeTranslate ? (camera.translateX || 0) : 0
|
|
const translateY = includeTranslate ? (camera.translateY || 0) : 0
|
|
const centerX = camera.viewportWidth / 2
|
|
const centerY = camera.viewportHeight / 2
|
|
|
|
const unrotated = rotateScreenPoint(
|
|
{
|
|
x: screen.x - translateX,
|
|
y: screen.y - translateY,
|
|
},
|
|
centerX,
|
|
centerY,
|
|
-(camera.rotationRad || 0),
|
|
)
|
|
|
|
return {
|
|
x: camera.centerWorldX + (unrotated.x - centerX) / tileSize,
|
|
y: camera.centerWorldY + (unrotated.y - centerY) / tileSize,
|
|
}
|
|
}
|