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.
- package/README.md +17 -27
- package/assets/logo-banner-optimized.svg +1 -1
- package/dist/engine.d.ts +13 -7
- package/dist/engine.js +21 -46
- package/dist/events.d.ts +61 -59
- package/dist/graphics/graphics.d.ts +2 -1
- package/dist/graphics/index.d.ts +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +1 -0
- package/dist/input/gamepad.d.ts +2 -2
- package/dist/input/gamepad.js +2 -2
- package/dist/input/mouse.d.ts +2 -2
- package/dist/input/mouse.js +2 -2
- package/dist/like.d.ts +37 -66
- package/dist/scene/index.d.ts +368 -0
- package/dist/scene/index.js +204 -0
- package/dist/scene/prefab/fadeTransition.d.ts +25 -0
- package/dist/scene/prefab/fadeTransition.js +55 -0
- package/dist/scene/prefab/mapGamepad.d.ts +47 -0
- package/dist/scene/prefab/mapGamepad.js +189 -0
- package/dist/scene/prefab/startScreen.d.ts +47 -0
- package/dist/{prefab-scenes → scene/prefab}/startScreen.js +25 -84
- package/package.json +10 -5
- package/dist/prefab-scenes/index.d.ts +0 -10
- package/dist/prefab-scenes/index.js +0 -9
- package/dist/prefab-scenes/mapGamepad.d.ts +0 -42
- package/dist/prefab-scenes/mapGamepad.js +0 -199
- package/dist/prefab-scenes/startScreen.d.ts +0 -58
- package/dist/scene.d.ts +0 -145
- package/dist/scene.js +0 -23
|
@@ -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 '
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
*
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
104
|
-
|
|
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.
|
|
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
|
-
}
|