Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

Commit

Permalink
feat: land amount display
Browse files Browse the repository at this point in the history
  • Loading branch information
jwcub committed May 2, 2024
1 parent 78a802c commit d1021b9
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 12 deletions.
2 changes: 2 additions & 0 deletions app/components/layout/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export default function Navbar() {
</Flex>
<Flex align="center" justify="start" flex={1}>
<Box
as={Link}
display={{ base: "none", sm: "block" }}
pl={{ base: 3, md: 0 }}
color="gray.800"
Expand All @@ -79,6 +80,7 @@ export default function Navbar() {
_dark={{
color: "white"
}}
to="/"
>
polygen
</Box>
Expand Down
21 changes: 21 additions & 0 deletions app/game/gm/gm.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import _ from "lodash";

import { Land } from "./land";
import { Matrix } from "./matrix";
import type { Pos } from "./matrix";
Expand Down Expand Up @@ -50,6 +52,25 @@ export class Gm extends Matrix<Land> {
return new this(mode, Matrix.default(height, width, new Land()));
}

/**
* Creates a random gm with given height and width.
*/
static random(mode: Gm["mode"], height: number, width: number) {
return new this(
mode,
Matrix.defaultWith(
height,
width,
() =>
new Land(
_.random(0, 20),
_.sample(Object.values(Land.Type))!,
_.random(1, 9) * Math.pow(10, _.random(0, 6))
)
)
);
}

/**
* Exports the Gm to JSON.
*/
Expand Down
108 changes: 102 additions & 6 deletions app/game/view/baseRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import _ from "lodash";
import type { PointData } from "pixi.js";
import { Application, Graphics } from "pixi.js";
import { BitmapText, BitmapFont, Application, Graphics } from "pixi.js";

import type { Gm } from "../gm/gm";
import type { Pos } from "../gm/matrix";
import { Matrix } from "../gm/matrix";

import { R } from "./constants";
import { R, TEXT_COLOR, TEXT_SIZE } from "./constants";
import { formatLargeNumber } from "./utils";

/**
* Basic renderer without mode support.
Expand All @@ -15,6 +17,11 @@ export default abstract class BaseRenderer {
graphics = new Graphics();
gm: Gm;

/**
* Land amounts.
*/
texts = new Matrix<BitmapText>();

protected constructor(gm: Gm) {
this.gm = gm;
}
Expand All @@ -36,14 +43,33 @@ export default abstract class BaseRenderer {

this.app.stage.addChild(this.graphics);

BitmapFont.install({
style: {
fontWeight: "bold",
fontSize: TEXT_SIZE,
fill: TEXT_COLOR
},
name: "text",
chars: [["0", "9"], "kme.- "]
});

// Zoom support.
canvas.onwheel = event => {
event.preventDefault();

const newScale = this.app.stage.scale.x + (event.deltaY > 0 ? -0.1 : 0.1);
const oldScale = this.app.stage.scale.x;
const newScale = oldScale + (event.deltaY > 0 ? -0.1 : 0.1);

if (newScale >= 0.5 && newScale <= 2) {
this.app.stage.scale.set(newScale);

const rate = newScale / oldScale;

const width = this.app.canvas.width,
height = this.app.canvas.height;

this.app.stage.x = width / 2 - rate * (width / 2 - this.app.stage.x);
this.app.stage.y = height / 2 - rate * (height / 2 - this.app.stage.y);
}
};

Expand Down Expand Up @@ -80,6 +106,8 @@ export default abstract class BaseRenderer {
document.onpointermove = document.onpointerup = null;
};
};

this.reset();
}

/**
Expand All @@ -92,6 +120,16 @@ export default abstract class BaseRenderer {
*/
abstract topLeft(pos: Pos): PointData;

/**
* Gets the center position of the polygon at the given pos. (R = 1)
*/
abstract center(pos: Pos): PointData;

/**
* Gets the maximum width of a text. (R = 1)
*/
abstract maxTextWidth(): number;

/**
* Destroys the renderer and its resources.
*/
Expand Down Expand Up @@ -121,9 +159,67 @@ export default abstract class BaseRenderer {
}

/**
* Updates the graphics of all polygons.
* Updates the text of the polygon at the given pos.
*/
updateText(pos: Pos) {
const text = this.texts.get(pos);
const land = this.gm.get(pos);

text.text = land.amount.toString();

const maxWidth = this.maxTextWidth() * R;

if (text.width > maxWidth) {
text.text = formatLargeNumber(land.amount);
}

const { x, y } = this.center(pos);
const width = text.width;
const height = text.height;

text.x = x * R - width / 2;
text.y = y * R - height / 2;
}

/**
* Updates all polygons.
*/
updateAll() {
this.gm.positions().forEach(pos => {
this.updateGraphics(pos);
this.updateText(pos);
});
}

/**
* Resets the renderer to its initial state.
*/
updateGraphicsAll() {
this.gm.positions().forEach(pos => this.updateGraphics(pos));
reset() {
// Clear graphics.
this.graphics.clear();

// Remove texts.
for (const text of this.texts.flat()) {
this.app.stage.removeChild(text);
text.destroy();
}

// Add texts.
this.texts = Matrix.defaultWith(
this.gm.height,
this.gm.width,
() =>
new BitmapText({
text: "",
style: { fontFamily: "text", fontSize: TEXT_SIZE }
})
);

for (const text of this.texts.flat()) {
this.app.stage.addChild(text);
}

// Redraw everything.
this.updateAll();
}
}
3 changes: 3 additions & 0 deletions app/game/view/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export const R = 30;

export const TEXT_SIZE = 15;
export const TEXT_COLOR = 0xffffff;
37 changes: 37 additions & 0 deletions app/game/view/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,41 @@ export default class Renderer extends BaseRenderer {
}
}
}

