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

Commit

Permalink
feat: palette generation
Browse files Browse the repository at this point in the history
  • Loading branch information
jwcub committed May 12, 2024
1 parent b83f36d commit e38f5e4
Show file tree
Hide file tree
Showing 10 changed files with 703 additions and 713 deletions.
13 changes: 8 additions & 5 deletions app/game/gm/gm.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import _ from "lodash";

import { STANDARD_COLOR } from "../view/constants";

import { Land } from "./land";
import { Matrix } from "./matrix";
import type { Pos } from "./matrix";
import { Palette } from "./palette";

/**
* Gm extended from a Matrix of Lands, which knows its mode and
Expand Down Expand Up @@ -55,22 +54,26 @@ export class Gm extends Matrix<Land> {
}

/**
* Creates a random gm with given height and width.
* Creates a random gm and a palette with given height and width.
*/
static random(mode: Gm["mode"], height: number, width: number) {
return new this(
const n = _.random(10, 50);
const palette = Palette.colors(n);
const gm = new this(
mode,
Matrix.defaultWith(
height,
width,
() =>
new Land(
_.random(0, STANDARD_COLOR.length - 1),
_.random(0, n),
_.sample(Object.values(Land.Type))!,
_.random(1, 9) * Math.pow(10, _.random(0, 9))
)
)
);

return { gm, palette };
}

/**
Expand Down
10 changes: 10 additions & 0 deletions app/game/gm/palette.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { expect, it } from "vitest";

import { Palette } from "./palette";

it("creates a palette", () => {
const palette = Palette.colors(20);

expect(palette).toHaveLength(21);
expect(palette[0]).toBe(0x808080);
});
28 changes: 28 additions & 0 deletions app/game/gm/palette.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import generateColors from "iwanthue";

/**
* A palette consisting of different standard colors.
*/
export class Palette extends Array<number> {
/**
* Not meant to be called directly.
*/
constructor(...args: ConstructorParameters<typeof Array<number>>) {
super(...args);
}

/**
* Creates a Palette with (n + 1) standard colors.
*
* The first color is fixed to grey.
*/
static colors(n: number) {
return new Palette(
0x808080,
...generateColors(n, {
colorSpace: [0, 360, 25, 85, 45, 70],
clustering: "force-vector"
}).map(color => parseInt(color.substring(1), 16))
);
}
}
24 changes: 17 additions & 7 deletions app/game/view/baseRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type { Gm } from "../gm/gm";
import { Land } from "../gm/land";
import type { Pos } from "../gm/matrix";
import { Matrix } from "../gm/matrix";
import type { Palette } from "../gm/palette";

import {
BORDER_COLOR,
Expand All @@ -35,7 +36,6 @@ import {
MOBILE_ZOOM_RATE,
MOUNTAIN_COLOR,
R,
STANDARD_COLOR,
TEXT_COLOR,
TEXT_SIZE,
UNKNOWN_COLOR
Expand All @@ -51,6 +51,7 @@ export default abstract class BaseRenderer {
app = new Application();
graphics = new Graphics();
gm: Gm;
palette: Palette;

/**
* Land types.
Expand Down Expand Up @@ -84,8 +85,9 @@ export default abstract class BaseRenderer {
*/
selected?: Pos;

protected constructor(gm: Gm) {
protected constructor(gm: Gm, palette: Palette) {
this.gm = gm;
this.palette = palette;
}

/**
Expand All @@ -100,7 +102,13 @@ export default abstract class BaseRenderer {
powerPreference: "high-performance",
canvas,
height,
width
width,
eventFeatures: {
move: false,
globalMove: false,
click: false,
wheel: false
}
});

this.app.stage.addChild(this.graphics);
Expand Down Expand Up @@ -359,7 +367,7 @@ export default abstract class BaseRenderer {
updateGraphics(pos: Pos) {
const land = this.gm.get(pos);

let fillColor = STANDARD_COLOR[land.color];
let fillColor = this.palette[land.color];

if (!land.visible()) {
fillColor = UNKNOWN_COLOR;
Expand Down Expand Up @@ -456,10 +464,14 @@ export default abstract class BaseRenderer {

// Clear graphics.
this.graphics.clear();
this.graphics.interactiveChildren = false;
this.graphics.eventMode = "none";

// Remove images.
this.imageContainer.destroy({ children: true });
this.imageContainer = new Container({ isRenderGroup: true });
this.imageContainer.interactiveChildren = false;
this.imageContainer.eventMode = "none";
this.app.stage.addChild(this.imageContainer);

// Remove texts.
Expand Down Expand Up @@ -493,7 +505,6 @@ export default abstract class BaseRenderer {
// Add texts.
this.texts = Matrix.defaultWith(this.gm.height, this.gm.width, () => {
const text = new BitmapText({
text: "",
style: { fontFamily: "text", fontSize: TEXT_SIZE }
});
text.interactiveChildren = false;
Expand All @@ -512,6 +523,7 @@ export default abstract class BaseRenderer {
for (const pos of this.hitAreas.positions()) {
const hitArea = this.hitAreas.get(pos);
hitArea.interactiveChildren = false;
hitArea.eventMode = "static";

const { x, y } = this.topLeft(pos);
hitArea.position.set(x * R, y * R);
Expand All @@ -521,8 +533,6 @@ export default abstract class BaseRenderer {
);

this.hitAreaContainer.addChild(hitArea);

hitArea.eventMode = "static";
}

// Redraw everything.
Expand Down
6 changes: 0 additions & 6 deletions app/game/view/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ export const MOBILE_ZOOM_RATE = 0.007;

export const BORDER_COLOR = 0xffffff;

export const STANDARD_COLOR = [
0x808080, 0xff0000, 0x4363d8, 0x008000, 0x008080, 0xf58231, 0xf032e6,
0x800080, 0x800000, 0xb09f30, 0x9a6324, 0x0000ff, 0x483d8b, 0xd81b60,
0x03a9f4, 0x9c27b0, 0x4caf50, 0x5c6bc0, 0xff5722, 0x673ab7, 0xcddc39,
0xffc107, 0x9acd32, 0xff1493, 0x3e2cbb, 0xff6347
];
export const EMPTY_COLOR = 0xdcdcdc;
export const MOUNTAIN_COLOR = 0xbbbbbb;
export const UNKNOWN_COLOR = 0x393939;
5 changes: 3 additions & 2 deletions app/game/view/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Gm } from "../gm/gm";
import type { Pos } from "../gm/matrix";
import type { Palette } from "../gm/palette";

import BaseRenderer from "./baseRenderer";

/**
* Full-featured renderer with mode support and interaction.
*/
export default class Renderer extends BaseRenderer {
constructor(gm: Gm) {
super(gm);
constructor(gm: Gm, palette: Palette) {
super(gm, palette);
}

shape([i, j]: Pos) {
Expand Down
8 changes: 5 additions & 3 deletions app/routes/map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ export default function Map() {
}

useEffect(() => {
const gm = generateGm();
const { gm, palette } = generateGm();

const _renderer = new Renderer(gm);
const _renderer = new Renderer(gm, palette);

void _renderer.init(canvas.current!);

Expand Down Expand Up @@ -53,7 +53,9 @@ export default function Map() {
return;
}

renderer.current.gm = generateGm();
const { gm, palette } = generateGm();
renderer.current.gm = gm;
renderer.current.palette = palette;
renderer.current.reset();
}}
/>
Expand Down
2 changes: 1 addition & 1 deletion app/routes/user.$username.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default function User() {
const anchor = useRef<HTMLDivElement>(null);
const currentUser = useOptionalUser();
const [edit, setEdit] = useState(false);
const actionData: string = useActionData<typeof action>();
const actionData = useActionData<typeof action>();

useEffect(() => {
canScroll &&
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"i18next": "latest",
"i18next-browser-languagedetector": "latest",
"isbot": "latest",
"iwanthue": "latest",
"katex": "latest",
"lodash": "latest",
"lz-string": "latest",
Expand Down Expand Up @@ -133,7 +134,7 @@
"bufferutil": "latest",
"utf-8-validate": "latest"
},
"packageManager": "pnpm@9.0.6",
"packageManager": "pnpm@9.1.0",
"pnpm": {
"supportedArchitectures": {
"os": [
Expand Down
Loading

0 comments on commit e38f5e4

Please sign in to comment.