diff --git a/packages/core/data/index.ts b/packages/core/data/index.ts index 3ba4f25..4359f27 100644 --- a/packages/core/data/index.ts +++ b/packages/core/data/index.ts @@ -1,4 +1,12 @@ +import { SetupInfo } from "../types/static"; import FactionData from "./factions"; import PlanetData from "./planets"; import SystemData from "./systems"; + +const DefaultSetupInfo: SetupInfo = { + factions: FactionData, + planets: PlanetData, + systems: SystemData, +}; + export { FactionData, PlanetData, SystemData }; diff --git a/packages/core/galaxy.ts b/packages/core/galaxy.ts index 0677925..835e534 100644 --- a/packages/core/galaxy.ts +++ b/packages/core/galaxy.ts @@ -62,6 +62,7 @@ export function ttsStringtoTilePositions(ttsString: string): { }[] { // const mapWidth = 9; // const mapHeight = 9; + const offset = -2; const tileIds = ttsString.split(" ").map((x) => Number(x)); const tilePositions = [ @@ -167,7 +168,7 @@ export function createSixPlayerGalaxy( } map = map.concat({ - position: { x: 7, y: 8 }, + position: { x: 7, y: 1 }, systemId: 82, }); diff --git a/packages/core/index.ts b/packages/core/index.ts index 26736c3..960eb9d 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -1,2 +1,3 @@ export * from "./galaxy"; export * from "./types/galaxy"; +export * from "./math"; diff --git a/packages/core/math.ts b/packages/core/math.ts index d489c18..c2259c5 100644 --- a/packages/core/math.ts +++ b/packages/core/math.ts @@ -1,6 +1,7 @@ const HexDefaultWidth = 364.0; const HexDefaultHeight = 317.0; -const MagicY = 0.87; +// const HexMagicY = 0.87; +const HexMagicY = 0.7555; class Vec2f { x: number = 0; @@ -15,4 +16,76 @@ class Axial2 { } } -export { MagicY, HexDefaultWidth, HexDefaultHeight }; +interface BoundingBox { + minX: number; + minY: number; + maxX: number; + maxY: number; +} + +const tilePositionToCoordinate: (position: { x: number; y: number }) => { + x: number; + y: number; +} = (position: { x: number; y: number }) => { + const xOffset = (position.x * HexMagicY + 0.5) * HexDefaultWidth; + const yOffset = + (position.x % 2 == 0 ? 1 + position.y : 0.5 + position.y) * + HexDefaultHeight; + + return { + x: Math.round(100 * xOffset) / 100, + y: Math.round(100 * yOffset) / 100, + }; +}; + +const tileBounds: (position: { + x: number; + y: number; +}) => BoundingBox = (position: { x: number; y: number }) => { + const minX = position.x * HexMagicY * HexDefaultWidth; + const maxX = (position.x * HexMagicY + 1) * HexDefaultWidth; + const minY = + (position.x % 2 == 0 ? 0.5 + position.y : position.y) * HexDefaultHeight; + const maxY = + (position.x % 2 == 0 ? 1.5 + position.y : 1 + position.y) * + HexDefaultHeight; + + return { + minX: Math.round(100 * minX) / 100, + minY: Math.round(100 * minY) / 100, + maxX: Math.round(100 * maxX) / 100, + maxY: Math.round(100 * maxY) / 100, + }; +}; + +const expandBoundingBox: ( + one: BoundingBox, + two: BoundingBox | number +) => BoundingBox = (one, two) => { + if (typeof two === "number") { + return { + minX: one.minX - two, + minY: one.minY - two, + maxX: one.maxX + two, + maxY: one.maxY + two, + }; + } + + return { + minX: Math.min(one.minX, two.minX), + minY: Math.min(one.minY, two.minY), + maxX: Math.max(one.maxX, two.maxX), + maxY: Math.max(one.maxY, two.maxY), + }; +}; + +export type { BoundingBox }; + +export { + HexMagicY, + HexDefaultWidth, + HexDefaultHeight, + tilePositionToCoordinate, + tileBounds, + expandBoundingBox, +}; diff --git a/packages/core/tests/math.test.ts b/packages/core/tests/math.test.ts new file mode 100644 index 0000000..28d4d7f --- /dev/null +++ b/packages/core/tests/math.test.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest"; +import { tilePositionToCoordinate, tileBounds } from "../math"; + +describe("math.test.coords", () => { + it("Test coordinates", () => { + const coords0 = tilePositionToCoordinate({ x: 0, y: 0 }); + expect(coords0).toEqual({ x: 182, y: 317 }); + + const coords1 = tilePositionToCoordinate({ x: 1, y: 0 }); + expect(coords1).toEqual({ x: 457, y: 158.5 }); + + const coords2 = tilePositionToCoordinate({ x: 0, y: 1 }); + expect(coords2).toEqual({ x: 182, y: 634 }); + }); + + it("Test bounding box", () => { + const bb0 = tileBounds({ x: 0, y: 0 }); + expect(bb0).toEqual({ minX: 0, minY: 158.5, maxX: 364, maxY: 475.5 }); + + const bb1 = tileBounds({ x: 1, y: 0 }); + expect(bb1).toEqual({ minX: 275, minY: 0, maxX: 639, maxY: 317 }); + }); +}); diff --git a/packages/core/types/static.ts b/packages/core/types/static.ts index 8cdb9f6..565e428 100644 --- a/packages/core/types/static.ts +++ b/packages/core/types/static.ts @@ -47,3 +47,9 @@ export interface Faction { game: Expansion; attributes: FactionAttributes[]; } + +export interface SetupInfo { + factions: Faction[]; + systems: System[]; + planets: Planet[]; +} diff --git a/packages/ui/PublicGalaxyMap.tsx b/packages/ui/PublicGalaxyMap.tsx index 7f6e631..a766233 100644 --- a/packages/ui/PublicGalaxyMap.tsx +++ b/packages/ui/PublicGalaxyMap.tsx @@ -1,5 +1,10 @@ import * as React from "react"; -import { PublicGalaxy } from "@twilight-assembly/core"; +import { + BoundingBox, + PublicGalaxy, + expandBoundingBox, + tileBounds, +} from "@twilight-assembly/core"; import { Stage } from "@pixi/react"; import { GalaxySystemTile } from "./pixi/GalaxySystemTile"; import Viewport from "./pixi/Viewport"; @@ -10,10 +15,15 @@ export const PublicGalaxyMap = (props: { publicGalaxy: PublicGalaxy }) => { )); - const mapWidth = 3640; - const mapHeight = 3170; - const screenWidth = 1200; - const screenHeight = 740; + let worldBounds: BoundingBox = { + maxX: -100, + maxY: -100, + minX: 10000, + minY: 10000, + }; + Object.values(props.publicGalaxy.systems).forEach((element) => { + worldBounds = expandBoundingBox(tileBounds(element.position), worldBounds); + }); const parentRef = React.useRef(null); const windowSize = useWindowSize(); @@ -35,8 +45,9 @@ export const PublicGalaxyMap = (props: { publicGalaxy: PublicGalaxy }) => {
diff --git a/packages/ui/pixi/GalaxySystemTile.tsx b/packages/ui/pixi/GalaxySystemTile.tsx index c536fef..e80d9f1 100644 --- a/packages/ui/pixi/GalaxySystemTile.tsx +++ b/packages/ui/pixi/GalaxySystemTile.tsx @@ -1,28 +1,21 @@ import { Sprite } from "@pixi/react"; -import { Position } from "@twilight-assembly/core"; +import { Position, tilePositionToCoordinate } from "@twilight-assembly/core"; import * as React from "react"; export const GalaxySystemTile = (props: { systemId: number; position: Position; }) => { - const pxTileWidth = 364; - const pxTileHeight = 317; - /// Large tile size - const pxTileHeightStretch = 340; - - const hexMagicY = 0.7555; - const xOffset = (props.position.x * hexMagicY + 0.5) * pxTileWidth; - const yOffset = - (props.position.x % 2 == 0 - ? 1 + props.position.y - : 0.5 + props.position.y) * pxTileHeight; + const px = tilePositionToCoordinate({ + x: props.position.x, + y: props.position.y, + }); return ( ); diff --git a/packages/ui/pixi/Viewport.tsx b/packages/ui/pixi/Viewport.tsx index 5a4e6c9..26f2dbb 100644 --- a/packages/ui/pixi/Viewport.tsx +++ b/packages/ui/pixi/Viewport.tsx @@ -3,12 +3,14 @@ import * as PIXI from "pixi.js"; import { Viewport } from "pixi-viewport"; import { PixiComponent, useApp } from "@pixi/react"; import { EventSystem } from "@pixi/events"; +import { BoundingBox } from "@twilight-assembly/core"; export interface ViewportProps { screenWidth: number; screenHeight: number; mapWidth: number; mapHeight: number; + mapBounds: BoundingBox; children?: React.ReactNode; } @@ -30,23 +32,23 @@ const PixiComponentViewport = PixiComponent("Viewport", { ticker: app.ticker, passiveWheel: false, }); - viewport + return viewport .drag() .pinch() .wheel() .decelerate() .clamp({ direction: "all", - bottom: props.mapHeight, - top: 0, - left: -80, - right: props.mapWidth, + bottom: props.mapBounds.maxY, + top: props.mapBounds.minY, + left: props.mapBounds.minX, + right: props.mapBounds.maxX, }) .clampZoom({ minScale: 0.4, maxScale: 8, }); - return viewport; + // return viewport; }, applyProps(instance, oldProps, newProps) { if (