like2d 2.12.1 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,189 @@
1
+ /**
2
+ * An automagical gamepad mapper.
3
+ *
4
+ * ```ts
5
+ * like.gamepadconnected = (index) =>
6
+ * scenes.push(mapGamepad({ buttons: buttonSetGBA, sticks: 0 }, 0), false)
7
+ * ```
8
+ *
9
+ * Add this to your codebase and activating a gamepad causes a button mapping screen to pop up.
10
+ * It will request to map any buttons not already covered by the automapping database.
11
+ *
12
+ * If you're wondering what `scenes` refers to, check out {@link SceneManager} to
13
+ * get started.
14
+ *
15
+ * Note: many browsers only fire gamepadconnected on first button press, so always writing "P2: press any button" is a fine idea.
16
+ * @module scene/prefab/mapGamepad
17
+ */
18
+ import { callOwnHandlers, likeDispatch } from "../..";
19
+ import { defaultMapping } from "../../input";
20
+ const mapOrder = [
21
+ "BRight",
22
+ "BBottom",
23
+ "Up",
24
+ "Down",
25
+ "Left",
26
+ "Right",
27
+ "MenuLeft",
28
+ "MenuRight",
29
+ // 8: NES buttons
30
+ "L1",
31
+ "R1",
32
+ // 10: GBA buttons
33
+ "BLeft",
34
+ "BTop",
35
+ // 12: SNES buttons
36
+ "L2",
37
+ "R2",
38
+ // 14: PS1 buttons
39
+ "LeftStick",
40
+ "RightStick",
41
+ ];
42
+ /** All the buttons on an NES */
43
+ export const buttonSetNES = new Set(mapOrder.slice(0, 8));
44
+ /** All the buttons on a GBA -- Like an NES but with L+R */
45
+ export const buttonSetGBA = new Set(mapOrder.slice(0, 10));
46
+ /** All the buttons on a SNES */
47
+ export const buttonSetSNES = new Set(mapOrder.slice(0, 12));
48
+ /** All the buttons on a PS1 -- Like a SNES but with L2+R2 */
49
+ export const buttonSetPS1 = new Set(mapOrder.slice(0, 14));
50
+ /** All the buttons -- including the stick buttons. */
51
+ export const buttonSetAll = new Set(mapOrder);
52
+ const drawCircButt = (pos, size) => (like, color) => like.gfx.circle("fill", color, pos, size);
53
+ const drawDpadPart = (rot) => (like, color) => {
54
+ like.gfx.withTransform(() => {
55
+ like.gfx.translate([2.5, 6]);
56
+ like.gfx.rotate(rot);
57
+ like.gfx.rectangle("fill", color, [0.5, -0.5, 1.3, 1]);
58
+ });
59
+ };
60
+ const drawShoulder = (y, width, flip) => (like, color) => {
61
+ const r = 0.8;
62
+ const rectPos = [5 - width, y];
63
+ const circPos = [5 - width - r, y];
64
+ like.gfx.withTransform(() => {
65
+ if (flip) {
66
+ like.gfx.translate([16, 0]);
67
+ like.gfx.scale([-1, 1]);
68
+ }
69
+ like.gfx.circle("fill", color, circPos, r, { arc: [Math.PI, Math.PI * 3 / 2], center: false });
70
+ like.gfx.rectangle("fill", color, [...rectPos, width, r]);
71
+ });
72
+ };
73
+ // Buttons assume a centered resolution of 16x9px. Transforms exist for a reason lol.
74
+ // LLLLL . RRRRR
75
+ // LLLLLLLLL . RRRRRRRRR
76
+ // .
77
+ // DDD S . S B
78
+ // -.....DDD.....................................
79
+ // DDD DDD . B B
80
+ // DDD LS . RS
81
+ // DDD . B
82
+ // .
83
+ const buttonProps = {
84
+ BLeft: { draw: drawCircButt([12, 6], 0.8) },
85
+ BRight: { draw: drawCircButt([15, 6], 0.8) },
86
+ BTop: { draw: drawCircButt([13.5, 4.5], 0.8) },
87
+ BBottom: { draw: drawCircButt([13.5, 7.5], 0.8) },
88
+ MenuLeft: { draw: drawCircButt([6, 4], 0.5) },
89
+ MenuRight: { draw: drawCircButt([10, 4], 0.5) },
90
+ LeftStick: { draw: drawCircButt([6.5, 7], 1.4) },
91
+ RightStick: { draw: drawCircButt([9.5, 7], 1.4) },
92
+ L1: { draw: drawShoulder(2, 3, false) },
93
+ L2: { draw: drawShoulder(1, 2, false) },
94
+ R1: { draw: drawShoulder(2, 3, true) },
95
+ R2: { draw: drawShoulder(1, 2, true) },
96
+ Right: { draw: drawDpadPart(0) },
97
+ Up: { draw: drawDpadPart(-Math.PI / 2) },
98
+ Left: { draw: drawDpadPart(Math.PI) },
99
+ Down: { draw: drawDpadPart(Math.PI / 2) },
100
+ };
101
+ /** The gamepad mapping scene factory. Call this and pass it into {@link SceneManager.push} */
102
+ export const mapGamepad = (mapMode, targetPad) => (like, scenes) => {
103
+ const currentlyUnmapped = [];
104
+ const mapping = like.gamepad.getMapping(targetPad) ?? defaultMapping(2);
105
+ const alreadyMapped = new Set();
106
+ let held;
107
+ let frameWait = 10;
108
+ const alreadyMappedValues = new Set(Object.values(mapping.buttons));
109
+ for (const btn of mapOrder.reverse()) {
110
+ if (mapMode.buttons.has(btn) && !alreadyMappedValues.has(btn)) {
111
+ currentlyUnmapped.push(btn);
112
+ }
113
+ }
114
+ return {
115
+ handleEvent(ev) {
116
+ if (ev.type == 'draw') {
117
+ const parent = scenes.get(-2);
118
+ if (parent) {
119
+ likeDispatch(parent, ev);
120
+ like.gfx.clear([0, 0, 0, 0.5]);
121
+ }
122
+ else {
123
+ like.gfx.clear();
124
+ }
125
+ }
126
+ callOwnHandlers(this, ev);
127
+ },
128
+ update() {
129
+ frameWait--;
130
+ },
131
+ draw() {
132
+ const centerText = {
133
+ font: "1px sans-serif",
134
+ align: "center",
135
+ width: 16,
136
+ };
137
+ const active = currentlyUnmapped.at(-1);
138
+ const csize = like.canvas.getSize();
139
+ like.gfx.scale(csize[0] / 16);
140
+ like.gfx.translate([0, 1]);
141
+ like.gfx.print("white", `Map gamepad ${targetPad}`, [8, 0.0], centerText);
142
+ // draw shadows
143
+ like.gfx.withTransform(() => {
144
+ like.gfx.translate([0.1, 0.1]);
145
+ for (const prop of mapMode.buttons.keys()) {
146
+ buttonProps[prop].draw(like, 'black');
147
+ }
148
+ });
149
+ for (const prop of mapMode.buttons.keys()) {
150
+ const color = held == prop
151
+ ? "green"
152
+ : active == prop
153
+ ? "red"
154
+ : mapMode.buttons.has(prop)
155
+ ? "white"
156
+ : [0, 0, 0, 0];
157
+ // draw shadows
158
+ buttonProps[prop].draw(like, color);
159
+ }
160
+ like.gfx.print("white", active
161
+ ? `Press ${like.gamepad.fullButtonName(active)}!`
162
+ : "Press any button to resume.", [2, 10], { font: "1px sans-serif" });
163
+ },
164
+ gamepadpressed(source, _name, num) {
165
+ if (source !== targetPad || held || frameWait > 0)
166
+ return;
167
+ const active = currentlyUnmapped.pop();
168
+ if (active && !alreadyMapped.has(num)) {
169
+ alreadyMapped.add(num);
170
+ mapping.buttons[num] = active;
171
+ held = active;
172
+ }
173
+ else if (!active) {
174
+ like.gamepad.setMapping(targetPad, mapping);
175
+ setTimeout(() => scenes.pop(), 100);
176
+ }
177
+ },
178
+ gamepadreleased(source, _name, num) {
179
+ if (source !== targetPad)
180
+ return;
181
+ if (held == mapping.buttons[num]) {
182
+ held = undefined;
183
+ }
184
+ },
185
+ mousepressed() {
186
+ scenes.pop();
187
+ }
188
+ };
189
+ };
@@ -0,0 +1,47 @@
1
+ /**
2
+ * ## Why
3
+ *
4
+ * 1. Because the LIKE logo looks awesome.
5
+ * 2. Autoplay restriction; modern browers don't let you play audio until the page is clicked.
6
+ * 3. You have to click on the game in order to send inputs, anyway.
7
+ * 4. It's polite.
8
+ *
9
+ * ## Usage
10
+ *
11
+ * ```typescript
12
+ * import { createLike, createStartScreen } from 'like';
13
+ * import { createGameScene } from './game';
14
+ *
15
+ * // init LIKE with scenes
16
+ * const container = document.getElementById("myGame");
17
+ * const like = createLike(container);
18
+ * const sceneMan = new SceneManager(like);
19
+ *
20
+ * // these callbacks will be ignored until the scene is clicked
21
+ * like.update = function () { ... }
22
+ * like.draw = function () { ... }
23
+ *
24
+ * // Set up the start screen
25
+ * like.start();
26
+ * sceneMan.push(startScreen())
27
+ * ```
28
+ *
29
+ * Alternatively, copy-paste this code into your own project and modify it freely.
30
+ *
31
+ * ## Custom Rendering
32
+ *
33
+ * Pass a custom draw function to replace the default logo:
34
+ *
35
+ * ```typescript
36
+ * const startup = startScreen((like) => {
37
+ * like.gfx.clear([0, 0, 0, 1]);
38
+ * like.gfx.print([1, 1, 1], 'Click to Start', [100, 100]);
39
+ * });
40
+ * ```
41
+ * @module scene/prefab/startScreen
42
+ */
43
+ import type { Scene } from '..';
44
+ import type { Like } from '../..';
45
+ /** The start screen scene factory. Call this and pass it into {@link scene.SceneManager.push} */
46
+ export declare const startScreen: (onDraw?: (like: Like) => void) => Scene;
47
+ //# sourceMappingURL=startScreen.d.ts.map
@@ -1,4 +1,4 @@
1
- import { Vec2 } from '../math/vector2';
1
+ import { Vec2 } from '../../math/vector2';
2
2
  const LOGO = 'data:image/svg+xml;base64,' +
