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 corners
connectCorner(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 corners
connectCorner(this.frames.out.corners.S, this.frames.in0.corners.L);
connectCorner(this.frames.out.corners.L, this.frames.in1.corners.S);
// center corners
connectCorner(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 right
let 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 window
this.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 right
let 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 justify
this.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 backdrop
backdrop.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.js
const container = new Pixi.Container();
this.actionStage.addChild(container);
// Create a new texture
const texture = Pixi.Texture.from(bunny);
window.alert("doing bunny stuff")
// Create a 5x5 grid of bunnies
for (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 center
container.x = this.app.screen.width / 2;
container.y = this.app.screen.height / 2;
// Center bunny sprite in local container coordinates
container.pivot.x = container.width / 2;
container.pivot.y = container.height / 2;
// Listen for animate update
this.app.ticker.add((delta) => {
// rotate the container!
// use delta to create frame-independent transform
container.rotation -= 0.01 * delta;
});
createBunnyExample({ parent: this.actionStage, ticker: this.app.ticker, x: this.app.screen.width / 2, y: this.app.screen.height / 2 });