Skip to content

Commit 2fc67e2

Browse files
committed
Add title screen
1 parent 2be15a9 commit 2fc67e2

File tree

8 files changed

+129
-13
lines changed

8 files changed

+129
-13
lines changed

public/assets/gfx/maintitle.png

2.62 KB
Loading

public/assets/gfx/titlewave.png

547 Bytes
Loading

src/App.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ footer {
115115

116116
@font-face {
117117
font-family: "Monogram";
118-
src: url("fonts/monogram.ttf") format("truetype");
118+
src: url("./assets/fonts/monogram.ttf") format("truetype");
119119
}
120120

121121
.orientation-message {

src/components/Game.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import Phaser from "phaser";
33
import { gameConfig } from "../game/config";
44
import { ConnectDevice } from "./ConnectDevice";
55
import { GameScene } from "../game/scenes/GameScene";
6+
import { MenuScene } from "../game/scenes/MenuScene";
7+
import { GameOverScene } from "../game/scenes/GameOverScene";
68

79
const Game = () => {
810
const [device, setDevice] = useState<HIDDevice | null>(null);
@@ -22,7 +24,10 @@ const Game = () => {
2224

2325
// Small delay to ensure DOM has fully rendered
2426
const initTimer = setTimeout(() => {
25-
gameRef.current = new Phaser.Game(config);
27+
gameRef.current = new Phaser.Game({
28+
...config,
29+
scene: [MenuScene, GameScene, GameOverScene],
30+
});
2631
}, 50);
2732

2833
// Handle orientation change and resize events

src/game/config.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
import Phaser from "phaser";
22
import { GameScene } from "./scenes/GameScene";
33
import { GameOverScene } from "./scenes/GameOverScene";
4+
import { MenuScene } from "./scenes/MenuScene";
45

56
export const gameConfig: Phaser.Types.Core.GameConfig = {
67
type: Phaser.AUTO,
78
backgroundColor: "#9bbc0f",
89
width: 160,
910
height: 144,
10-
zoom: 4,
11+
zoom: 6,
1112
physics: {
1213
default: "arcade",
1314
arcade: {
1415
gravity: { y: 0, x: 0 },
1516
debug: false,
1617
},
1718
},
18-
scene: [GameScene, GameOverScene],
19+
scene: [MenuScene, GameScene, GameOverScene],
1920
scale: {
2021
parent: "game-container",
2122
},

src/game/createSpriteAssets.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,49 @@ import Phaser from "phaser";
33
export class SpriteAssets {
44
static loadSimpleSprites(scene: Phaser.Scene): void {
55
if (!scene.textures.exists("screenwipe")) {
6-
scene.load.image("screenwipe", "assets/gfx/screenwipe.png");
6+
scene.load.image("screenwipe", "./assets/gfx/screenwipe.png");
7+
}
8+
if (!scene.textures.exists("maintitle")) {
9+
scene.load.image("maintitle", "./assets/gfx/maintitle.png");
10+
}
11+
if (!scene.textures.exists("titlewave")) {
12+
scene.load.image("titlewave", "./assets/gfx/titlewave.png");
713
}
814
}
915

1016
static loadSpriteSheets(scene: Phaser.Scene): void {
1117
if (!scene.textures.exists("switchy")) {
12-
scene.load.spritesheet("switchy", "assets/gfx/switchy.png", {
18+
scene.load.spritesheet("switchy", "./assets/gfx/switchy.png", {
1319
frameWidth: 16,
1420
frameHeight: 16,
1521
});
1622
}
1723
if (!scene.textures.exists("briefcase")) {
18-
scene.load.spritesheet("briefcase", "assets/gfx/briefcase.png", {
24+
scene.load.spritesheet("briefcase", "./assets/gfx/briefcase.png", {
1925
frameWidth: 16,
2026
frameHeight: 16,
2127
});
2228
}
2329
if (!scene.textures.exists("mail")) {
24-
scene.load.spritesheet("mail", "assets/gfx/mail.png", {
30+
scene.load.spritesheet("mail", "./assets/gfx/mail.png", {
2531
frameWidth: 16,
2632
frameHeight: 16,
2733
});
2834
}
2935
if (!scene.textures.exists("paper")) {
30-
scene.load.spritesheet("paper", "assets/gfx/paper.png", {
36+
scene.load.spritesheet("paper", "./assets/gfx/paper.png", {
3137
frameWidth: 16,
3238
frameHeight: 16,
3339
});
3440
}
3541
if (!scene.textures.exists("stapler")) {
36-
scene.load.spritesheet("stapler", "assets/gfx/stapler.png", {
42+
scene.load.spritesheet("stapler", "./assets/gfx/stapler.png", {
3743
frameWidth: 16,
3844
frameHeight: 16,
3945
});
4046
}
4147
if (!scene.textures.exists("taxman")) {
42-
scene.load.spritesheet("taxman", "assets/gfx/taxman.png", {
48+
scene.load.spritesheet("taxman", "./assets/gfx/taxman.png", {
4349
frameWidth: 32,
4450
frameHeight: 64,
4551
});

src/game/scenes/GameOverScene.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@ export class GameOverScene extends Phaser.Scene {
1717
.setOrigin(0.5);
1818

1919
this.add
20-
.text(width / 2, height / 2 + 10, "Press R to retry", {
20+
.text(width / 2, height / 2 + 10, "Press Backspace to go back", {
2121
fontFamily: "Monogram",
2222
fontSize: "16px",
2323
color: "#0f380f",
2424
})
2525
.setOrigin(0.5);
2626
});
2727

28-
this.input.keyboard?.once("keydown-R", () => this.scene.start("GameScene"));
28+
this.input.keyboard?.once("keydown-BACKSPACE", () =>
29+
this.scene.start("MenuScene")
30+
);
2931
}
3032
}

src/game/scenes/MenuScene.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import Phaser from "phaser";
2+
import { SpriteAssets } from "../createSpriteAssets";
3+
4+
export class MenuScene extends Phaser.Scene {
5+
private selectedIndex: number = 0;
6+
private options: string[] = ["START GAME", "HI SCORES"];
7+
private optionTexts: Phaser.GameObjects.Text[] = [];
8+
private cursor!: Phaser.GameObjects.Triangle;
9+
10+
constructor() {
11+
super("MenuScene");
12+
}
13+
14+
preload() {
15+
SpriteAssets.loadSimpleSprites(this);
16+
}
17+
18+
create() {
19+
const { width, height } = this.cameras.main;
20+
this.add.sprite(0, 0, "maintitle").setOrigin(0, 0);
21+
this.add.sprite(width, height / 2, "titlewave").setOrigin(1, 0);
22+
23+
document.fonts.load('16px "Monogram"').then(() => {
24+
this.add
25+
.text(width / 2, height - 32, "Play with WASD :)", {
26+
fontFamily: "Monogram",
27+
fontSize: "16px",
28+
color: "#0f380f",
29+
})
30+
.setOrigin(0.5, 0.5);
31+
this.add
32+
.text(width / 2, height - 16, "2025 heidi@wooting", {
33+
fontFamily: "Monogram",
34+
fontSize: "14px",
35+
color: "#0f380f",
36+
})
37+
.setOrigin(0.5, 0.5);
38+
this.add
39+
.text(width / 2, height / 2 - 12, "TAX FRAUD", {
40+
fontFamily: "Monogram",
41+
fontSize: "20px",
42+
color: "#0f380f",
43+
})
44+
.setOrigin(0.5, 0.5);
45+
46+
this.options.forEach((label, i) => {
47+
const text = this.add
48+
.text(width / 2, height / 2 + 8 + i * 16, label, {
49+
fontFamily: "Monogram",
50+
fontSize: "16px",
51+
color: "#0f380f",
52+
})
53+
.setOrigin(0.5, 0.5);
54+
this.optionTexts.push(text);
55+
});
56+
57+
this.cursor = this.add
58+
.triangle(
59+
width / 2 - 50,
60+
this.optionTexts[0].y + 4,
61+
0,
62+
0,
63+
8,
64+
4,
65+
0,
66+
8,
67+
0x0f380f
68+
)
69+
.setOrigin(0.5, 0.75);
70+
});
71+
72+
this.input.keyboard?.on("keydown-W", () => {
73+
this.selectedIndex =
74+
(this.selectedIndex + this.options.length - 1) % this.options.length;
75+
this.updateCursor();
76+
});
77+
78+
this.input.keyboard?.on("keydown-S", () => {
79+
this.selectedIndex =
80+
(this.selectedIndex + this.options.length + 1) % this.options.length;
81+
this.updateCursor();
82+
});
83+
84+
this.input.keyboard?.on("keydown-ENTER", () => {
85+
this.selectOption();
86+
});
87+
}
88+
89+
updateCursor() {
90+
const targetText = this.optionTexts[this.selectedIndex];
91+
this.cursor.setY(targetText.y + 4);
92+
}
93+
94+
selectOption() {
95+
const selected = this.options[this.selectedIndex];
96+
if (selected === "START GAME") {
97+
this.scene.start("GameScene");
98+
} else if (selected === "HI SCORES") {
99+
console.log("TODO: Show high scores");
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)