3
3
  'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBDcmVhdGVkIHdpdGgg' +
4
4
  'SW5rc2NhcGUgKGh0dHA6Ly93d3cuaW5rc2NhcGUub3JnLykgLS0+Cjxzdmcgd2lkdGg9IjI1Nm1t' +
@@ -31,87 +31,28 @@ const LOGO = 'data:image/svg+xml;base64,' +
31
31
  'MyAwLjAzNjk4LThlLTMgLTE1LjM3N3oiLz4KICA8ZWxsaXBzZSBjeD0iMTMyLjk5IiBjeT0iMTYu' +
32
32
  'MTIyIiByeD0iNi4wMjIxIiByeT0iNi4xMTgyIi8+CiAgPGVsbGlwc2UgY3g9IjE0Ny40OSIgY3k9' +
33
33
  'IjE2LjEyMiIgcng9IjYuMDIyMSIgcnk9IjYuMTE4MiIvPgogPC9nPgo8L3N2Zz4K';
34
- /**
35
- * ## Why
36
- *
37
- * 1. Because the LIKE logo looks awesome.
38
- * 2. Autoplay restriction, doesn't let you play audio until the page is clicked.
39
- * 3. You have to click on the game in order to send inputs, anyway.
40
- * 4. It's polite.
41
- *
42
- * ## Usage
43
- *
44
- * ```typescript
45
- * import { createLike, StartScreen } from 'like';
46
- * import { GameScene } from './game';
47
- *
48
- * const container = document.getElementById("myGame");
49
- * const like = createLike(container);
50
- *
51
- * // these callbacks will be ignored until the scene is clicked
52
- * like.update = function () { ... }
53
- * like.draw = function () { ... }
54
- *
55
- * // Set up the start screen
56
- * like.pushScene(new StartScreen())
57
- * like.start();
58
- * ```
59
- *
60
- * Alternatively, copy-paste this code into your own project and modify it freely.
61
- * Update imports:
62
- *
63
- * ```ts
64
- * import { type Scene } from 'like/scene';
65
- * import type { ImageHandle } from 'like/graphics';
66
- * import { Vec2 } from 'like/math';
67
- * import { Like } from 'like';
68
- * ```
69
- *
70
- * ## Custom Rendering
71
- *
72
- * Pass a custom draw function to replace the default logo:
73
- *
74
- * ```typescript
75
- * const startup = new StartupScene(gameScene, (like) => {
76
- * like.gfx.clear([0, 0, 0, 1]);
77
- * like.gfx.print([1, 1, 1], 'Click to Start', [100, 100]);
78
- * });
79
- * ```
80
- */
81
- export class StartScreen {
82
- constructor(onDraw) {
83
- Object.defineProperty(this, "onDraw", {
84
- enumerable: true,
85
- configurable: true,
86
- writable: true,
87
- value: onDraw
88
- });
89
- Object.defineProperty(this, "logo", {
90
- enumerable: true,
91
- configurable: true,
92
- writable: true,
93
- value: void 0
94
- });
95
- }
96
- load(like) {
97
- this.logo = like.gfx.newImage(LOGO);
98
- }
99
- draw(like) {
100
- if (this.onDraw) {
101
- this.onDraw(like);
34
+ /** The start screen scene factory. Call this and pass it into {@link scene.SceneManager.push} */
35
+ export const startScreen = (onDraw) => (like, scenes) => {
36
+ const logo = like.gfx.newImage(LOGO);
37
+ like.mouse.setMode({ lock: false, scrollBlock: false });
38
+ return {
39
+ draw() {
40
+ if (onDraw) {
41
+ onDraw(like);
42
+ }
43
+ else if (logo.isReady()) {
44
+ like.gfx.clear([0.5, 0, 0.5, 1]);
45
+ const winSize = like.canvas.getSize();
46
+ const scale = (winSize[0] * 0.5) / logo.size[0];
47
+ like.gfx.draw(logo, Vec2.div(winSize, 2), {
48
+ scale,
49
+ origin: Vec2.div(logo.size, 2),
50
+ });
51
+ like.gfx.print([1, 1, 0, 0.5 + 0.5 * Math.sin(like.timer.getTime() * 3)], "▶️ click to start ◀️", Vec2.mul(winSize, [0.5, 0.8]), { align: "center", font: "25px sans" });
52
+ }
53
+ },
54
+ mousepressed() {
55
+ scenes.pop();
102
56
  }
103
- else if (this.logo.isReady()) {
104
- like.gfx.clear([0.5, 0, 0.5, 1]);
105
- const winSize = like.canvas.getSize();
106
- const scale = (winSize[0] * 0.5) / this.logo.size[0];
107
- like.gfx.draw(this.logo, Vec2.div(winSize, 2), {
108
- scale,
109
- origin: Vec2.div(this.logo.size, 2),
110
- });
111
- like.gfx.print([1, 1, 0, 0.5 + 0.5 * Math.sin(like.timer.getTime() * 3)], "▶️ click to start ◀️", Vec2.mul(winSize, [0.5, 0.8]), { align: "center", font: "25px sans" });
112
- }
113
- }
114
- mousepressed(like) {
115
- like.popScene();
116
- }
117
- }
57
+ };
58
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "like2d",
3
- "version": "2.12.1",
3
+ "version": "2.13.0",
4
4
  "description": "A web-native game framework inspired by Love2D",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,10 +15,6 @@
15
15
  "import": "./dist/math/index.js",
16
16
  "types": "./dist/math/index.d.ts"
17
17
  },
18
- "./prefab-scenes": {
19
- "import": "./dist/prefab-scenes/index.js",
20
- "types": "./dist/prefab-scenes/index.d.ts"
21
- },
22
18
  "./graphics": {
23
19
  "types": "./dist/graphics/index.d.ts"
24
20
  },
@@ -33,6 +29,14 @@
33
29
  "./timer": {
34
30
  "import": "./dist/timer/index.js",
35
31
  "types": "./dist/timer/index.d.ts"
32
+ },
33
+ "./scene": {
34
+ "import": "./dist/scene/index.js",
35
+ "types": "./dist/scene/index.d.ts"
36
+ },
37
+ "./scene/prefab/*": {
38
+ "import": "./dist/scene/prefab/*.js",
39
+ "types": "./dist/scene/prefab/*.d.ts"
36
40
  }
37
41
  },