center([i, j]: Pos) {
switch (this.gm.mode) {
case Gm.Mode.Hexagon: {
return {
x: 1 + 1.5 * (j - 1),
y: j % 2 === 0 ? Math.sqrt(3) * i : Math.sqrt(3) * (i - 0.5)
};
}
case Gm.Mode.Square: {
return {
x: Math.sqrt(2) * (j - 0.5),
y: Math.sqrt(2) * (i - 0.5)
};
}
case Gm.Mode.Triangle: {
return {
x: (Math.sqrt(3) / 2) * j,
y: 1.5 * (i - 1) + ((i + j) % 2 === 0 ? 1 : 0.5)
};
}
}
}

maxTextWidth() {
switch (this.gm.mode) {
case Gm.Mode.Hexagon: {
return 2;
}
case Gm.Mode.Square: {
return Math.sqrt(2);
}
case Gm.Mode.Triangle: {
return Math.sqrt(3) / 2;
}
}
}
}
30 changes: 30 additions & 0 deletions app/game/view/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Formats a large number.
*/
export function formatLargeNumber(n: number): string {
let text;

if (n < 0) {
return "-" + formatLargeNumber(-n);
} else if (n === 0) {
return "";
} else if (n < 1000) {
text = String(n);
} else if (n < 10000) {
text = String(Math.round(n / 100) / 10) + "k";
} else if (n < 100000) {
text = String(Math.round(n / 1000)) + "k";
} else if (n < 10000000) {
const millions = Math.round(n / 100000) / 10;
text =
(millions < 1 ? millions.toString().substring(1) : millions.toString()) +
"m";
} else if (n < 100000000) {
text = String(Math.round(n / 1000000)) + "m";
} else {
const power = Math.round(Math.log10(n));
text = `${Math.round(n / Math.pow(10, power))}e${power}`;
}

return text;
}
9 changes: 3 additions & 6 deletions app/routes/map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function Map() {
const renderer = useRef<Renderer | null>(null);

function generateGm() {
return Gm.empty(
return Gm.random(
_.sample(Object.values(Gm.Mode))!,
_.random(2, 5) * 10,
_.random(2, 5) * 10
Expand All @@ -30,9 +30,7 @@ export default function Map() {

const _renderer = new Renderer(gm);

_renderer.init(canvas.current!).then(() => {
_renderer.updateGraphicsAll();
});
void _renderer.init(canvas.current!);

renderer.current = _renderer;

Expand All @@ -59,9 +57,8 @@ export default function Map() {
return;
}

renderer.current.graphics.clear();
renderer.current.gm = generateGm();
renderer.current.updateGraphicsAll();
renderer.current.reset();
}}
/>
</Center>
Expand Down

0 comments on commit d1021b9

Please sign in to comment.