pxt-arcade 1.12.13 → 1.12.16
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/built/common-sim.d.ts +6 -0
- package/built/common-sim.js +15 -2
- package/built/sim.js +108 -26
- package/built/target-strings.json +2 -2
- package/built/target.js +274 -194
- package/built/target.json +274 -194
- package/built/targetlight.json +5 -5
- package/built/theme.json +5 -5
- package/docs/skillmap/educator-info/adventure-info.md +87 -0
- package/docs/static/hero-gallery/multiplayer-banner.png +0 -0
- package/docs/test/skillmap/adventure/adventure1.md +493 -0
- package/docs/test/skillmap/adventure/adventure2.md +279 -0
- package/docs/test/skillmap/adventure/adventure3.md +208 -0
- package/docs/test/skillmap/adventure/adventure4.md +1773 -0
- package/docs/test/skillmap/adventure.md +85 -0
- package/docs/test/skillmap/story/story1.md +15 -10
- package/docs/test/skillmap/story/story2.md +2 -1
- package/docs/test/tutorials/collect-clovers.md +1044 -0
- package/docs/test/tutorials/hawk.md +172 -75
- package/docs/test/tutorials/time-flies.md +346 -0
- package/package.json +4 -4
- package/pxtarget.json +5 -5
- package/targetconfig.json +57 -3
package/built/common-sim.d.ts
CHANGED
|
@@ -818,6 +818,11 @@ declare namespace pxsim {
|
|
|
818
818
|
instruction: "playinstructions" | "muteallchannels";
|
|
819
819
|
soundbuf?: Uint8Array;
|
|
820
820
|
}
|
|
821
|
+
interface MultiplayerConnectionEvent extends SimulatorMultiplayerMessage {
|
|
822
|
+
content: "Connection";
|
|
823
|
+
slot: number;
|
|
824
|
+
connected: boolean;
|
|
825
|
+
}
|
|
821
826
|
class MultiplayerState {
|
|
822
827
|
lastMessageId: number;
|
|
823
828
|
origin: string;
|
|
@@ -826,6 +831,7 @@ declare namespace pxsim {
|
|
|
826
831
|
send(msg: SimulatorMultiplayerMessage): void;
|
|
827
832
|
init(origin: string): void;
|
|
828
833
|
setButton(key: number, isPressed: boolean): void;
|
|
834
|
+
registerConnectionState(player: number, connected: boolean): void;
|
|
829
835
|
protected messageHandler(msg: SimulatorMessage): void;
|
|
830
836
|
}
|
|
831
837
|
}
|
package/built/common-sim.js
CHANGED
|
@@ -2554,8 +2554,6 @@ var pxsim;
|
|
|
2554
2554
|
}
|
|
2555
2555
|
multiplayer.postImage = postImage;
|
|
2556
2556
|
function postIcon(iconType, slot, im) {
|
|
2557
|
-
if (pxsim.getMultiplayerState().origin !== "server")
|
|
2558
|
-
return;
|
|
2559
2557
|
if (im._width * im._height > 64 * 64) {
|
|
2560
2558
|
// setting 64x64 as max size for icon for now
|
|
2561
2559
|
return;
|
|
@@ -2596,6 +2594,8 @@ var pxsim;
|
|
|
2596
2594
|
IconType[IconType["Player"] = 0] = "Player";
|
|
2597
2595
|
IconType[IconType["Reaction"] = 1] = "Reaction";
|
|
2598
2596
|
})(IconType = pxsim.IconType || (pxsim.IconType = {}));
|
|
2597
|
+
const MULTIPLAYER_PLAYER_JOINED_ID = 3241;
|
|
2598
|
+
const MULTIPLAYER_PLAYER_LEFT_ID = 3242;
|
|
2599
2599
|
class MultiplayerState {
|
|
2600
2600
|
constructor() {
|
|
2601
2601
|
this.lastMessageId = 0;
|
|
@@ -2628,6 +2628,11 @@ var pxsim;
|
|
|
2628
2628
|
});
|
|
2629
2629
|
}
|
|
2630
2630
|
}
|
|
2631
|
+
registerConnectionState(player, connected) {
|
|
2632
|
+
const evId = connected ? MULTIPLAYER_PLAYER_JOINED_ID : MULTIPLAYER_PLAYER_LEFT_ID;
|
|
2633
|
+
const b = pxsim.board();
|
|
2634
|
+
b.bus.queue(evId, player);
|
|
2635
|
+
}
|
|
2631
2636
|
messageHandler(msg) {
|
|
2632
2637
|
if (!isMultiplayerMessage(msg)) {
|
|
2633
2638
|
return;
|
|
@@ -2661,6 +2666,11 @@ var pxsim;
|
|
|
2661
2666
|
}
|
|
2662
2667
|
}
|
|
2663
2668
|
}
|
|
2669
|
+
else if (isConnectionMessage(msg)) {
|
|
2670
|
+
if (this.origin === "server") {
|
|
2671
|
+
this.registerConnectionState(msg.slot, msg.connected);
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2664
2674
|
}
|
|
2665
2675
|
}
|
|
2666
2676
|
pxsim.MultiplayerState = MultiplayerState;
|
|
@@ -2676,6 +2686,9 @@ var pxsim;
|
|
|
2676
2686
|
function isAudioMessage(msg) {
|
|
2677
2687
|
return msg && msg.content === "Audio";
|
|
2678
2688
|
}
|
|
2689
|
+
function isConnectionMessage(msg) {
|
|
2690
|
+
return msg && msg.content === "Connection";
|
|
2691
|
+
}
|
|
2679
2692
|
})(pxsim || (pxsim = {}));
|
|
2680
2693
|
var pxsim;
|
|
2681
2694
|
(function (pxsim) {
|
package/built/sim.js
CHANGED
|
@@ -156,11 +156,17 @@ var pxsim;
|
|
|
156
156
|
let isFirstRunSafari = true;
|
|
157
157
|
window.addEventListener("DOMContentLoaded", () => {
|
|
158
158
|
const searchParams = new URL(window.location.toString()).searchParams;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
159
|
+
const setThemeIfDefined = (themeType) => {
|
|
160
|
+
const paramVal = searchParams.get(themeType);
|
|
161
|
+
if (paramVal) {
|
|
162
|
+
setSimThemeColor(themeType, paramVal);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
setThemeIfDefined("background-color");
|
|
166
|
+
setThemeIfDefined("button-stroke");
|
|
167
|
+
setThemeIfDefined("text-color");
|
|
168
|
+
setThemeIfDefined("button-fill");
|
|
169
|
+
setThemeIfDefined("dpad-fill");
|
|
164
170
|
if (!!searchParams.get("pointer-events"))
|
|
165
171
|
registerPointerEvents();
|
|
166
172
|
if (!!searchParams.get("hideSimButtons"))
|
|
@@ -223,20 +229,33 @@ var pxsim;
|
|
|
223
229
|
canvas.addEventListener("pointerout", reporter);
|
|
224
230
|
canvas.addEventListener("wheel", wheelReporter);
|
|
225
231
|
}
|
|
226
|
-
function setSimThemeColor(part, color) {
|
|
227
|
-
if (!part || !color ||
|
|
232
|
+
function setSimThemeColor(part, color, elOverride) {
|
|
233
|
+
if (!part || (!(color == undefined || /^[0-9A-F]{6}$/i.test(color))))
|
|
228
234
|
return;
|
|
235
|
+
if (part != "background-color"
|
|
236
|
+
&& part != "button-stroke"
|
|
237
|
+
&& part != "text-color"
|
|
238
|
+
&& part != "button-fill"
|
|
239
|
+
&& part != "dpad-fill") {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
229
242
|
const propName = `--sim-${part}`;
|
|
230
|
-
const propColor = `#${color}
|
|
231
|
-
const wrapper = document.getElementById("wrap");
|
|
232
|
-
|
|
243
|
+
const propColor = color ? `#${color}` : undefined;
|
|
244
|
+
const wrapper = elOverride || document.getElementById("wrap");
|
|
245
|
+
if (propColor) {
|
|
246
|
+
wrapper.style.setProperty(propName, propColor);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
wrapper.style.removeProperty(propName);
|
|
250
|
+
}
|
|
233
251
|
}
|
|
234
252
|
/**
|
|
235
253
|
* This function gets called each time the program restarts
|
|
236
254
|
*/
|
|
237
|
-
pxsim.initCurrentRuntime = () => {
|
|
255
|
+
pxsim.initCurrentRuntime = (msg) => {
|
|
238
256
|
pxsim.runtime.board = new Board();
|
|
239
257
|
pxsim.initGamepad();
|
|
258
|
+
board().setActivePlayer(msg.activePlayer);
|
|
240
259
|
if (!forcedUpdateLoop) {
|
|
241
260
|
forcedUpdateLoop = true;
|
|
242
261
|
// this is used to force screen update if game loop is stuck or not set up properly
|
|
@@ -305,6 +324,7 @@ var pxsim;
|
|
|
305
324
|
}
|
|
306
325
|
};
|
|
307
326
|
window.addEventListener("message", (ev) => {
|
|
327
|
+
var _a;
|
|
308
328
|
if (ev.data.button !== undefined && ev.data.type !== "multiplayer") {
|
|
309
329
|
let key;
|
|
310
330
|
switch (ev.data.button) {
|
|
@@ -344,6 +364,15 @@ var pxsim;
|
|
|
344
364
|
b.multiplayerState.origin = ev.data.context;
|
|
345
365
|
}
|
|
346
366
|
}
|
|
367
|
+
if (ev.data.type == "setactiveplayer") {
|
|
368
|
+
const b = board();
|
|
369
|
+
if (!(b.multiplayerState && b.multiplayerState.origin)) {
|
|
370
|
+
b.setActivePlayer(ev.data.playerNumber);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else if (ev.data.type == "setsimthemecolor") {
|
|
374
|
+
setSimThemeColor(ev.data.part, (_a = ev.data.color) === null || _a === void 0 ? void 0 : _a.replace("#", ""));
|
|
375
|
+
}
|
|
347
376
|
});
|
|
348
377
|
}
|
|
349
378
|
};
|
|
@@ -425,6 +454,32 @@ var pxsim;
|
|
|
425
454
|
const scale = isEdge() || isIE() ? 10 : 1;
|
|
426
455
|
this.gameplayer = new pxsim.visuals.GamePlayer(scale);
|
|
427
456
|
throttleAnimation((cb) => (this.screenState.onChange = cb), () => this.gameplayer.draw(this.screenState));
|
|
457
|
+
this.activePlayer = undefined;
|
|
458
|
+
}
|
|
459
|
+
setActivePlayer(playerNumber) {
|
|
460
|
+
if (this.multiplayerState && this.multiplayerState.origin)
|
|
461
|
+
return;
|
|
462
|
+
// TODO: this is duplicated in pxt/multiplayer's ArcadeSimulator.tsx;
|
|
463
|
+
// we could dedup this by starting a set of 'named' themes in the future
|
|
464
|
+
// (e.g. player1, player2, hotrodflames, ...)
|
|
465
|
+
// [[backgroundColor, buttonStroke]]
|
|
466
|
+
const playerThemes = [
|
|
467
|
+
[undefined, undefined],
|
|
468
|
+
["ED3636", "8D2525"],
|
|
469
|
+
["4E4EE9", "3333A1"],
|
|
470
|
+
["FF9A14", "B0701A"],
|
|
471
|
+
["4EB94E", "245D24"],
|
|
472
|
+
];
|
|
473
|
+
const newPlayerTheme = playerThemes[playerNumber || 0];
|
|
474
|
+
if (!newPlayerTheme) {
|
|
475
|
+
// invalid playerNumber
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
const themeOverrideElement = document.querySelector(".game-player");
|
|
479
|
+
setSimThemeColor("background-color", newPlayerTheme[0], themeOverrideElement);
|
|
480
|
+
setSimThemeColor("button-stroke", newPlayerTheme[1], themeOverrideElement);
|
|
481
|
+
setSimThemeColor("dpad-fill", newPlayerTheme[1], themeOverrideElement);
|
|
482
|
+
this.activePlayer = playerNumber || undefined;
|
|
428
483
|
}
|
|
429
484
|
getDefaultPitchPin() {
|
|
430
485
|
return undefined;
|
|
@@ -438,14 +493,24 @@ var pxsim;
|
|
|
438
493
|
}
|
|
439
494
|
}
|
|
440
495
|
setButton(which, isPressed) {
|
|
496
|
+
const inMultiplayerSession = !!this.multiplayerState.origin;
|
|
441
497
|
// Disallow local input for player 2+ in multiplayer mode.
|
|
442
|
-
if (
|
|
498
|
+
if (inMultiplayerSession && which > pxsim.Key.Menu)
|
|
443
499
|
return;
|
|
444
|
-
if (which)
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
500
|
+
if (!which)
|
|
501
|
+
return;
|
|
502
|
+
let playerOffset = 0;
|
|
503
|
+
if (!inMultiplayerSession
|
|
504
|
+
&& this.activePlayer
|
|
505
|
+
&& this.activePlayer > 1
|
|
506
|
+
&& which > 0
|
|
507
|
+
&& which < 7) {
|
|
508
|
+
playerOffset = this.activePlayer - 1;
|
|
509
|
+
}
|
|
510
|
+
this.handleKeyEvent(which, isPressed, playerOffset);
|
|
511
|
+
}
|
|
512
|
+
handleKeyEvent(key, isPressed, playerOffset = 0) {
|
|
513
|
+
const gameKey = key + 7 * (playerOffset | 0);
|
|
449
514
|
// handle system keys
|
|
450
515
|
switch (key) {
|
|
451
516
|
case pxsim.Key.Reset:
|
|
@@ -475,10 +540,14 @@ var pxsim;
|
|
|
475
540
|
break;
|
|
476
541
|
}
|
|
477
542
|
//this.lastKey = Date.now()
|
|
478
|
-
this.bus.queue(isPressed ? INTERNAL_KEY_DOWN : INTERNAL_KEY_UP,
|
|
479
|
-
|
|
480
|
-
if (
|
|
543
|
+
this.bus.queue(isPressed ? INTERNAL_KEY_DOWN : INTERNAL_KEY_UP, gameKey);
|
|
544
|
+
// no 'any' for p2-4
|
|
545
|
+
if (!playerOffset) {
|
|
546
|
+
this.bus.queue(isPressed ? INTERNAL_KEY_DOWN : INTERNAL_KEY_UP, 0); // "any" key
|
|
547
|
+
}
|
|
548
|
+
if (this.gameplayer) {
|
|
481
549
|
this.gameplayer.buttonChanged(key, isPressed);
|
|
550
|
+
}
|
|
482
551
|
if (this.multiplayerState && key >= pxsim.Key.Left && key <= pxsim.Key.B) {
|
|
483
552
|
this.multiplayerState.setButton(key, isPressed);
|
|
484
553
|
}
|
|
@@ -494,10 +563,10 @@ var pxsim;
|
|
|
494
563
|
}
|
|
495
564
|
resize() { }
|
|
496
565
|
async initAsync(msg) {
|
|
497
|
-
var _a;
|
|
498
566
|
if (msg.options.mpRole) {
|
|
499
567
|
this.multiplayerState.origin = msg.options.mpRole;
|
|
500
568
|
}
|
|
569
|
+
this.setActivePlayer(msg.activePlayer);
|
|
501
570
|
this.runOptions = msg;
|
|
502
571
|
this.stats = document.getElementById("debug-stats");
|
|
503
572
|
this.stats.className = "stats no-select";
|
|
@@ -518,7 +587,7 @@ var pxsim;
|
|
|
518
587
|
let safariEnablePromise;
|
|
519
588
|
if (isFirstRunSafari && !safariEnablePromise) {
|
|
520
589
|
const safariWarning = document.getElementById("safari-enable-game");
|
|
521
|
-
if (isSafari() &&
|
|
590
|
+
if (isSafari() && msg.options && msg.options.mpRole === "server") {
|
|
522
591
|
safariEnablePromise = new Promise(resolve => {
|
|
523
592
|
safariWarning.style.display = "flex";
|
|
524
593
|
safariWarning.addEventListener("click", () => {
|
|
@@ -1262,11 +1331,11 @@ var pxsim;
|
|
|
1262
1331
|
var visuals;
|
|
1263
1332
|
(function (visuals) {
|
|
1264
1333
|
function pressButton(button) {
|
|
1265
|
-
pxsim.board().
|
|
1334
|
+
pxsim.board().setButton(button, true);
|
|
1266
1335
|
}
|
|
1267
1336
|
visuals.pressButton = pressButton;
|
|
1268
1337
|
function releaseButton(button) {
|
|
1269
|
-
pxsim.board().
|
|
1338
|
+
pxsim.board().setButton(button, false);
|
|
1270
1339
|
}
|
|
1271
1340
|
visuals.releaseButton = releaseButton;
|
|
1272
1341
|
function hasPointerEvents() {
|
|
@@ -2799,8 +2868,6 @@ var pxsim;
|
|
|
2799
2868
|
}
|
|
2800
2869
|
multiplayer.postImage = postImage;
|
|
2801
2870
|
function postIcon(iconType, slot, im) {
|
|
2802
|
-
if (pxsim.getMultiplayerState().origin !== "server")
|
|
2803
|
-
return;
|
|
2804
2871
|
if (im._width * im._height > 64 * 64) {
|
|
2805
2872
|
// setting 64x64 as max size for icon for now
|
|
2806
2873
|
return;
|
|
@@ -2841,6 +2908,8 @@ var pxsim;
|
|
|
2841
2908
|
IconType[IconType["Player"] = 0] = "Player";
|
|
2842
2909
|
IconType[IconType["Reaction"] = 1] = "Reaction";
|
|
2843
2910
|
})(IconType = pxsim.IconType || (pxsim.IconType = {}));
|
|
2911
|
+
const MULTIPLAYER_PLAYER_JOINED_ID = 3241;
|
|
2912
|
+
const MULTIPLAYER_PLAYER_LEFT_ID = 3242;
|
|
2844
2913
|
class MultiplayerState {
|
|
2845
2914
|
constructor() {
|
|
2846
2915
|
this.lastMessageId = 0;
|
|
@@ -2873,6 +2942,11 @@ var pxsim;
|
|
|
2873
2942
|
});
|
|
2874
2943
|
}
|
|
2875
2944
|
}
|
|
2945
|
+
registerConnectionState(player, connected) {
|
|
2946
|
+
const evId = connected ? MULTIPLAYER_PLAYER_JOINED_ID : MULTIPLAYER_PLAYER_LEFT_ID;
|
|
2947
|
+
const b = pxsim.board();
|
|
2948
|
+
b.bus.queue(evId, player);
|
|
2949
|
+
}
|
|
2876
2950
|
messageHandler(msg) {
|
|
2877
2951
|
if (!isMultiplayerMessage(msg)) {
|
|
2878
2952
|
return;
|
|
@@ -2906,6 +2980,11 @@ var pxsim;
|
|
|
2906
2980
|
}
|
|
2907
2981
|
}
|
|
2908
2982
|
}
|
|
2983
|
+
else if (isConnectionMessage(msg)) {
|
|
2984
|
+
if (this.origin === "server") {
|
|
2985
|
+
this.registerConnectionState(msg.slot, msg.connected);
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2909
2988
|
}
|
|
2910
2989
|
}
|
|
2911
2990
|
pxsim.MultiplayerState = MultiplayerState;
|
|
@@ -2921,6 +3000,9 @@ var pxsim;
|
|
|
2921
3000
|
function isAudioMessage(msg) {
|
|
2922
3001
|
return msg && msg.content === "Audio";
|
|
2923
3002
|
}
|
|
3003
|
+
function isConnectionMessage(msg) {
|
|
3004
|
+
return msg && msg.content === "Connection";
|
|
3005
|
+
}
|
|
2924
3006
|
})(pxsim || (pxsim = {}));
|
|
2925
3007
|
var pxsim;
|
|
2926
3008
|
(function (pxsim) {
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"Microsoft MakeCode Arcade": "Microsoft MakeCode Arcade",
|
|
45
45
|
"Mouse emulation over HID": "Mouse emulation over HID",
|
|
46
46
|
"Multiplayer Games": "Multiplayer Games",
|
|
47
|
+
"Multiplayer Games!": "Multiplayer Games!",
|
|
47
48
|
"NRF52833 board": "NRF52833 board",
|
|
48
49
|
"NRF52840 board": "NRF52840 board",
|
|
49
50
|
"Networking abstractions": "Networking abstractions",
|
|
50
|
-
"New? Start here!": "New? Start here!",
|
|
51
51
|
"Onboard light level sensor": "Onboard light level sensor",
|
|
52
52
|
"Palette manipulations": "Palette manipulations",
|
|
53
53
|
"Power and sleep management": "Power and sleep management",
|
|
@@ -60,7 +60,6 @@
|
|
|
60
60
|
"Settings storage in internal flash": "Settings storage in internal flash",
|
|
61
61
|
"Seven segment digit display": "Seven segment digit display",
|
|
62
62
|
"Skillmaps": "Skillmaps",
|
|
63
|
-
"Start Skillmap": "Start Skillmap",
|
|
64
63
|
"The accelerometer library": "The accelerometer library",
|
|
65
64
|
"The base library": "The base library",
|
|
66
65
|
"The core library for Codal-based targets": "The core library for Codal-based targets",
|
|
@@ -71,6 +70,7 @@
|
|
|
71
70
|
"The programmable LED (WS2812b,APA102) driver.": "The programmable LED (WS2812b,APA102) driver.",
|
|
72
71
|
"The radio services": "The radio services",
|
|
73
72
|
"The screen library": "The screen library",
|
|
73
|
+
"Try Now": "Try Now",
|
|
74
74
|
"Tutorials": "Tutorials",
|
|
75
75
|
"UART communication": "UART communication",
|
|
76
76
|
"VM": "VM",
|