pxt-arcade 1.13.12 → 1.13.13

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/sim.js CHANGED
@@ -154,12 +154,14 @@ var pxsim;
154
154
  (function (pxsim) {
155
155
  let forcedUpdateLoop;
156
156
  let isFirstRunSafari = true;
157
+ let themeFromQueryParameter = false;
157
158
  window.addEventListener("DOMContentLoaded", () => {
158
159
  const searchParams = new URL(window.location.toString()).searchParams;
159
160
  const setThemeIfDefined = (themeType) => {
160
161
  const paramVal = searchParams.get(themeType);
161
162
  if (paramVal) {
162
- setSimThemeColor(themeType, paramVal);
163
+ themeFromQueryParameter = true;
164
+ pxsim.theme.setSimThemeColor(themeType, paramVal);
163
165
  }
164
166
  };
165
167
  setThemeIfDefined("background-color");
@@ -167,6 +169,11 @@ var pxsim;
167
169
  setThemeIfDefined("text-color");
168
170
  setThemeIfDefined("button-fill");
169
171
  setThemeIfDefined("dpad-fill");
172
+ const skin = searchParams.get("skin");
173
+ if (skin) {
174
+ themeFromQueryParameter = true;
175
+ pxsim.theme.applySkin(skin);
176
+ }
170
177
  if (!!searchParams.get("pointer-events"))
171
178
  registerPointerEvents();
172
179
  if (!!searchParams.get("hideSimButtons"))
@@ -174,6 +181,10 @@ var pxsim;
174
181
  if (!!searchParams.get("noExtraPadding"))
175
182
  noExtraPadding();
176
183
  });
184
+ if (hasNavigator()) {
185
+ // only XBOX webview looks at this, to get rid of cursor
186
+ navigator.gamepadInputEmulation = "gamepad";
187
+ }
177
188
  function hideSimButtons() {
178
189
  const gamePlayer = document.getElementsByClassName("game-player");
179
190
  if (gamePlayer && gamePlayer.length) {
@@ -237,33 +248,17 @@ var pxsim;
237
248
  canvas.addEventListener("pointerout", reporter);
238
249
  canvas.addEventListener("wheel", wheelReporter);
239
250
  }
240
- function setSimThemeColor(part, color, elOverride) {
241
- if (!part || (!(color == undefined || /^[0-9A-F]{6}$/i.test(color))))
242
- return;
243
- if (part != "background-color"
244
- && part != "button-stroke"
245
- && part != "text-color"
246
- && part != "button-fill"
247
- && part != "dpad-fill") {
248
- return;
249
- }
250
- const propName = `--sim-${part}`;
251
- const propColor = color ? `#${color}` : undefined;
252
- const wrapper = elOverride || document.getElementById("wrap");
253
- if (propColor) {
254
- wrapper.style.setProperty(propName, propColor);
255
- }
256
- else {
257
- wrapper.style.removeProperty(propName);
258
- }
259
- }
260
251
  /**
261
252
  * This function gets called each time the program restarts
262
253
  */
263
254
  pxsim.initCurrentRuntime = (msg) => {
264
255
  pxsim.runtime.board = new Board();
265
256
  pxsim.initGamepad();
266
- board().setActivePlayer(msg.activePlayer);
257
+ const theme = pxsim.theme.parseTheme(msg.theme);
258
+ if (theme && !themeFromQueryParameter) {
259
+ pxsim.theme.applyTheme(theme);
260
+ }
261
+ board().setActivePlayer(msg.activePlayer, theme);
267
262
  if (!forcedUpdateLoop) {
268
263
  forcedUpdateLoop = true;
269
264
  // this is used to force screen update if game loop is stuck or not set up properly
@@ -375,11 +370,11 @@ var pxsim;
375
370
  if (ev.data.type == "setactiveplayer") {
376
371
  const b = board();
377
372
  if (!(b.multiplayerState && b.multiplayerState.origin)) {
378
- b.setActivePlayer(ev.data.playerNumber);
373
+ b.setActivePlayer(ev.data.playerNumber, theme);
379
374
  }
380
375
  }
381
376
  else if (ev.data.type == "setsimthemecolor") {
382
- setSimThemeColor(ev.data.part, (_a = ev.data.color) === null || _a === void 0 ? void 0 : _a.replace("#", ""));
377
+ pxsim.theme.setSimThemeColor(ev.data.part, (_a = ev.data.color) === null || _a === void 0 ? void 0 : _a.replace("#", ""));
383
378
  }
384
379
  });
385
380
  }
@@ -464,29 +459,24 @@ var pxsim;
464
459
  throttleAnimation((cb) => (this.screenState.onChange = cb), () => this.gameplayer.draw(this.screenState));
465
460
  this.activePlayer = undefined;
466
461
  }
467
- setActivePlayer(playerNumber) {
462
+ setActivePlayer(playerNumber, theme) {
468
463
  if (this.multiplayerState && this.multiplayerState.origin)
469
464
  return;
470
- // TODO: this is duplicated in pxt/multiplayer's ArcadeSimulator.tsx;
471
- // we could dedup this by starting a set of 'named' themes in the future
472
- // (e.g. player1, player2, hotrodflames, ...)
473
- // [[backgroundColor, buttonStroke]]
474
465
  const playerThemes = [
475
- [undefined, undefined],
476
- ["ED3636", "8D2525"],
477
- ["4E4EE9", "3333A1"],
478
- ["FF9A14", "B0701A"],
479
- ["4EB94E", "245D24"],
466
+ undefined,
467
+ "p1",
468
+ "p2",
469
+ "p3",
470
+ "p4",
480
471
  ];
481
472
  const newPlayerTheme = playerThemes[playerNumber || 0];
482
473
  if (!newPlayerTheme) {
483
474
  // invalid playerNumber
484
475
  return;
485
476
  }
486
- const themeOverrideElement = document.querySelector(".game-player");
487
- setSimThemeColor("background-color", newPlayerTheme[0], themeOverrideElement);
488
- setSimThemeColor("button-stroke", newPlayerTheme[1], themeOverrideElement);
489
- setSimThemeColor("dpad-fill", newPlayerTheme[1], themeOverrideElement);
477
+ if ((!theme || !Object.keys(theme).length) && !themeFromQueryParameter) {
478
+ pxsim.theme.applySkin(newPlayerTheme);
479
+ }
490
480
  this.activePlayer = playerNumber || undefined;
491
481
  }
492
482
  getDefaultPitchPin() {
@@ -571,26 +561,25 @@ var pxsim;
571
561
  }
572
562
  resize() { }
573
563
  async initAsync(msg) {
574
- if (msg.options.mpRole) {
575
- this.multiplayerState.origin = msg.options.mpRole;
576
- }
577
- this.setActivePlayer(msg.activePlayer);
578
564
  this.runOptions = msg;
579
565
  this.stats = document.getElementById("debug-stats");
580
566
  this.stats.className = "stats no-select";
581
567
  this.id = msg.id;
582
568
  indicateFocus(document.hasFocus());
583
569
  this.accelerometerState.attachEvents(document.body);
584
- if (this.runOptions && this.runOptions.options) {
585
- const mpRole = this.runOptions.options.mpRole;
586
- if (mpRole) {
587
- this.multiplayerState.init(mpRole);
588
- if (mpRole === "client") {
589
- const wrapper = document.getElementById("wrap");
590
- wrapper && wrapper.classList.add("mp-client");
591
- }
592
- }
593
- }
570
+ const mpRole = this.runOptions
571
+ && this.runOptions.options
572
+ && this.runOptions.options.mpRole;
573
+ this.multiplayerState.init(mpRole);
574
+ if (mpRole === "client") {
575
+ const wrapper = document.getElementById("wrap");
576
+ wrapper && wrapper.classList.add("mp-client");
577
+ }
578
+ const theme = pxsim.theme.parseTheme(msg.theme);
579
+ if (theme && !themeFromQueryParameter) {
580
+ pxsim.theme.applyTheme(theme);
581
+ }
582
+ this.setActivePlayer(msg.activePlayer, theme);
594
583
  this.updateStats();
595
584
  let safariEnablePromise;
596
585
  if (isFirstRunSafari && !safariEnablePromise) {
@@ -700,10 +689,185 @@ function isSafari() {
700
689
  })(ButtonMethods = pxsim.ButtonMethods || (pxsim.ButtonMethods = {}));
701
690
  })(pxsim || (pxsim = {}));
702
691
  var pxsim;
692
+ (function (pxsim) {
693
+ var theme;
694
+ (function (theme_1) {
695
+ function parseTheme(theme) {
696
+ if (!theme)
697
+ return undefined;
698
+ return (typeof theme == "string") ? { skin: theme } : theme;
699
+ }
700
+ theme_1.parseTheme = parseTheme;
701
+ function applyTheme(theme) {
702
+ const parsedTheme = parseTheme(theme);
703
+ if (parsedTheme.skin) {
704
+ applySkin(parsedTheme.skin.toLowerCase());
705
+ }
706
+ const setThemeIfDefined = (themeType) => {
707
+ const paramVal = parsedTheme[themeType];
708
+ if (paramVal) {
709
+ setSimThemeColor(themeType, paramVal);
710
+ }
711
+ };
712
+ setThemeIfDefined("background-color");
713
+ setThemeIfDefined("button-stroke");
714
+ setThemeIfDefined("text-color");
715
+ setThemeIfDefined("button-fill");
716
+ setThemeIfDefined("dpad-fill");
717
+ }
718
+ theme_1.applyTheme = applyTheme;
719
+ function setSimThemeColor(part, color) {
720
+ if (!part || (!(color == undefined || /^(#|0x)?[0-9A-F]{6}$/i.test(color))))
721
+ return;
722
+ if (part != "background-color"
723
+ && part != "button-stroke"
724
+ && part != "text-color"
725
+ && part != "button-fill"
726
+ && part != "dpad-fill") {
727
+ return;
728
+ }
729
+ const propName = `--sim-${part}`;
730
+ const propColor = color ? `#${color.replace(/^(#|0x)/i, "")}` : undefined;
731
+ const wrapper = document.getElementById("wrap");
732
+ if (propColor) {
733
+ wrapper.style.setProperty(propName, propColor);
734
+ }
735
+ else {
736
+ wrapper.style.removeProperty(propName);
737
+ }
738
+ }
739
+ theme_1.setSimThemeColor = setSimThemeColor;
740
+ function applySkin(skin) {
741
+ switch (skin) {
742
+ case "zune": {
743
+ zuneSkin();
744
+ break;
745
+ }
746
+ case "p1":
747
+ case "red": {
748
+ redSkin();
749
+ break;
750
+ }
751
+ case "p2":
752
+ case "blue": {
753
+ blueSkin();
754
+ break;
755
+ }
756
+ case "p3":
757
+ case "orange": {
758
+ orangeSkin();
759
+ break;
760
+ }
761
+ case "p4":
762
+ case "green": {
763
+ greenSkin();
764
+ break;
765
+ }
766
+ case "brown": {
767
+ brownSkin();
768
+ break;
769
+ }
770
+ case "bubblegum": {
771
+ bubblegumSkin();
772
+ break;
773
+ }
774
+ case "purple": {
775
+ purpleSkin();
776
+ break;
777
+ }
778
+ case "microcode": {
779
+ microcodeSkin();
780
+ break;
781
+ }
782
+ default:
783
+ break;
784
+ }
785
+ }
786
+ theme_1.applySkin = applySkin;
787
+ function zuneSkin() {
788
+ setSimThemeColor("background-color", "#564131");
789
+ setSimThemeColor("button-stroke", "#524F4E");
790
+ setSimThemeColor("text-color", "#E7E7E7");
791
+ const wrapper = document.getElementById("wrap");
792
+ if (wrapper) {
793
+ wrapper.classList.add("zune", "portrait-only");
794
+ /** SVG overriding a, b button positions: b on left, a on right
795
+ <svg class="game-button-svg" viewBox="0 0 40 40"=>"0 0 100 28">
796
+ <circle class="button-b" cx="13"=>"18" cy="28"=>"12" />
797
+ <text class="label-b no-select" x="13"=>"18" y="28"=>"12">B</text>
798
+ <circle class="button-a" cx="28"=>"82" cy="12.5"=>"12"/>
799
+ <text class="label-a no-select" x="28"=>"82" y="12.5"=>"12">A</text>
800
+ </svg>
801
+ // simplify viewBox
802
+ <svg class="game-joystick-svg" viewBox="1 0 40 40"=>"0 0 40 40"/>
803
+ **/
804
+ const gameButtonSvg = document.querySelector(".game-button-svg");
805
+ gameButtonSvg.removeAttribute("width");
806
+ gameButtonSvg.removeAttribute("height");
807
+ gameButtonSvg.setAttribute("viewBox", "0 0 100 28");
808
+ const joystickSvg = document.querySelector(".game-joystick-svg");
809
+ joystickSvg.setAttribute("viewBox", "0 0 40 40");
810
+ const bButton = document.querySelector(".button-b");
811
+ const bLabel = document.querySelector(".label-b");
812
+ bButton.setAttribute("cx", "18");
813
+ bButton.setAttribute("cy", "12");
814
+ bLabel.setAttribute("x", "18");
815
+ bLabel.setAttribute("y", "12");
816
+ const aButton = document.querySelector(".button-a");
817
+ const aLabel = document.querySelector(".label-a");
818
+ aButton.setAttribute("cx", "82");
819
+ aButton.setAttribute("cy", "12");
820
+ aLabel.setAttribute("x", "82");
821
+ aLabel.setAttribute("y", "12");
822
+ }
823
+ }
824
+ function brownSkin() {
825
+ setSimThemeColor("background-color", "#8B4513");
826
+ setSimThemeColor("button-stroke", "#68320C");
827
+ }
828
+ function bubblegumSkin() {
829
+ setSimThemeColor("background-color", "#F7ABB9");
830
+ setSimThemeColor("button-stroke", "#71C1C9");
831
+ setSimThemeColor("button-fill", "#92F5FF");
832
+ setSimThemeColor("text-color", "#4E4E4E");
833
+ setSimThemeColor("dpad-fill", "#F7ABB9");
834
+ const msftLogo = document.querySelector(".game-player-msft");
835
+ if (msftLogo) {
836
+ msftLogo.classList.add("gray");
837
+ }
838
+ }
839
+ function redSkin() {
840
+ setSimThemeColor("background-color", "#ED3636");
841
+ setSimThemeColor("button-stroke", "#8D2525");
842
+ }
843
+ function blueSkin() {
844
+ setSimThemeColor("background-color", "#4E4EE9");
845
+ setSimThemeColor("button-stroke", "#3333A1");
846
+ }
847
+ function orangeSkin() {
848
+ setSimThemeColor("background-color", "#FF9A14");
849
+ setSimThemeColor("button-stroke", "#B0701A");
850
+ }
851
+ function greenSkin() {
852
+ setSimThemeColor("background-color", "#4EB94E");
853
+ setSimThemeColor("button-stroke", "#245D24");
854
+ }
855
+ function purpleSkin() {
856
+ setSimThemeColor("background-color", "#660fC7");
857
+ setSimThemeColor("button-stroke", "#4C0B95");
858
+ }
859
+ function microcodeSkin() {
860
+ setSimThemeColor("background-color", "#3F3F3F");
861
+ setSimThemeColor("button-stroke", "#212121");
862
+ setSimThemeColor("button-fill", "#2D2D2D");
863
+ setSimThemeColor("text-color", "#D9D9D9");
864
+ }
865
+ })(theme = pxsim.theme || (pxsim.theme = {}));
866
+ })(pxsim || (pxsim = {}));
867
+ var pxsim;
703
868
  (function (pxsim) {
704
869
  var visuals;
705
870
  (function (visuals) {
706
- const SVG_WIDTH = 40;
707
871
  class GameButtons {
708
872
  // <div id="game-buttons-container" class="game-buttons">
709
873
  // <div class="spacer" />
@@ -765,14 +929,16 @@ var pxsim;
765
929
  });
766
930
  this.bindings = [];
767
931
  }
932
+ pointIsWithinCircle(x, y, circle) {
933
+ const bounds = circle.getBoundingClientRect();
934
+ const radius = bounds.width / 2;
935
+ const distance = Math.sqrt(Math.pow(x - (bounds.left + radius), 2)
936
+ + Math.pow(y - (bounds.top + radius), 2));
937
+ return distance < radius;
938
+ }
768
939
  updateButtonGesture(x, y) {
769
- const bounds = this.dragSurface.getBoundingClientRect();
770
- const dx = ((x - bounds.left) * (SVG_WIDTH / bounds.width));
771
- const dy = ((y - bounds.top) * (SVG_WIDTH / bounds.height));
772
- const aDistance = Math.sqrt(Math.pow(dx - 30, 2) + Math.pow(dy - 15, 2));
773
- const bDistance = Math.sqrt(Math.pow(dx - 15, 2) + Math.pow(dy - 28, 2));
774
- this.setButtonState(pxsim.Key.A, aDistance < 8);
775
- this.setButtonState(pxsim.Key.B, bDistance < 8);
940
+ this.setButtonState(pxsim.Key.A, this.pointIsWithinCircle(x, y, this.aButton));
941
+ this.setButtonState(pxsim.Key.B, this.pointIsWithinCircle(x, y, this.bButton));
776
942
  pxsim.indicateFocus(true);
777
943
  }
778
944
  clearButtonPresses() {
@@ -919,10 +1085,9 @@ var pxsim;
919
1085
  this.screen = document.getElementById("game-screen");
920
1086
  this.menu = document.getElementsByClassName("game-menu-button")[0];
921
1087
  this.reset = document.getElementsByClassName("game-reset-button")[0];
922
- // TODO: localize; currently can't use lf in this repo
923
- this.menu.setAttribute("aria-label", "Menu");
924
- this.reset.setAttribute("aria-label", "Reset Game");
925
1088
  if (this.menu) {
1089
+ // TODO: localize; currently can't use lf in this repo
1090
+ this.menu.setAttribute("aria-label", "Menu");
926
1091
  this.menu.onclick = () => {
927
1092
  visuals.pressButton(pxsim.Key.Menu);
928
1093
  visuals.releaseButton(pxsim.Key.Menu);
@@ -930,6 +1095,7 @@ var pxsim;
930
1095
  };
931
1096
  }
932
1097
  if (this.reset) {
1098
+ this.reset.setAttribute("aria-label", "Reset Game");
933
1099
  this.reset.onclick = () => {
934
1100
  visuals.pressButton(pxsim.Key.Reset);
935
1101
  visuals.releaseButton(pxsim.Key.Reset);
@@ -998,12 +1164,12 @@ var pxsim;
998
1164
  }
999
1165
  indicateFocus(focused) {
1000
1166
  if (focused) {
1001
- this.menu.setAttribute("aria-disabled", "false");
1002
- this.reset.setAttribute("aria-disabled", "false");
1167
+ this.menu && this.menu.setAttribute("aria-disabled", "false");
1168
+ this.reset && this.reset.setAttribute("aria-disabled", "false");
1003
1169
  }
1004
1170
  else {
1005
- this.menu.setAttribute("aria-disabled", "true");
1006
- this.reset.setAttribute("aria-disabled", "true");
1171
+ this.menu && this.menu.setAttribute("aria-disabled", "true");
1172
+ this.reset && this.reset.setAttribute("aria-disabled", "true");
1007
1173
  }
1008
1174
  }
1009
1175
  }