+
+ {/* */}
+
+
+
+ Now Sasha's gonna edit src/app.tsx...
+
+
+ Sasha is building it using{" "}
+ {Link(new URL("https://reactjs.org"), "React")},{" "}
+ {Link(new URL("https://tailwindcss.com/"), "Tailwind CSS")}, and{" "}
+ {Link(new URL("https://www.typescriptlang.org/"), "TypeScript")}.
+
+
+
+ );
+};
diff --git a/src/pages/not-found/background.ts b/src/pages/not-found/background.ts
new file mode 100644
index 0000000..52d10fb
--- /dev/null
+++ b/src/pages/not-found/background.ts
@@ -0,0 +1,58 @@
+import dumbbellNebula from "../../assets/dumbbell-nebula.jpg";
+import godzillaNebula from "../../assets/godzilla-nebula.jpg";
+import horseheadNebula from "../../assets/horsehead-nebula.jpg";
+import planetaryNebula from "../../assets/planetary-nebula.jpg";
+import swanNebula from "../../assets/swan-nebula.jpg";
+import blackHole from "../../assets/black-hole.jpg";
+
+export type Background = {
+ entity: string;
+ constellation: string;
+ closestSystem: string;
+ resource: string;
+};
+
+export function randomBackground(): Background {
+ const backgrounds = [
+ {
+ entity: "Dumbbell Nebula",
+ constellation: "Vulpecula",
+ closestSystem: "M27",
+ resource: dumbbellNebula,
+ },
+ {
+ entity: "Godzilla Nebula",
+ constellation: "Orion",
+ closestSystem: "IC 2118",
+ resource: godzillaNebula,
+ },
+ {
+ entity: "Horsehead Nebula",
+ constellation: "Orion",
+ closestSystem: "IC 434",
+ resource: horseheadNebula,
+ },
+ {
+ entity: "Planetary Nebula",
+ constellation: "Aquarius",
+ closestSystem: "NGC 7009",
+ resource: planetaryNebula,
+ },
+ {
+ entity: "Swan Nebula",
+ constellation: "Sagittarius",
+ closestSystem: "M17",
+ resource: swanNebula,
+ },
+ {
+ entity: "Black Hole",
+ constellation: "Virgo",
+ closestSystem: "M87",
+ resource: blackHole,
+ },
+ ] as Background[];
+
+ const index = Math.floor(Math.random() * backgrounds.length);
+
+ return backgrounds[index];
+}
diff --git a/src/pages/not-found/buttons.ts b/src/pages/not-found/buttons.ts
new file mode 100644
index 0000000..e09fc62
--- /dev/null
+++ b/src/pages/not-found/buttons.ts
@@ -0,0 +1,20 @@
+export type ControlButtonCode =
+ | "ArrowUp"
+ | "ArrowDown"
+ | "ArrowLeft"
+ | "ArrowRight"
+ | "KeyA"
+ | "KeyD";
+
+export type ButtonCode = ControlButtonCode | "KeyS" | "KeyM" | "KeyV";
+
+export function isControlButton(code: ButtonCode): code is ControlButtonCode {
+ return (
+ code === "ArrowUp" ||
+ code === "ArrowDown" ||
+ code === "ArrowLeft" ||
+ code === "ArrowRight" ||
+ code === "KeyA" ||
+ code === "KeyD"
+ );
+}
diff --git a/src/pages/not-found/display-mode.ts b/src/pages/not-found/display-mode.ts
new file mode 100644
index 0000000..1f6a8b9
--- /dev/null
+++ b/src/pages/not-found/display-mode.ts
@@ -0,0 +1,12 @@
+export type DisplayMode = "message" | "stats" | "none";
+
+export function nextDisplayMode(current: DisplayMode): DisplayMode {
+ switch (current) {
+ case "message":
+ return "stats";
+ case "stats":
+ return "none";
+ case "none":
+ return "message";
+ }
+}
diff --git a/src/pages/not-found/display-pad.ts b/src/pages/not-found/display-pad.ts
new file mode 100644
index 0000000..e98a140
--- /dev/null
+++ b/src/pages/not-found/display-pad.ts
@@ -0,0 +1,76 @@
+import {
+ Text,
+ TextMetrics,
+ Graphics,
+ TextStyle,
+ Container,
+ ITextStyle,
+} from "pixi.js";
+
+export class DisplayPad {
+ private borderWidth = 10;
+ private graphics: Graphics;
+ private text: Text;
+ private style: TextStyle;
+
+ public get width(): number {
+ return this.graphics.width;
+ }
+
+ public get height(): number {
+ return this.graphics.height;
+ }
+
+ constructor(
+ parent: Container,
+ styleOptions: Partial