-
Notifications
You must be signed in to change notification settings - Fork 3
/
menuState.ts
154 lines (132 loc) · 4.43 KB
/
menuState.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
namespace story.menu {
let state: _BlockMenuState;
let sceneStack: _BlockMenuState[];
export function showMenu(options: string[], style: MenuStyle, location: MenuLocation) {
const state = _getState();
state.menu.setOptions(options);
state.menu.setStyle(style);
state.menu.setLocation(location);
state.menu.setMenuOpen(true);
}
export function closeMenu() {
const state = _getState();
state.menu.setMenuOpen(false);
}
export function setColors(foreground: number, background: number) {
const state = _getState();
state.menu.setColors(foreground, background, background, foreground);
}
export function selectedMenuOption(): string {
const state = _getState();
return state.menu.selectedMenuOption();
}
export function selectedMenuIndex(): number {
const state = _getState();
return state.menu.selectedMenuIndex();
}
export function isMenuOpen(): boolean {
const state = _getState();
return state.menu.isOpen();
}
export function onMenuOptionSelected(handler: (option: string, index: number) => void) {
const state = _getState();
state.addHandler(handler);
}
export class _BlockMenuState {
menu: MenuSprite;
handlers: ((option: string, index: number) => void)[];
controlsEnabled: boolean;
constructor() {
this.menu = new MenuSprite();
this.handlers = [];
this.controlsEnabled = true;
}
addHandler(handler: ((option: string, index: number) => void)) {
if (handler) {
this.handlers.push(handler);
}
}
runHandlers(option: string, index: number) {
if (this.handlers.length) {
control.runInParallel(() => {
for (const handler of this.handlers) {
handler(option, index)
}
});
}
}
destroy() {
this.menu.destroy();
}
}
enum button {
u = 1,
r = 1 << 1,
d = 1 << 2,
l = 1 << 3,
a = 1 << 4,
b = 1 << 5
}
export function _init() {
if (sceneStack) return;
sceneStack = [];
state = new _BlockMenuState();
// can't use controller events because it would override
// the user's controller handlers. this works okay but
// it's a little glitchy in the grid layout
let debounce = 100;
control.runInParallel(function() {
while (true) {
controller.pauseUntilAnyButtonIsPressed();
if (!state.controlsEnabled) continue;
if (state.menu.style === MenuStyle.Grid) {
debounce = 150
}
else {
debounce = 100;
}
if (controller.A.isPressed()) {
for (const handler of state.handlers) {
handler(state.menu.selectedMenuOption(), state.menu.selectedMenuIndex());
}
pause(debounce);
}
if (controller.up.isPressed()) {
state.menu.moveSelectionVertical(true);
pause(debounce);
}
if (controller.down.isPressed()) {
state.menu.moveSelectionVertical(false);
pause(debounce);
}
if (controller.left.isPressed()) {
state.menu.moveSelectionHorizontal(true);
pause(debounce);
}
if (controller.right.isPressed()) {
state.menu.moveSelectionHorizontal(false);
pause(debounce);
}
}
})
game.addScenePushHandler(function (oldScene: scene.Scene) {
sceneStack.push(state);
state = new _BlockMenuState();
});
game.addScenePopHandler(function (oldScene: scene.Scene) {
if (sceneStack.length) {
state = sceneStack.pop();
}
else {
if (state) {
state.destroy();
}
state = new _BlockMenuState();
}
});
}
export function _getState() {
_init();
return state;
}
}