38
42
  "files": [
@@ -61,6 +65,7 @@
61
65
  ],
62
66
  "author": "",
63
67
  "license": "MIT",
68
+ "homepage": "https://likeorg.github.io/Like2D/",
64
69
  "repository": {
65
70
  "type": "git",
66
71
  "url": "https://github.com/likeOrg/Like2D"
@@ -1,10 +0,0 @@
1
- /**
2
- * A set of built-in scenes to aid with game development.
3
- *
4
- * To learn more about scenes, see {@link index.Scene}.
5
- *
6
- * @module prefab-scenes
7
- */
8
- export { StartScreen } from "./startScreen";
9
- export { MapGamepad, buttonSetAll, buttonSetNES, buttonSetPS1, buttonSetSNES, type MapMode } from "./mapGamepad";
10
- //# sourceMappingURL=index.d.ts.map
@@ -1,9 +0,0 @@
1
- /**
2
- * A set of built-in scenes to aid with game development.
3
- *
4
- * To learn more about scenes, see {@link index.Scene}.
5
- *
6
- * @module prefab-scenes
7
- */
8
- export { StartScreen } from "./startScreen";
9
- export { MapGamepad, buttonSetAll, buttonSetNES, buttonSetPS1, buttonSetSNES } from "./mapGamepad";
@@ -1,42 +0,0 @@
1
- import type { Like } from "..";
2
- import { type LikeButton } from "../input";
3
- import { Scene } from "../scene";
4
- export declare const buttonSetNES: Set<LikeButton>;
5
- export declare const buttonSetGBA: Set<LikeButton>;
6
- export declare const buttonSetSNES: Set<LikeButton>;
7
- export declare const buttonSetPS1: Set<LikeButton>;
8
- export declare const buttonSetAll: Set<LikeButton>;
9
- export type MapMode = {
10
- buttons: Set<LikeButton>;
11
- stickCount: number;
12
- };
13
- /**
14
- * An automagical gamepad mapper.
15
- *
16
- * ```ts
17
- * like.gamepadconnected = (index) =>
18
- * like.pushScene(new MapGamepad({buttons: buttonSetGBA, sticks: 0}), index)
19
- * ```
20
- *
21
- * Add this to your codebase and activating a gamepad causes a button mapping screen to pop up.
22
- * It will request to map any buttons not already covered by the automapping database.
23
- *
24
- * Note: many browsers do this on first button press, so always writing "P2: press any button" is a fine idea.
25
- */
26
- export declare class MapGamepad implements Scene {
27
- private mapMode;
28
- private targetPad;
29
- private currentlyUnmapped;
30
- private mapping;
31
- private held?;
32
- private alreadyMapped;
33
- private frameWait;
34
- constructor(mapMode: MapMode, targetPad: number);
35
- load(like: Like): void;
36
- update(): void;
37
- draw(like: Like): void;
38
- gamepadpressed(like: Like, source: number, _name: LikeButton, num: number): void;
39
- gamepadreleased(_like: Like, source: number, _name: LikeButton, num: number): void;
40
- mousepressed(like: Like): void;
41
- }
42
- //# sourceMappingURL=mapGamepad.d.ts.map
@@ -1,199 +0,0 @@
1
- import { defaultMapping } from "../input";
2
- const mapOrder = [
3
- "BRight",
4
- "BBottom",
5
- "Up",
6
- "Down",
7
- "Left",
8
- "Right",
9
- "MenuLeft",
10
- "MenuRight",
11
- // 8: NES buttons
12
- "L1",
13
- "R1",
14
- // 10: GBA buttons
15
- "BLeft",
16
- "BTop",
17
- // 12: SNES buttons
18
- "L2",
19
- "R2",
20
- // 14: PS1 buttons
21
- "LeftStick",
22
- "RightStick",
23
- ];
24
- export const buttonSetNES = new Set(mapOrder.slice(0, 8));
25
- export const buttonSetGBA = new Set(mapOrder.slice(0, 10));
26
- export const buttonSetSNES = new Set(mapOrder.slice(0, 12));
27
- export const buttonSetPS1 = new Set(mapOrder.slice(0, 14));
28
- export const buttonSetAll = new Set(mapOrder);
29
- const drawCircButt = (pos, size) => (like, color) => like.gfx.circle("fill", color, pos, size);
30
- const drawDpadPart = (rot) => (like, color) => {
31
- like.gfx.withTransform(() => {
32
- like.gfx.translate([2.5, 6]);
33
- like.gfx.rotate(rot);
34
- like.gfx.rectangle("fill", color, [0.5, -0.5, 1.3, 1]);
35
- });
36
- };
37
- const drawShoulder = (y, width, flip) => (like, color) => {
38
- const r = 0.8;
39
- const rectPos = [5 - width, y];
40
- const circPos = [5 - width - r, y];
41
- like.gfx.withTransform(() => {
42
- if (flip) {
43
- like.gfx.translate([16, 0]);
44
- like.gfx.scale([-1, 1]);
45
- }
46
- like.gfx.circle("fill", color, circPos, r, { arc: [Math.PI, Math.PI * 3 / 2], center: false });
47
- like.gfx.rectangle("fill", color, [...rectPos, width, r]);
48
- });
49
- };
50
- // Buttons assume a centered resolution of 16x9px. Transforms exist for a reason lol.
51
- // LLLLL . RRRRR
52
- // LLLLLLLLL . RRRRRRRRR
53
- // .
54
- // DDD S . S B
55
- // -.....DDD.....................................
56
- // DDD DDD . B B
57
- // DDD LS . RS
58
- // DDD . B
59
- // .
60
- const buttonProps = {
61
- BLeft: { draw: drawCircButt([12, 6], 0.8) },
62
- BRight: { draw: drawCircButt([15, 6], 0.8) },
63
- BTop: { draw: drawCircButt([13.5, 4.5], 0.8) },
64
- BBottom: { draw: drawCircButt([13.5, 7.5], 0.8) },
65
- MenuLeft: { draw: drawCircButt([6, 4], 0.5) },
66
- MenuRight: { draw: drawCircButt([10, 4], 0.5) },
67
- LeftStick: { draw: drawCircButt([6.5, 7], 1.4) },
68
- RightStick: { draw: drawCircButt([9.5, 7], 1.4) },
69
- L1: { draw: drawShoulder(2, 3, false) },
70
- L2: { draw: drawShoulder(1, 2, false) },
71
- R1: { draw: drawShoulder(2, 3, true) },
72
- R2: { draw: drawShoulder(1, 2, true) },
73
- Right: { draw: drawDpadPart(0) },
74
- Up: { draw: drawDpadPart(-Math.PI / 2) },
75
- Left: { draw: drawDpadPart(Math.PI) },
76
- Down: { draw: drawDpadPart(Math.PI / 2) },
77
- };
78
- /**
79
- * An automagical gamepad mapper.
80
- *
81
- * ```ts
82
- * like.gamepadconnected = (index) =>
83
- * like.pushScene(new MapGamepad({buttons: buttonSetGBA, sticks: 0}), index)
84
- * ```
85
- *
86
- * Add this to your codebase and activating a gamepad causes a button mapping screen to pop up.
87
- * It will request to map any buttons not already covered by the automapping database.
88
- *
89
- * Note: many browsers do this on first button press, so always writing "P2: press any button" is a fine idea.
90
- */
91
- export class MapGamepad {
92
- constructor(mapMode, targetPad) {
93
- Object.defineProperty(this, "mapMode", {
94
- enumerable: true,
95
- configurable: true,
96
- writable: true,
97
- value: mapMode
98
- });
99
- Object.defineProperty(this, "targetPad", {
100
- enumerable: true,
101
- configurable: true,
102
- writable: true,
103
- value: targetPad
104
- });
105
- Object.defineProperty(this, "currentlyUnmapped", {
106
- enumerable: true,
107
- configurable: true,
108
- writable: true,
109
- value: []
110
- });
111
- Object.defineProperty(this, "mapping", {
112
- enumerable: true,
113
- configurable: true,
114
- writable: true,
115
- value: void 0
116
- });
117
- Object.defineProperty(this, "held", {
118
- enumerable: true,
119
- configurable: true,
120
- writable: true,
121
- value: void 0
122
- });
123
- Object.defineProperty(this, "alreadyMapped", {
124
- enumerable: true,
125
- configurable: true,
126
- writable: true,
127
- value: new Set()
128
- });
129
- Object.defineProperty(this, "frameWait", {
130
- enumerable: true,
131
- configurable: true,
132
- writable: true,
133
- value: 0
134
- });
135
- }
136
- load(like) {
137
- this.frameWait = 10;
138
- this.mapping = like.gamepad.getMapping(this.targetPad) ?? defaultMapping(2);
139
- const alreadyMapped = new Set(Object.values(this.mapping.buttons));
140
- for (const btn of mapOrder.reverse()) {
141
- if (this.mapMode.buttons.has(btn) && !alreadyMapped.has(btn)) {
142
- this.currentlyUnmapped.push(btn);
143
- }
144
- }
145
- like.canvas.setMode([320, 240]);
146
- }
147
- update() {
148
- this.frameWait--;
149
- }
150
- draw(like) {
151
- const centerText = {
152
- font: "1px sans-serif",
153
- align: "center",
154
- width: 16,
155
- };
156
- const active = this.currentlyUnmapped.at(-1);
157
- like.gfx.clear();
158
- like.gfx.scale(20);
159
- like.gfx.translate([0, 1]);
160
- like.gfx.print("white", `Map gamepad ${this.targetPad}`, [8, 0.0], centerText);
161
- for (const prop of this.mapMode.buttons.keys()) {
162
- const color = this.held == prop
163
- ? "green"
164
- : active == prop
165
- ? "red"
166
- : this.mapMode.buttons.has(prop)
167
- ? "gray"
168
- : "black";
169
- buttonProps[prop].draw(like, color);
170
- }
171
- like.gfx.print("white", active
172
- ? `Press ${like.gamepad.fullButtonName(active)}!`
173
- : "Press any button to resume.", [2, 10], { font: "1px sans-serif" });
174
- }
175
- gamepadpressed(like, source, _name, num) {
176
- if (source !== this.targetPad || this.held || this.frameWait > 0)
177
- return;
178
- const active = this.currentlyUnmapped.pop();
179
- if (active && !this.alreadyMapped.has(num)) {
180
- this.alreadyMapped.add(num);
181
- this.mapping.buttons[num] = active;
182
- this.held = active;
183
- }
184
- else if (!active) {
185
- like.gamepad.setMapping(this.targetPad, this.mapping);
186
- setTimeout(() => like.popScene(), 100);
187
- }
188
- }
189
- gamepadreleased(_like, source, _name, num) {
190
- if (source !== this.targetPad)
191
- return;
192
- if (this.held == this.mapping.buttons[num]) {
193
- this.held = undefined;
194
- }
195
- }
196
- mousepressed(like) {
197
- like.popScene();
198
- }
199
- }