4TYJCGT4MTCAH7GSJJWFQPPHZNAUQZDEIZYT365EYTMXS7D2MTNAC K6GXDBTYCUEF3GGLL46RTYJTH7DF6C2F5XIJK74FSQFVJZUDL3UAC JGVAE75MDL2H7Y5GP4IYGSMPN4P6DZY3JKDXPALRSGBMOD4LSTDAC O65A3D4ZQZ4EVMU65B5HRUHYTMZXAIKETO4ZGLY2HWJC57ANMJQAC Q7BHQXOCHVUWZCW23EA64XGOGC4TNGCNXUCZCNUAKWBF53QPVHMQC ZHOSSPNKGFIKSFPDXCGLMSYMMX2J433VU2BUUWBKUH7TOLQUBSPQC 5BA7VZ3D36S2TC7NZ64R3O364TGXPY5BJUJTGCFZHWZ6JWAXJMUQC JG36CDUKVUWJT25PJVMWKWI4KFRHM24PFBKPXXRY3D2XVDKUVI7QC OEKGYL6XZFMUSQPDFFMGGNAPDDKNW4XJNY6ALYQILBLNCRD5BFRAC XF75MWE3S7HPZXDNR5A5BCRAYO3AYCPUQ4KS6JAAH5DWJRYBKJTQC AAKN4XJLZ2GARZMUFYX3CJZKYHTRRZDYNTFRLMY7VPAY7K6W4N3QC OYNCMT7YDCHK7TFRZDVCMODYMYXRQKK3AU7EOZU7KRA76QGKI3EQC 627ZCA4JTONT2DQPA2FU44FRSCXZGA6P3YAGTPL76K3UJVYGMFWAC 2EGPRWETVM2XPSRMGYM25Y46RXPW7IOCN6MDIV6POCPHNOEGSMHAC NQA6YRMRCF7LIHPYWLC355FPCH7CYA3QKSKQHSNJHA2XHOCWZXCAC NRPN6TDZ3VMPQTBNVNMMIXPTPVNEE2QZFKA74VOOOBKJM7WRVPQQC ZVGVCWXHWI2VH5RIC7NCN5P6YQKTLABSRSNJ735SNACXHEFY53HAC M4DT5MAD3TATSVAT3MFNABHONWXOW443XD5W6DGEVVYHVITXVBDAC Q34G6QFD5YTQALLNF2RMSYDU22GLZ6J4QRCROAXXVQ2WOR3Z4NRAC LAS3JSYVTEQFJ5N4XAIKX4QADU3BU3UO7NVMZ4FYIRFPKM2UCCTQC F63ZRAIJZFIF33IVOHHLXHYZ4SYGQJ5Y7CLTKZGBPVBHNTPR7IYAC X52UWGP3IMBHZXBBWERRYJ2C2SMQACCEQCO4WAIHVGMP3PKTX5AQC 5PWH6EJMJE5C6FODNDCF45BHKI27WGKDJ5ZJXRSB2JDELPE3AZSQC VUNJRHFRDXPWZEQMOGKWAY2Z3ZZJKFI4JPI6AWQRGMY2OGULQS5AC 62QKIMRH7GBBUQITPYG7FKXMNCQ6RY75G2T7V56G3VFYCEE6DHKAC KHAKSWQANUZL7B3EYF6GWTDGSUR2WVZGU5BPPI6OKYIPCD3QMWAQC D56DDDEJPJZ2PA55BSYVLTZHVBLNPK2STRYYQSMPFCPJASEXVFXQC I7GDRUZLCHCLM7UCTUCYC46TL24P4HYAYXUUS4IHVRIPN4MUNBIAC THNMNMVRZQVPZTEXHIK6WGYN3QDEFPKFOVOCB5HTWCYC5BOBYQ5AC 3ZWCUXFJKMBK2E7LB3CD6CAMLA365TY2UM4YOY5LJMIUU7A5EP2AC 2U4FPBRH4POPKCDYHCAI6JBOM4T3T36EBTCHJUAEE2RSAWNTQ6FQC QU7JVYXAGGNN4754FJAT7HFTSFHLLIWWNIVYBMCBQJVSLTB5RNIQC VQJBTLNEKPLH62WALLZABSTLHLEMS4SFVEVFUOXJ4EFABHISYF5QC MVMGDCF5YC4OJC2OACVZCDJATCYQPLWX3P2PCOHIR7AHFKTMALUAC HGXJZUEJA2SU6AATVCYBQXOKYF3ATULY375NL5ZZWRBWJYDHKJ4QC FXYPURO7GWFOWZMZ4HP7SMLAXSZMQAON6D6LTGSKPYST52RJYXIAC FOSCN7AFGTTDRJRLAIIRMI2D5JYXXCKMYMCKOAVVT6WV2PAGUJOQC export type HighwayConfig = {};const defaultConfig: HighwayConfig = {};
import * as Pixi from "pixi.js";import { Container } from "pixi.js";import { Pair } from "../lib/util/data_structures/pair";import { Rect } from "../lib/util/geometry/rect";import { IVector2, Vector2 } from "../lib/util/geometry/vector2";export type RenderRectsConfig = {containerHeightProportion: number;aspectRatio1: number;downscaleRatio12: number;aspectRatio2?: number;downscaleRatio23?: number;aspectRatio3?: number;circleSize: number;circleOffColor: number;circleOnColor: number;circleHoverColor: number;circleFillColor: number;};export class RenderRects {private config: RenderRectsConfig = {containerHeightProportion: 0.9,aspectRatio1: 1.6,aspectRatio3: 1.6,downscaleRatio12: 0.75,downscaleRatio23: 0.35,circleSize: 6,circleOnColor: 0x030303,circleOffColor: 0xcecece,circleHoverColor: 0x000000,circleFillColor: 0xd3d3d3,borderOffColor: 0xefefef,borderOnColor: 0xbcdebc,borderThickness: 2,centerToEdgeBorderRatio2: 1.2,centerToEdgeBorderRatio3: 1.0,cornerCompression1: 0.08,cornerCompression2: 0.2,cornerCompression3: 0.3,debugHasRectBorder: false,debugRandomOn: true,};private containerRect!: Rect;private stage!: Container;constructor(stage: Container,containerRect: Rect,config?: RenderRectsConfig) {this.stage = stage;this.containerRect = containerRect;this.config = Object.assign({}, this.config, config || {});}public drawFirst() {const newHeight =this.containerRect.height * this.config.containerHeightProportion;const newRect = this.containerRect.withScale({height: newHeight,width: newHeight * this.config.aspectRatio1,});}private nestRectPair(original: Rect,downscaleRatio: number,newAspectRatio: number,centerToEdgeBorderRatio: number): Pair<Rect, Rect> {const longSide = Math.min(original.height, original.width) * downscaleRatio;const shortSide = longSide / newAspectRatio;const remaining = Math.max(original.height, original.width) - 2 * shortSide;const middleGap =(remaining / (2 + centerToEdgeBorderRatio)) * centerToEdgeBorderRatio;const offset = middleGap / 2 + shortSide / 2;if (original.height < original.width) {const newHeight = longSide;const newWidth = shortSide;const leftCenter = new Vector2(original.centerX - offset,original.centerY);const rightCenter = new Vector2(original.centerX + offset,original.centerY);return new Pair<Rect, Rect>(Rect.FromCenter({center: leftCenter,dimensions: new Vector2(newWidth, newHeight),}),Rect.FromCenter({center: rightCenter,dimensions: new Vector2(newWidth, newHeight),}));} else {const newHeight = shortSide;const newWidth = longSide;const topCenter = new Vector2(original.centerX,original.centerY - offset);const bottomCenter = new Vector2(original.centerX,original.centerY + offset);return new Pair<Rect, Rect>(Rect.FromCenter({center: topCenter,dimensions: new Vector2(newWidth, newHeight),}),Rect.FromCenter({center: bottomCenter,dimensions: new Vector2(newWidth, newHeight),}));}}private drawRect(rect: Rect,hasBorder: boolean,cornerCompressionRatio: number) {const corners = rect.withScale({width:rect.width -(cornerCompressionRatio * (3 * rect.width + rect.height)) / 4,height:rect.height -(cornerCompressionRatio * (rect.width + 3 * rect.height)) / 4,});const midpoints = {left: new Vector2(rect.left, rect.centerY),right: new Vector2(rect.right, rect.centerY),top: new Vector2(rect.centerX, rect.top),bottom: new Vector2(rect.centerX, rect.bottom),};}private drawCorners(rect: Rect) {this.drawCircleAt(rect.topLeft);this.drawCircleAt(rect.topRight);this.drawCircleAt(rect.bottomLeft);this.drawCircleAt(rect.bottomRight);}public drawLine(p1: IVector2, p2: IVector2) {const graphics = new Pixi.Graphics();// graphics.position.set(p1.x, p1.y);if (this.config.debugRandomOn && Math.random() < 0.5) {graphics.lineStyle(this.config.borderThickness,this.config.borderOnColor,1);} else {graphics.lineStyle(this.config.borderThickness,this.config.borderOffColor,1);}graphics.moveTo(p1.x, p1.y);graphics.lineTo(p2.x, p2.y);this.stage.addChild(graphics);}public drawCircleAt(point: IVector2): IVector2 {const graphics = new Pixi.Graphics();if (this.config.debugRandomOn && Math.random() < 0.5) {graphics.lineStyle(1, this.config.circleOnColor, 1);} else {graphics.lineStyle(1, this.config.circleOffColor, 1);}graphics.beginFill(this.config.circleFillColor, 1);graphics.drawCircle(point.x, point.y, this.config.circleSize);graphics.endFill();this.stage.addChild(graphics);}}return point;if (hasBorder) {const graphics = new Pixi.Graphics();graphics.lineStyle(this.config.borderThickness,this.config.borderOffColor,1);graphics.drawRect(rect.x, rect.y, rect.width, rect.height);this.stage.addChild(graphics);}this.drawLine(corners.topLeft, midpoints.left);this.drawLine(corners.topLeft, midpoints.top);this.drawLine(corners.topRight, midpoints.right);this.drawLine(corners.topRight, midpoints.top);this.drawLine(corners.bottomLeft, midpoints.left);this.drawLine(corners.bottomLeft, midpoints.bottom);this.drawLine(corners.bottomRight, midpoints.right);this.drawLine(corners.bottomRight, midpoints.bottom);this.drawCorners(corners);Object.values(midpoints).map((p) => this.drawCircleAt(p));this.drawRect(newRect, hasBorder, this.config.cornerCompression1 || 0);const layer2 = this.nestRectPair(newRect,this.config.downscaleRatio12,this.config.aspectRatio2 || this.config.aspectRatio1,this.config.centerToEdgeBorderRatio2);this.drawRect(layer2.first,hasBorder,this.config.cornerCompression2 || this.config.cornerCompression1 || 0);this.drawRect(layer2.second,hasBorder,this.config.cornerCompression2 || this.config.cornerCompression1 || 0);const layer3 = new Pair(this.nestRectPair(layer2.first,this.config.downscaleRatio23 || this.config.downscaleRatio12,this.config.aspectRatio3 ||this.config.aspectRatio2 ||this.config.aspectRatio1,this.config.centerToEdgeBorderRatio3 ||this.config.centerToEdgeBorderRatio2),this.nestRectPair(layer2.second,this.config.downscaleRatio23 || this.config.downscaleRatio12,this.config.aspectRatio3 ||this.config.aspectRatio2 ||this.config.aspectRatio1,this.config.centerToEdgeBorderRatio3 ||this.config.centerToEdgeBorderRatio2));this.drawRect(layer3.first.first,hasBorder,this.config.cornerCompression3 ||this.config.cornerCompression2 ||this.config.cornerCompression1 ||0);this.drawRect(layer3.second.first,hasBorder,this.config.cornerCompression3 ||this.config.cornerCompression2 ||this.config.cornerCompression1 ||0);this.drawRect(layer3.first.second,hasBorder,this.config.cornerCompression3 ||this.config.cornerCompression2 ||this.config.cornerCompression1 ||0);this.drawRect(layer3.second.second,hasBorder,this.config.cornerCompression3 ||this.config.cornerCompression2 ||this.config.cornerCompression1 ||0);const hasBorder = this.config.debugHasRectBorder;/*** Draws a '=' oriented rectangle, 2 'O' oriented nested, and then 4 '=' further-nested.*/borderOffColor: number;borderOnColor: number;borderThickness: number;centerToEdgeBorderRatio2: number;centerToEdgeBorderRatio3?: number;cornerCompression1?: number;cornerCompression2?: number;cornerCompression3?: number;debugHasRectBorder: boolean;debugRandomOn: boolean;
import { HashState } from "../lib/util/random";export type Topo3Frames = {out: TopoFrame;in0: TopoFrame;in1: TopoFrame;};export class TopoTemplate {public id!: string;public orientation!: FrameOrientation;public frames!: Topo3Frames;public nodes: TopoNode[] = [];constructor(id: string, frames: Topo3Frames, random: HashState) {this.id = id;this.frames = frames;this.orientation = frames.out.orientation;// start constructing the guy// opposite cornersconnectCorner(this.frames.out.corners.I, this.frames.in0.corners.I);connectCorner(this.frames.out.corners.D, this.frames.in1.corners.D);// the other 2 outside cornersconnectCorner(this.frames.out.corners.S, this.frames.in0.corners.L);connectCorner(this.frames.out.corners.L, this.frames.in1.corners.S);// center cornersconnectCorner(this.frames.in0.corners.S, this.frames.in1.corners.I);connectCorner(this.frames.in0.corners.D, this.frames.in1.corners.L);// make some midpoints// connect some midpoints// out.IS , in0.IL// in0.SD, in1.IL// in1.SD, out.LD// out.IL, in0.IS, in1.IS// out.SD, in0.LD, in1.LD}}export type FrameOrientation = "=" | "0";export class TopoFrame {public id!: string;public orientation!: FrameOrientation;public corners!: {I: TopoNode;L: TopoNode;S: TopoNode;D: TopoNode;};/**** I ----- L I - S* | | | |* S ----- D or | |* | |* L - D**/constructor(id: string, orientation: FrameOrientation) {this.id = id;this.corners = {I: new TopoNode(id + "-NI"),L: new TopoNode(id + "-NL"),S: new TopoNode(id + "-NS"),D: new TopoNode(id + "-ND"),};this.orientation = orientation;}}export class TopoNode {public id!: string;constructor(id: string) {this.id = id;}}function connectCorner(x: any, y: any) {}doStuff() {}
// put a text thingy in the top rightlet textFpsHud = new Pixi.Text('');this.app.ticker.add(() => {textFpsHud.text = this.fpsTracker.getFpsString() + " FPS\n" + this.fpsTracker.getUpsString() + " UPS";})textFpsHud.x = 600;textFpsHud.y = 200;this.fixedCameraStage.addChild(textFpsHud);
/*** Draws a full skill tree at the default zoom level.*/public drawAll() {// get the first 3 layers' configurations// render the top layer points// renderLayerPoints(layer[0], { rect: null })// render the next layer// render the intermediate connections// render the final layer// render the intermediate connections
public resize(windowWidth: number, windowHeight: number) {// we dont want to take up the whole windowthis.app.renderer.resize(windowHeight * 0.75, windowHeight * 0.75);// causes the game to be rescaled when window is resized// this.app.stage.width = windowHeight * 0.75;// this.app.stage.height = windowHeight * 0.75;// this.app.stage.x = windowHeight * 0.375;this.actionStage.pivot.x = (this.app.screen.width - this.config.originalWidth) * -0.5;this.actionStage.pivot.y = (this.app.screen.height - this.config.originalHeight) * -0.5;this.onResize.map(fn => fn());// this.app.stage.pivot.x = 0;
// this.renderRects.drawFirst();this.pixiExample();
// put a text thingy in the top rightlet textFpsHud = new Pixi.Text('', {fontFamily: 'PixelMix',// align: 'right'});this.app.ticker.add(() => {textFpsHud.text = this.fpsTracker.getFpsString() + " FPS\n" + this.fpsTracker.getUpsString() + " UPS";})textFpsHud.x = this.app.screen.width;this.onResize.push(() => { textFpsHud.x = this.app.screen.width; });textFpsHud.y = 0;textFpsHud.anchor.x = 1; // right justifythis.fixedCameraStage.addChild(textFpsHud);
// backdrop.interactiveChildren = true;// backdrop.zIndex = 31;// backdrop.buttonMode = true;// backdrop.drawRect(0, 0, this.config.canvasWidth, this.config.canvasHeight);backdrop.drawRect(-10000, -10000, 20000, 20000);// backdrop.addListener('pointerupoutside', e => {// console.log('clickable hud', e)// })// backdrop.addListener('pointerup', (e) => {// // window.alert('up from clickable hud');// console.log('clickable hud', e)// })
// backdrop.interactiveChildren = true; // not sure what this does// backdrop.buttonMode = true; // changes the mouse cursor on hover to pointer; not desirable for the entire backdropbackdrop.drawRect(0, 0, this.app.screen.width, this.app.screen.height);this.onResize.push(() => {backdrop.width = this.app.screen.width;backdrop.height = this.app.screen.height;});// backdrop.drawRect(-10000, -10000, 30000, 30000);
reticle.drawCircle(this.config.canvasWidth / 2, this.config.canvasHeight / 2, 10);
reticle.drawCircle(0, 0, 6);reticle.x = this.app.screen.width / 2;reticle.y = this.app.screen.height / 2;this.onResize.push(() => {reticle.x = this.app.screen.width / 2;reticle.y = this.app.screen.height / 2;})
public pixiExample() {// Taken from https://pixijs.io/examples/#/demos-basic/container.jsconst container = new Pixi.Container();this.actionStage.addChild(container);// Create a new textureconst texture = Pixi.Texture.from(bunny);window.alert("doing bunny stuff")// Create a 5x5 grid of bunniesfor (let i = 0; i < 25; i++) {const bunny = new Pixi.Sprite(texture);bunny.anchor.set(0.5);bunny.x = (i % 5) * 40;bunny.y = Math.floor(i / 5) * 40;container.addChild(bunny);bunny.interactive = true;// bunny.addListener('pointerdown', () => {// window.alert('clicked bunny #' + i);// });}// Move container to the centercontainer.x = this.app.screen.width / 2;container.y = this.app.screen.height / 2;// Center bunny sprite in local container coordinatescontainer.pivot.x = container.width / 2;container.pivot.y = container.height / 2;// Listen for animate updatethis.app.ticker.add((delta) => {// rotate the container!// use delta to create frame-independent transformcontainer.rotation -= 0.01 * delta;});
createBunnyExample({ parent: this.actionStage, ticker: this.app.ticker, x: this.app.screen.width / 2, y: this.app.screen.height / 2 });