diff --git a/package-lock.json b/package-lock.json index 793cf11..f8e2b23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12769,6 +12769,16 @@ "errno": "0.1.7" } }, + "worker-loader": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-1.1.1.tgz", + "integrity": "sha512-qJZLVS/jMCBITDzPo/RuweYSIG8VJP5P67mP/71alGyTZRe1LYJFdwLjLalY3T5ifx0bMDRD3OB6P2p1escvlg==", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "schema-utils": "0.4.5" + } + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index 467b7a2..3072af3 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "uglifyjs-webpack-plugin": "^1.2.4", "webpack": "^4.4.1", "webpack-cli": "^2.0.13", - "webpack-dev-server": "^3.1.1" + "webpack-dev-server": "^3.1.1", + "worker-loader": "^1.1.1" }, "dependencies": { "@types/pixi.js": "^4.7.2", diff --git a/src/Line.ts b/src/Line.ts index a45a314..af29bff 100644 --- a/src/Line.ts +++ b/src/Line.ts @@ -5,17 +5,13 @@ import LineConnection from './LineConnection'; import Station from './Station'; import { distance, randomInt, randomPoint } from './utils'; -const CONNECTION_RADIUS = Math.floor(Math.sqrt( - Math.pow(window.innerWidth, 2) + Math.pow(window.innerHeight, 2), -) / 8); - export default class Line { public name: string; - public color: tinycolorInstance; + public color: ColorFormats.RGBA; constructor( name: string, - color: tinycolorInstance, + color: ColorFormats.RGBA, ) { this.name = name; this.color = color; @@ -26,13 +22,14 @@ export default class Line { stations: Station[], visitedStations: Station[], connectionLimit: number, + connectionRadius: number, ) { visitedStations.push(currentStation); const otherStations = stations.filter(station => station !== currentStation); const closeStations = Station.stationsWithinRadius( otherStations, currentStation.location, - CONNECTION_RADIUS, + connectionRadius, ); for (let i = 0; i < connectionLimit; i += 1) { if (closeStations.length < 1) { @@ -51,6 +48,7 @@ export default class Line { stations, visitedStations, connectionLimit, + connectionRadius, ); } } diff --git a/src/LineConnection.ts b/src/LineConnection.ts index 33db81c..ee9393e 100644 --- a/src/LineConnection.ts +++ b/src/LineConnection.ts @@ -1,9 +1,11 @@ import Line from './Line'; +import Signal from './Signal'; import Station from './Station'; export default class LineConnection { - public station: Station; public line: Line; + public signals: Signal[]; + public station: Station; constructor( station: Station, diff --git a/src/Station.ts b/src/Station.ts index d1780ad..914d0ea 100644 --- a/src/Station.ts +++ b/src/Station.ts @@ -1,3 +1,4 @@ +import Point from 'pixi.js/lib/core/math/Point'; import * as tinycolor from 'tinycolor2'; import Direction, { getPointDirection } from './Direction'; @@ -18,23 +19,23 @@ export default class Station { return largest; } - public static stationsWithinRadius(stations: Station[], point: PIXI.Point, + public static stationsWithinRadius(stations: Station[], point: Point, radius: number): Station[] { return stations.filter(station => distance(point, station.location) <= radius); } - public static stationsInDirection(stations: Station[], point: PIXI.Point, + public static stationsInDirection(stations: Station[], point: Point, direction: Direction): Station[] { return stations.filter(station => getPointDirection(point, station.location) === direction); } - public static closestStation(stations: Station[], point: PIXI.Point): Station { + public static closestStation(stations: Station[], point: Point): Station { return stations.reduce( (prev, curr) => distance(point, prev.location) < distance(point, curr.location) ? prev : curr, ); } - public static randomCloseLargeStation(stations: Station[], point: PIXI.Point, + public static randomCloseLargeStation(stations: Station[], point: Point, radius: number): Station { const closeStations = Station.stationsWithinRadius(stations, point, radius); @@ -42,7 +43,7 @@ export default class Station { return weightedRandom(closeStations, closeStationWeights); } - public static isPointDistant(point: PIXI.Point, stations: Station[], + public static isPointDistant(point: Point, stations: Station[], minDistance: number): boolean { for (const station of stations) { if (distance(point, station.location) < minDistance) { @@ -52,10 +53,15 @@ export default class Station { return true; } - public static randomDistantPoint(stations: Station[], minDistance: number): PIXI.Point | null { + public static randomDistantPoint( + stations: Station[], + minDistance: number, + height: number, + width: number, + ): Point | null { let tries = 100; while (tries > 0) { - const point = randomPoint(); + const point = randomPoint(height, width); if (Station.isPointDistant(point, stations, minDistance)) { return point; } @@ -64,19 +70,16 @@ export default class Station { return null; } - public location: PIXI.Point; + public location: Point; public population: number; public connections: LineConnection[]; public id: number; - public label: PIXI.Text; - public color: tinycolorInstance; - - private textStyle: object; + public color: ColorFormats.RGBA; constructor( - location: PIXI.Point, + location: Point, population: number, - color: tinycolorInstance, + color: ColorFormats.RGBA, connections?: LineConnection[], ) { this.location = location; @@ -87,15 +90,5 @@ export default class Station { // for debugging stationCount += 1; this.id = stationCount; - this.textStyle = { - fill: '#FFA500', - fontFamily: 'monospace', - fontSize: '12px', - }; - this.renderLabel(); - } - - public renderLabel() { - this.label = new PIXI.Text(`${this.id}`, this.textStyle); } } diff --git a/src/Station.worker.ts b/src/Station.worker.ts new file mode 100644 index 0000000..427748c --- /dev/null +++ b/src/Station.worker.ts @@ -0,0 +1,60 @@ +import * as tinycolor from 'tinycolor2'; + +import Line from './Line'; +import Station from './Station'; +import { randomInt } from './utils'; + +const LINE_CONNECTION_LIMIT = 5; +const ctx: Worker = self as any; + +const initStations = (numStations: number, height: number, width: number): Station[] => { + const stations: Station[] = []; + for (let i = 0; i < numStations; i += 1) { + stations.push(new Station( + Station.randomDistantPoint(stations, 30, height, width), + randomInt(300, 2000), + tinycolor.random().toRgb())); + } + return stations; +}; + +const initLines = (numLines: number, stations: Station[], connectionRadius: number): Line[] => { + const lines = []; + for (let i = 0; i < numLines; i += 1) { + let color = tinycolor.random(); + while (color.isDark()) { + color = tinycolor.random(); + } + const lineColor = color.toRgb(); + const stationsWithoutConnections = stations.filter(station => + station.connections.length === 0, + ); + let centralHub: Station; + if (stationsWithoutConnections.length > 0) { + centralHub = Station.largestStation(stationsWithoutConnections); + } else { + centralHub = stations[randomInt(0, stations.length - 1)]; + } + const line = new Line(`line-${i}`, lineColor); + const stationsLeft = stations.slice(0); + line.connectStations(centralHub, stationsLeft, [], LINE_CONNECTION_LIMIT, connectionRadius); + lines.push(line); + } + return lines; +}; + +ctx.addEventListener('message', (event: MessageEvent) => { + if ('initStations' in event.data) { + const { connectionRadius, height, numLines, numStations, width } = event.data.initStations; + let stations: Station[] = []; + let lines: Line[] = []; + let stationsWithConnections: Station[] = []; + while (stationsWithConnections.length === 0) { + // If all stations are too far away to connect, try generating again + stations = initStations(numStations, height, width); + lines = initLines(numLines, stations, connectionRadius); + stationsWithConnections = stations.filter(station => station.connections.length > 0); + } + ctx.postMessage({ stations, lines }); + } +}); diff --git a/src/Train.ts b/src/Train.ts index d3dcf21..6a32a42 100644 --- a/src/Train.ts +++ b/src/Train.ts @@ -1,3 +1,4 @@ +import Point from 'pixi.js/lib/core/math/Point'; import * as tinycolor from 'tinycolor2'; import Station from './Station'; @@ -5,25 +6,23 @@ import Station from './Station'; let trainCount = 0; export default class Train { - public location: PIXI.Point; + public location: Point; public speed: number; public origin: Station; public destination: Station; public passengers: number; public id: number; - public label: PIXI.Text; - public color: tinycolorInstance; - public sprite: PIXI.Sprite; + public color: ColorFormats.RGBA; private textStyle: object; constructor( - location: PIXI.Point, + location: Point, speed: number, passengers: number, origin: Station, destination: Station, - color: tinycolorInstance, + color: ColorFormats.RGBA, ) { this.location = location; this.speed = speed; @@ -32,25 +31,8 @@ export default class Train { this.passengers = passengers; this.color = color; - this.sprite = new PIXI.Sprite(PIXI.loader.resources.nodeImg.texture); - // for debugging trainCount += 1; this.id = trainCount; - this.textStyle = { - fill: '#AEAEAE', - fontFamily: 'monospace', - fontSize: '12px', - }; - this.renderLabel(); - } - - public boardPassengers() { - if (this.location === this.origin.location) { // about to leave a station - } - } - - public renderLabel() { - this.label = new PIXI.Text(`${this.id}`, this.textStyle); } } diff --git a/src/Train.worker.ts b/src/Train.worker.ts new file mode 100644 index 0000000..79f2342 --- /dev/null +++ b/src/Train.worker.ts @@ -0,0 +1,116 @@ +import Point from 'pixi.js/lib/core/math/Point'; +import * as tinycolor from 'tinycolor2'; + +import Station from './Station'; +import Train from './Train'; +import { distance, pointsAlmostEqual, randomInt, weightedRandom } from './utils'; + +// TODO: define these in a common constants file +const MAX_SPEED = 10.0; +const ACCELERATION = 0.025; +const APPROACH_DISTANCE = 3.0; +const TRAIN_CAPACITY = 50; + +const ctx: Worker = self as any; + +let stations: Station[] = []; +let trains: Train[] = []; + +const initTrains = (numTrains: number, stations: Station[]): Train[] => { + const trains = []; + const stationsWithConnections = stations.filter(station => station.connections.length > 0); + for (let i = 0; i < numTrains; i += 1) { + const originStation = stationsWithConnections[ + Math.floor(Math.random() * stationsWithConnections.length) + ]; + trains.push(new Train( + new Point(originStation.location.x, originStation.location.y), + 0, 0, originStation, undefined, tinycolor('grey').toRgb()), + ); + } + return trains; +}; + +const moveTrains = (trains: Train[], stations: Station[]) => { + for (const train of trains) { + if (train.origin.connections.length === 0) { + // train is stuck at an orphaned station + continue; + } + // choose a destination randomly with a bias towards larger stations + if (train.destination === undefined) { + const otherStations = train.origin.connections.map(conn => conn.station); + const closeStationWeights = otherStations.map(station => station.population); + train.destination = weightedRandom(otherStations, closeStationWeights); + + // board passengers + const boardingPassengers = randomInt(0, Math.min(TRAIN_CAPACITY - train.passengers, + train.origin.population)); + // set or mix train color with the color of new passenger origin + if (train.passengers === 0) { + train.color = train.origin.color; + } else { + train.color = tinycolor.mix( + train.color, + train.origin.color, + Math.round((boardingPassengers / train.passengers) * 100), + ).toRgb(); + } + train.passengers += boardingPassengers; + train.origin.population -= boardingPassengers; + } + + // train reached destination, stop moving and let passengers off + if (pointsAlmostEqual(train.location, train.destination.location)) { + train.speed = 0; + + // average destination color with passenger color weighted by ratio + // (a simulation of culture mixing) + train.destination.color = tinycolor.mix( + train.destination.color, + train.origin.color, + Math.round((train.passengers / train.destination.population) * 100), + ).toRgb(); + + // transfer passengers to destination + const disembarkingPassengers = randomInt(0, train.passengers); + train.destination.population += disembarkingPassengers; + train.passengers -= disembarkingPassengers; + + // prepare for next journey + train.origin = train.destination; + train.destination = undefined; + continue; + } + + const journeyLeft = distance(train.location, train.destination.location); + + if ((train.speed / ACCELERATION) >= ((journeyLeft / train.speed) - APPROACH_DISTANCE) && + train.speed !== ACCELERATION) { + // slowing down + train.speed -= ACCELERATION; + } else if (train.speed < MAX_SPEED) { + // speeding up + train.speed += ACCELERATION; + } + + // advance train + const progress = train.speed / journeyLeft; + train.location.x += ((train.destination.location.x - train.location.x) * progress); + train.location.y += ((train.destination.location.y - train.location.y) * progress); + } +}; + +ctx.addEventListener('message', (event: MessageEvent) => { + if ('initTrains' in event.data) { + const { numTrains } = event.data.initTrains; + stations = event.data.initTrains.stations; + trains = initTrains(numTrains, stations); + ctx.postMessage({ initTrains: trains }); + } else if ('moveTrains' in event.data) { + // trains = event.data.moveTrains.trains; + // stations = event.data.moveTrains.stations; + moveTrains(trains, stations); + ctx.postMessage({ moveTrains: trains }); + } +}); diff --git a/src/transport.ts b/src/transport.ts index b630bba..6e44773 100644 --- a/src/transport.ts +++ b/src/transport.ts @@ -6,18 +6,20 @@ import * as tinycolor from 'tinycolor2'; import Direction from './Direction'; import Line from './Line'; import Station from './Station'; +import StationWorker from 'worker-loader!./Station.worker'; import Train from './Train'; import { distance, pointsAlmostEqual, pointsEqual, randomInt, randomPoint, rangeMap, weightedRandom } from './utils'; +import TrainWorker from 'worker-loader!./Train.worker'; import * as imgNode from './node.png'; import './style.css'; const NODE_RES = 100; -const MAX_SPEED = 10.0; -const ACCELERATION = 0.025; -const APPROACH_DISTANCE = 3.0; +const CONNECTION_RADIUS = Math.floor(Math.sqrt( + Math.pow(window.innerWidth, 2) + Math.pow(window.innerHeight, 2), +) / 8); const TRAIN_CAPACITY = 50; const LINE_CONNECTION_LIMIT = 5; const WORLD_WIDTH = 1000; @@ -29,161 +31,49 @@ const ZOOM_MAX_HEIGHT = 4000; const trainTexts: PIXI.Text[] = []; -const initStations = (numStations: number): Station[] => { - const stations: Station[] = []; - for (let i = 0; i < numStations; i += 1) { - stations.push(new Station( - Station.randomDistantPoint(stations, 30), - randomInt(300, 2000), - tinycolor.random())); - } - return stations; -}; - -const initTrains = (numTrains: number, stations: Station[]): Train[] => { - const trains = []; - const stationsWithConnections = stations.filter(station => station.connections.length > 0); - for (let i = 0; i < numTrains; i += 1) { - const originStation = stationsWithConnections[ - Math.floor(Math.random() * stationsWithConnections.length) - ]; - trains.push(new Train( - new PIXI.Point(originStation.location.x, originStation.location.y), - 0, 0, originStation, undefined, tinycolor('grey')), - ); - } - return trains; -}; - -const initLines = (numLines: number, stations: Station[]): Line[] => { - const lines = []; - for (let i = 0; i < numLines; i += 1) { - let color = tinycolor.random(); - while (color.isDark()) { - color = tinycolor.random(); - } - const stationsWithoutConnections = stations.filter(station => - station.connections.length === 0, - ); - let centralHub: Station; - if (stationsWithoutConnections.length > 0) { - centralHub = Station.largestStation(stationsWithoutConnections); - } else { - centralHub = stations[randomInt(0, stations.length - 1)]; - } - const line = new Line(`line-${i}`, tinycolor.random()); - const stationsLeft = stations.slice(0); - line.connectStations(centralHub, stationsLeft, [], LINE_CONNECTION_LIMIT); - lines.push(line); - } - return lines; -}; - -const moveTrains = (trains: Train[], stations: Station[]) => { - for (const train of trains) { - if (train.origin.connections.length === 0) { - // train is stuck at an orphaned station - continue; - } - // choose a destination randomly with a bias towards larger stations - if (train.destination === undefined) { - const otherStations = train.origin.connections.map(conn => conn.station); - const closeStationWeights = otherStations.map(station => station.population); - train.destination = weightedRandom(otherStations, closeStationWeights); - - // board passengers - const boardingPassengers = randomInt(0, Math.min(TRAIN_CAPACITY - train.passengers, - train.origin.population)); - // set or mix train color with the color of new passenger origin - if (train.passengers === 0) { - train.color = train.origin.color; - } else { - train.color = tinycolor.mix( - train.color, - train.origin.color, - Math.round((boardingPassengers / train.passengers) * 100), - ); - } - train.passengers += boardingPassengers; - train.origin.population -= boardingPassengers; - } - - // train reached destination, stop moving and let passengers off - if (pointsAlmostEqual(train.location, train.destination.location)) { - train.speed = 0; - - // average destination color with passenger color weighted by ratio - // (a simulation of culture mixing) - train.destination.color = tinycolor.mix( - train.destination.color, - train.origin.color, - Math.round((train.passengers / train.destination.population) * 100), - ); - - // transfer passengers to destination - const disembarkingPassengers = randomInt(0, train.passengers); - train.destination.population += disembarkingPassengers; - train.passengers -= disembarkingPassengers; - - // prepare for next journey - train.origin = train.destination; - train.destination = undefined; - continue; - } - - const journeyLeft = distance(train.location, train.destination.location); - - if ((train.speed / ACCELERATION) >= ((journeyLeft / train.speed) - APPROACH_DISTANCE) && - train.speed !== ACCELERATION) { - // slowing down - train.speed -= ACCELERATION; - } else if (train.speed < MAX_SPEED) { - // speeding up - train.speed += ACCELERATION; - } - - // advance train - const progress = train.speed / journeyLeft; - train.location.x += ((train.destination.location.x - train.location.x) * progress); - train.location.y += ((train.destination.location.y - train.location.y) * progress); - } -}; - -const drawStations = (stations: Station[], graphics: PIXI.Graphics) => { - for (const station of stations) { +const drawStations = (stations: Station[], stationLabels: PIXI.Text[], graphics: PIXI.Graphics) => { + stations.forEach((station, i) => { const radius = station.population / 150; - graphics.beginFill(parseInt(station.color.toHex(), 16), 0.5); + const color = tinycolor(station.color); + graphics.beginFill(parseInt(color.toHex(), 16), 0.5); graphics.drawCircle(station.location.x, station.location.y, radius); graphics.endFill(); - station.label.x = station.location.x + radius + 1; - station.label.y = station.location.y + radius + 1; - } + stationLabels[i].x = station.location.x + radius + 1; + stationLabels[i].y = station.location.y + radius + 1; + }); }; -const drawTrains = (trains: Train[], graphics: PIXI.Graphics) => { - for (const train of trains) { +const drawTrains = ( + trains: Train[], + trainLabels: PIXI.Text[], + trainSprites: PIXI.Sprite[], + graphics: PIXI.Graphics, +) => { + trains.forEach((train, i) => { const trainSize = rangeMap(train.passengers, 0, TRAIN_CAPACITY, 1, 5); const scale = trainSize / NODE_RES; - train.sprite.x = train.location.x; - train.sprite.y = train.location.y; - train.sprite.scale.x = scale; - train.sprite.scale.y = scale; - train.sprite.tint = parseInt(train.color.toHex(), 16); - train.label.x = train.location.x + scale + 1; - train.label.y = train.location.y + scale + 1; - } + const color = tinycolor(train.color); + trainSprites[i].x = train.location.x; + trainSprites[i].y = train.location.y; + trainSprites[i].scale.x = scale; + trainSprites[i].scale.y = scale; + trainSprites[i].tint = parseInt(color.toHex(), 16); + trainLabels[i].x = train.location.x + scale + 1; + trainLabels[i].y = train.location.y + scale + 1; + }); }; const drawLines = (stations: Station[], graphics: PIXI.Graphics) => { for (const station of stations) { for (const connection of station.connections) { + const color = tinycolor(connection.line.color); let twoWay = false; for (const conn of connection.station.connections) { if (conn.station === station) { twoWay = true; } } - graphics.lineStyle(twoWay ? 2 : 1, parseInt(connection.line.color.toHex(), 16), 1); + graphics.lineStyle(twoWay ? 2 : 1, parseInt(color.toHex(), 16), 1); graphics.moveTo(station.location.x, station.location.y); graphics.lineTo(connection.station.location.x, connection.station.location.y); } @@ -210,28 +100,85 @@ const run = () => { let stations: Station[] = []; let lines: Line[] = []; - let stationsWithConnections: Station[] = []; - while (stationsWithConnections.length === 0) { - // If all stations are too far away to connect, try generating again - stations = initStations(30); - lines = initLines(4, stations); - stationsWithConnections = stations.filter(station => station.connections.length > 0); - } - const trains = initTrains(50, stations); + let trains: Train[] = []; + const stationLabels: PIXI.Text[] = []; + const trainLabels: PIXI.Text[] = []; + const trainSprites: PIXI.Sprite[] = []; + const stationWorker = new StationWorker(); + const trainWorker = new TrainWorker(); + + stationWorker.postMessage({ initStations: { + connectionRadius: CONNECTION_RADIUS, + height: window.innerHeight, + numLines: 4, + numStations: 30, + width: window.innerWidth, + }}); + stationWorker.onmessage = (event: MessageEvent) => { + stations = event.data.stations; + lines = event.data.lines; + console.log(stations); + console.log(lines); + + trainWorker.postMessage({ initTrains: { + stations, + + numTrains: 50, + }}); + trainWorker.onmessage = (trainEvent: MessageEvent) => { + if ('initTrains' in trainEvent.data) { + trains = trainEvent.data.initTrains; + + // add train sprites + for (const train of trains) { + const sprite = new PIXI.Sprite(PIXI.loader.resources.nodeImg.texture); + sprite.visible = false; + trainSprites.push(sprite); + viewport.addChild(sprite); + } + // Add debug labels + for (const train of trains) { + const label = new PIXI.Text( + `${train.id}`, { + fill: '#AEAEAE', + fontFamily: 'monospace', + fontSize: '12px', + }, + ); + trainLabels.push(label); + viewport.addChild(label); + } + } else if ('moveTrains' in trainEvent.data) { + trains = trainEvent.data.moveTrains; + } + }; + + for (const station of stations) { + const label = new PIXI.Text( + `${station.id}`, { + fill: '#FFA500', + fontFamily: 'monospace', + fontSize: '12px', + }, + ); + stationLabels.push(label); + viewport.addChild(label); + } + }; ticker.stop(); ticker.add((deltaTime) => { stats.begin(); - moveTrains(trains, stations); + trainWorker.postMessage({ moveTrains: {} }); graphics.clear(); graphics.lineStyle(1, 0xFFA500, 1); - drawStations(stations, graphics); + drawStations(stations, stationLabels, graphics); graphics.lineStyle(1, 0xAEAEAE, 1); - drawTrains(trains, graphics); + drawTrains(trains, trainLabels, trainSprites, graphics); drawLines(stations, graphics); @@ -240,17 +187,6 @@ const run = () => { ticker.start(); viewport.addChild(graphics); - // add train sprites - for (const train of trains) { - viewport.addChild(train.sprite); - } - // Add debug labels - for (const train of trains) { - viewport.addChild(train.label); - } - for (const station of stations) { - viewport.addChild(station.label); - } document.body.appendChild(app.view); app.stage.addChild(viewport); viewport.drag().pinch().wheel().clampZoom({ diff --git a/src/utils.ts b/src/utils.ts index 08be619..0431bbb 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,4 @@ -import * as PIXI from 'pixi.js'; +import Point from 'pixi.js/lib/core/math/Point'; const EPSILON = 1.0; @@ -19,20 +19,20 @@ export const weightedRandom = (choices: any[], weights: number[]): any => { } }; -export const randomPoint = () => ( - new PIXI.Point(randomInt(0, window.innerWidth), randomInt(0, window.innerHeight)) +export const randomPoint = (height: number, width: number): Point => ( + new Point(randomInt(0, width), randomInt(0, height)) ); -export const pointsEqual = (pointA: PIXI.Point, pointB: PIXI.Point): boolean => ( +export const pointsEqual = (pointA: Point, pointB: Point): boolean => ( (pointA.x === pointB.x && pointA.y === pointB.y) ); -export const pointsAlmostEqual = (pointA: PIXI.Point, pointB: PIXI.Point): boolean => ( +export const pointsAlmostEqual = (pointA: Point, pointB: Point): boolean => ( Math.abs(pointA.x - pointB.x) < EPSILON && Math.abs(pointA.y - pointB.y) < EPSILON ); -export const distance = (pointA: PIXI.Point, pointB: PIXI.Point): number => { +export const distance = (pointA: Point, pointB: Point): number => { const distX = pointA.x - pointB.x; const distY = pointA.y - pointB.y; return Math.sqrt((distX * distX) + (distY * distY)); @@ -43,10 +43,10 @@ export const rangeMap = (num: number, inMin: number, inMax: number, (num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin ); -export const angleRadians = (pointA: PIXI.Point, pointB: PIXI.Point): number => ( +export const angleRadians = (pointA: Point, pointB: Point): number => ( Math.atan2(-(pointB.x - pointA.x), pointB.y - pointA.y) ); -export const angleDegrees = (pointA: PIXI.Point, pointB: PIXI.Point): number => ( +export const angleDegrees = (pointA: Point, pointB: Point): number => ( 180 + angleRadians(pointA, pointB) * (180 / Math.PI) ); diff --git a/typings/custom.d.ts b/typings/custom.d.ts index e2937d4..469205c 100644 --- a/typings/custom.d.ts +++ b/typings/custom.d.ts @@ -1 +1,17 @@ declare module '*.png'; + +declare module 'worker-loader!*' { + class WebpackWorker extends Worker { + constructor(); + } + + export default WebpackWorker; +} + +declare module 'pixi.js/lib/core/math/Point' { + export default PIXI.Point; +} + +declare module 'pixi.js/lib/core/text/Text' { + export default PIXI.Text; +}