pxt-common-packages 10.2.5 → 10.2.7

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.
Files changed (34) hide show
  1. package/built/common-sim.d.ts +5 -0
  2. package/built/common-sim.js +28 -4
  3. package/libs/azureiot/built/debug/binary.js +461 -461
  4. package/libs/color/built/debug/binary.js +8 -8
  5. package/libs/color-sensor/built/debug/binary.js +8 -8
  6. package/libs/controller/built/debug/binary.js +6968 -6968
  7. package/libs/controller---none/built/debug/binary.js +6950 -6950
  8. package/libs/datalogger/built/debug/binary.js +63 -63
  9. package/libs/edge-connector/built/debug/binary.js +8 -8
  10. package/libs/esp32/built/debug/binary.js +462 -462
  11. package/libs/game/_locales/game-jsdoc-strings.json +1 -0
  12. package/libs/game/built/debug/binary.js +6889 -6889
  13. package/libs/game/controller.ts +27 -3
  14. package/libs/game/info.ts +263 -91
  15. package/libs/game/sim/multiplayer.ts +38 -8
  16. package/libs/lcd/built/debug/binary.js +8 -8
  17. package/libs/light-spectrum-sensor/built/debug/binary.js +8 -8
  18. package/libs/lora/built/debug/binary.js +8 -8
  19. package/libs/matrix-keypad/built/debug/binary.js +8 -8
  20. package/libs/mqtt/built/debug/binary.js +176 -176
  21. package/libs/net/built/debug/binary.js +176 -176
  22. package/libs/net-game/built/debug/binary.js +8478 -8478
  23. package/libs/palette/built/debug/binary.js +6888 -6888
  24. package/libs/pixel/built/debug/binary.js +8 -8
  25. package/libs/power/built/debug/binary.js +8 -8
  26. package/libs/proximity/built/debug/binary.js +8 -8
  27. package/libs/radio/built/debug/binary.js +8 -8
  28. package/libs/radio-broadcast/built/debug/binary.js +8 -8
  29. package/libs/rotary-encoder/built/debug/binary.js +8 -8
  30. package/libs/screen/built/debug/binary.js +50 -50
  31. package/libs/servo/built/debug/binary.js +8 -8
  32. package/libs/sprite-scaling/built/debug/binary.js +6888 -6888
  33. package/libs/storyboard/built/debug/binary.js +6888 -6888
  34. package/package.json +2 -2
@@ -164,7 +164,14 @@ namespace controller {
164
164
  //% group="Multiplayer"
165
165
  //% vx.shadow="spriteSpeedPicker"
166
166
  //% vy.shadow="spriteSpeedPicker"
167
+ //% parts="multiplayer"
167
168
  moveSprite(sprite: Sprite, vx: number = 100, vy: number = 100) {
169
+ this._moveSpriteInternal(sprite, vx, vy);
170
+ }
171
+
172
+ // use this instead of movesprite internally to avoid adding the "multiplayer" part
173
+ // to the compiled program
174
+ _moveSpriteInternal(sprite: Sprite, vx: number = 100, vy: number = 100) {
168
175
  if (!sprite) return;
169
176
  if (!this._controlledSprites) this._controlledSprites = [];
170
177
  let cp = this._controlledSprites.find(cp => cp.s.id == sprite.id);
@@ -193,6 +200,7 @@ namespace controller {
193
200
  //% blockId=ctrlonbuttonevent block="on %controller %button **button** %event"
194
201
  //% group="Multiplayer"
195
202
  //% help=controller/on-button-event
203
+ //% parts="multiplayer"
196
204
  onButtonEvent(btn: ControllerButton, event: ControllerButtonEvent, handler: () => void) {
197
205
  this.button(btn).onEvent(event, handler);
198
206
  }
@@ -206,6 +214,7 @@ namespace controller {
206
214
  //% blockId=ctrlonevent block="on %controller %event"
207
215
  //% group="Multiplayer"
208
216
  //% help=controller/on-event
217
+ //% parts="multiplayer"
209
218
  onEvent(event: ControllerEvent, handler: () => void) {
210
219
  control.onEvent(this.id, event, handler);
211
220
  }
@@ -227,6 +236,7 @@ namespace controller {
227
236
  //% weight=96 blockGap=8 help=controller/button/is-pressed
228
237
  //% blockId=ctrlispressed block="is %controller %button **button** pressed"
229
238
  //% group="Multiplayer"
239
+ //% parts="multiplayer"
230
240
  isPressed(btn: ControllerButton): boolean {
231
241
  return this.button(btn).isPressed();
232
242
  }
@@ -239,7 +249,14 @@ namespace controller {
239
249
  //% blockId=ctrldx block="%controller dx (left-right buttons)||scaled by %step"
240
250
  //% step.defl=100
241
251
  //% group="Multiplayer"
252
+ //% parts="multiplayer"
242
253
  dx(step: number = 100) {
254
+ return this._dxInternal(step);
255
+ }
256
+
257
+ // use this instead of dx internally to avoid adding the "multiplayer" part
258
+ // to the compiled program
259
+ _dxInternal(step: number = 100) {
243
260
  const ctx = control.eventContext();
244
261
  if (!ctx) return 0;
245
262
 
@@ -261,7 +278,14 @@ namespace controller {
261
278
  //% blockId=ctrldy block="%controller dy (up-down buttons)||scaled by %step"
262
279
  //% step.defl=100
263
280
  //% group="Multiplayer"
281
+ //% parts="multiplayer"
264
282
  dy(step: number = 100) {
283
+ return this._dyInternal(step);
284
+ }
285
+
286
+ // use this instead of dy internally to avoid adding the "multiplayer" part
287
+ // to the compiled program
288
+ _dyInternal(step: number = 100) {
265
289
  const ctx = control.eventContext();
266
290
  if (!ctx) return 0;
267
291
 
@@ -386,7 +410,7 @@ namespace controller {
386
410
  //% vx.shadow=spriteSpeedPicker
387
411
  //% vy.shadow=spriteSpeedPicker
388
412
  export function moveSprite(sprite: Sprite, vx: number = 100, vy: number = 100) {
389
- _player1().moveSprite(sprite, vx, vy);
413
+ _player1()._moveSpriteInternal(sprite, vx, vy);
390
414
  }
391
415
 
392
416
  /**
@@ -398,7 +422,7 @@ namespace controller {
398
422
  //% step.defl=100
399
423
  //% group="Single Player"
400
424
  export function dx(step: number = 100) {
401
- return _player1().dx(step);
425
+ return _player1()._dxInternal(step);
402
426
  }
403
427
 
404
428
  /**
@@ -410,7 +434,7 @@ namespace controller {
410
434
  //% step.defl=100
411
435
  //% group="Single Player"
412
436
  export function dy(step: number = 100) {
413
- return _player1().dy(step);
437
+ return _player1()._dyInternal(step);
414
438
  }
415
439
 
416
440
  class AnyButton extends Button {
package/libs/game/info.ts CHANGED
@@ -121,18 +121,18 @@ namespace info {
121
121
  // First draw players
122
122
  ps.forEach(p => p.drawPlayer());
123
123
  // Then run life over events
124
- ps.forEach(p => p.raiseLifeZero(false));
124
+ ps.forEach(p => p.impl.raiseLifeZero(false));
125
125
  } else { // single player
126
126
  // show score
127
127
  const p = player1;
128
- if (p.hasScore() && (infoState.visibilityFlag & Visibility.Score)) {
128
+ if (p.impl.hasScore() && (infoState.visibilityFlag & Visibility.Score)) {
129
129
  p.drawScore();
130
130
  }
131
131
  // show life
132
- if (p.hasLife() && (infoState.visibilityFlag & Visibility.Life)) {
132
+ if (p.impl.hasLife() && (infoState.visibilityFlag & Visibility.Life)) {
133
133
  p.drawLives();
134
134
  }
135
- p.raiseLifeZero(true);
135
+ p.impl.raiseLifeZero(true);
136
136
  }
137
137
  // show countdown in both modes
138
138
  if (infoState.gameEnd !== undefined && infoState.visibilityFlag & Visibility.Countdown) {
@@ -216,7 +216,7 @@ namespace info {
216
216
  const allScoresKey = "all-scores";
217
217
  let allScores: number[];
218
218
  if (players) {
219
- allScores = players.filter(item => item.hasScore()).map(item => item.score());
219
+ allScores = players.filter(item => item.impl.hasScore()).map(item => item.impl.score());
220
220
  }
221
221
  else {
222
222
  allScores = [];
@@ -229,8 +229,8 @@ namespace info {
229
229
  if (players) {
230
230
  let hs = 0;
231
231
  players
232
- .filter(p => p && p.hasScore())
233
- .forEach(p => hs = Math.max(hs, p.score()));
232
+ .filter(p => p && p.impl.hasScore())
233
+ .forEach(p => hs = Math.max(hs, p.impl.score()));
234
234
  const curr = settings.readNumber("high-score")
235
235
  if (curr == null || hs > curr)
236
236
  settings.writeNumber("high-score", hs);
@@ -245,13 +245,13 @@ namespace info {
245
245
  //% help=info/score
246
246
  //% group="Score"
247
247
  export function score() {
248
- return player1.score();
248
+ return player1.impl.score();
249
249
  }
250
250
 
251
251
  //%
252
252
  //% group="Score"
253
253
  export function hasScore() {
254
- return player1.hasScore();
254
+ return player1.impl.hasScore();
255
255
  }
256
256
 
257
257
  /**
@@ -273,7 +273,7 @@ namespace info {
273
273
  //% help=info/set-score
274
274
  //% group="Score"
275
275
  export function setScore(value: number) {
276
- player1.setScore(value);
276
+ player1.impl.setScore(value);
277
277
  }
278
278
 
279
279
  /**
@@ -285,7 +285,7 @@ namespace info {
285
285
  //% help=info/change-score-by
286
286
  //% group="Score"
287
287
  export function changeScoreBy(value: number) {
288
- player1.changeScoreBy(value);
288
+ player1.impl.changeScoreBy(value);
289
289
  }
290
290
 
291
291
  /**
@@ -296,12 +296,12 @@ namespace info {
296
296
  //% help=info/life
297
297
  //% group="Life"
298
298
  export function life() {
299
- return player1.life();
299
+ return player1.impl.life();
300
300
  }
301
301
 
302
302
  //% group="Life"
303
303
  export function hasLife() {
304
- return player1.hasLife();
304
+ return player1.impl.hasLife();
305
305
  }
306
306
 
307
307
  /**
@@ -313,7 +313,7 @@ namespace info {
313
313
  //% help=info/set-life
314
314
  //% group="Life"
315
315
  export function setLife(value: number) {
316
- player1.setLife(value);
316
+ player1.impl.setLife(value);
317
317
  }
318
318
 
319
319
  /**
@@ -325,7 +325,7 @@ namespace info {
325
325
  //% help=info/change-life-by
326
326
  //% group="Life"
327
327
  export function changeLifeBy(value: number) {
328
- player1.changeLifeBy(value);
328
+ player1.impl.changeLifeBy(value);
329
329
  }
330
330
 
331
331
  /**
@@ -337,7 +337,7 @@ namespace info {
337
337
  //% help=info/on-life-zero
338
338
  //% group="Life"
339
339
  export function onLifeZero(handler: () => void) {
340
- player1.onLifeZero(handler);
340
+ player1.impl.onLifeZero(handler);
341
341
  }
342
342
 
343
343
  /**
@@ -355,7 +355,7 @@ namespace info {
355
355
  //% help=info/on-score
356
356
  //% group="Score"
357
357
  export function onScore(score: number, handler: () => void) {
358
- player1.onScore(score, handler);
358
+ player1.impl.onScore(score, handler);
359
359
  }
360
360
 
361
361
  /**
@@ -564,9 +564,14 @@ namespace info {
564
564
  }
565
565
  }
566
566
 
567
- //% fixedInstances
568
- //% blockGap=8
569
- export class PlayerInfo {
567
+ /**
568
+ * Splits the implementation of the player info from the user-facing APIs so that
569
+ * we can reference this internally without causing the "multiplayer" part to show
570
+ * up in the usedParts array of the user program's compile result. Make sure to
571
+ * use the APIs on this class and not the PlayerInfo to avoid false-positives when
572
+ * we detect if a game is multiplayer or not
573
+ */
574
+ export class PlayerInfoImpl {
570
575
  protected _player: number;
571
576
  public bg: number; // background color
572
577
  public border: number; // border color
@@ -614,9 +619,6 @@ namespace info {
614
619
  this.left = true;
615
620
  this.up = true;
616
621
  }
617
-
618
- if (!players) players = [];
619
- players[this._player - 1] = this;
620
622
  }
621
623
 
622
624
  private init() {
@@ -637,12 +639,6 @@ namespace info {
637
639
  return this._player;
638
640
  }
639
641
 
640
- /**
641
- * Get the player score
642
- */
643
- //% group="Multiplayer"
644
- //% blockId=piscore block="%player score"
645
- //% help=info/score
646
642
  score(): number {
647
643
  if (this.showScore === undefined) this.showScore = true;
648
644
  if (this.showPlayer === undefined) this.showPlayer = true;
@@ -654,13 +650,6 @@ namespace info {
654
650
  return state.score;
655
651
  }
656
652
 
657
- /**
658
- * Set the player score
659
- */
660
- //% group="Multiplayer"
661
- //% blockId=pisetscore block="set %player score to %value"
662
- //% value.defl=0
663
- //% help=info/set-score
664
653
  setScore(value: number) {
665
654
  const state = this.getState();
666
655
  if (!(infoState.visibilityFlag & Visibility._ExplicitlySetScore)) {
@@ -680,6 +669,211 @@ namespace info {
680
669
  }
681
670
  }
682
671
 
672
+ changeScoreBy(value: number): void {
673
+ this.setScore(this.score() + value);
674
+ }
675
+
676
+ hasScore() {
677
+ const state = this.getState();
678
+ return state.score !== undefined;
679
+ }
680
+
681
+ life(): number {
682
+ const state = this.getState();
683
+ if (this.showLife === undefined) this.showLife = true;
684
+ if (this.showPlayer === undefined) this.showPlayer = true;
685
+
686
+ if (state.life === undefined) {
687
+ state.life = 3;
688
+ }
689
+ return state.life || 0;
690
+ }
691
+
692
+ setLife(value: number): void {
693
+ const state = this.getState();
694
+ if (!(infoState.visibilityFlag & Visibility._ExplicitlySetLife)) {
695
+ updateFlag(Visibility.Life, true);
696
+ }
697
+
698
+ this.life(); // invoked for side effects
699
+ state.life = (value | 0);
700
+ }
701
+
702
+ changeLifeBy(value: number): void {
703
+ this.setLife(this.life() + value);
704
+ }
705
+
706
+ hasLife(): boolean {
707
+ const state = this.getState();
708
+ return state.life !== undefined && state.life !== null;
709
+ }
710
+
711
+ onLifeZero(handler: () => void) {
712
+ const state = this.getState();
713
+ state.lifeZeroHandler = handler;
714
+ }
715
+
716
+ onScore(score: number, handler: () => void) {
717
+ const state = this.getState();
718
+ state.scoreReachedHandler = new ScoreReachedHandler(score, handler);
719
+ }
720
+
721
+ raiseLifeZero(gameOver: boolean) {
722
+ const state = this.getState();
723
+ if (state.life !== null && state.life <= 0) {
724
+ state.life = null;
725
+ if (state.lifeZeroHandler) {
726
+ state.lifeZeroHandler();
727
+ } else if (gameOver) {
728
+ game.over();
729
+ }
730
+ }
731
+ }
732
+ }
733
+
734
+ //% fixedInstances
735
+ //% blockGap=8
736
+ export class PlayerInfo {
737
+ protected _player: number;
738
+ public impl: PlayerInfoImpl;
739
+
740
+ constructor(player: number) {
741
+ this._player = player;
742
+ this.impl = new PlayerInfoImpl(player);
743
+
744
+ if (!players) players = [];
745
+ players[this._player - 1] = this;
746
+ }
747
+
748
+ private init() {
749
+ initHUD();
750
+ if (this._player > 1) initMultiHUD();
751
+ if (!infoState.playerStates[this._player - 1]) {
752
+ infoState.playerStates[this._player - 1] = new PlayerState();
753
+ }
754
+ }
755
+
756
+ get bg(): number {
757
+ return this.impl.bg;
758
+ }
759
+
760
+ set bg(value: number) {
761
+ this.impl.bg = value;
762
+ }
763
+
764
+ get border(): number {
765
+ return this.impl.border;
766
+ }
767
+
768
+ set border(value: number) {
769
+ this.impl.border = value;
770
+ }
771
+
772
+ get fc(): number {
773
+ return this.impl.fc;
774
+ }
775
+
776
+ set fc(value: number) {
777
+ this.impl.fc = value;
778
+ }
779
+
780
+ get showScore(): boolean {
781
+ return this.impl.showScore;
782
+ }
783
+
784
+ set showScore(value: boolean) {
785
+ this.impl.showScore = value;
786
+ }
787
+
788
+ get showLife(): boolean {
789
+ return this.impl.showLife;
790
+ }
791
+
792
+ set showLife(value: boolean) {
793
+ this.impl.showLife = value;
794
+ }
795
+
796
+ get visibility(): Visibility {
797
+ return this.impl.visibility;
798
+ }
799
+
800
+ set visibility(value: Visibility) {
801
+ this.impl.visibility = value;
802
+ }
803
+
804
+ get showPlayer(): boolean {
805
+ return this.impl.showPlayer;
806
+ }
807
+
808
+ set showPlayer(value: boolean) {
809
+ this.impl.showPlayer = value;
810
+ }
811
+
812
+ get x(): number {
813
+ return this.impl.x;
814
+ }
815
+
816
+ set x(value: number) {
817
+ this.impl.x = value;
818
+ }
819
+
820
+ get y(): number {
821
+ return this.impl.y;
822
+ }
823
+
824
+ set y(value: number) {
825
+ this.impl.y = value;
826
+ }
827
+
828
+ get left(): boolean {
829
+ return this.impl.left;
830
+ }
831
+
832
+ set left(value: boolean) {
833
+ this.impl.left = value;
834
+ }
835
+
836
+ get up(): boolean {
837
+ return this.impl.up;
838
+ }
839
+
840
+ set up(value: boolean) {
841
+ this.impl.up = value;
842
+ }
843
+
844
+ getState(): PlayerState {
845
+ this.init();
846
+ return infoState.playerStates[this._player - 1];
847
+ }
848
+
849
+ // the id numbera of the player
850
+ id(): number {
851
+ return this.impl.id();
852
+ }
853
+
854
+ /**
855
+ * Get the player score
856
+ */
857
+ //% group="Multiplayer"
858
+ //% blockId=piscore block="%player score"
859
+ //% help=info/score
860
+ //% parts="multiplayer"
861
+ score(): number {
862
+ return this.impl.score();
863
+ }
864
+
865
+ /**
866
+ * Set the player score
867
+ */
868
+ //% group="Multiplayer"
869
+ //% blockId=pisetscore block="set %player score to %value"
870
+ //% value.defl=0
871
+ //% help=info/set-score
872
+ //% parts="multiplayer"
873
+ setScore(value: number) {
874
+ this.impl.setScore(value);
875
+ }
876
+
683
877
  /**
684
878
  * Change the score of a player
685
879
  * @param value
@@ -688,13 +882,13 @@ namespace info {
688
882
  //% blockId=pichangescore block="change %player score by %value"
689
883
  //% value.defl=1
690
884
  //% help=info/change-score-by
885
+ //% parts="multiplayer"
691
886
  changeScoreBy(value: number): void {
692
- this.setScore(this.score() + value);
887
+ this.impl.changeScoreBy(value);
693
888
  }
694
889
 
695
890
  hasScore() {
696
- const state = this.getState();
697
- return state.score !== undefined;
891
+ return this.impl.hasScore();
698
892
  }
699
893
 
700
894
  /**
@@ -703,15 +897,9 @@ namespace info {
703
897
  //% group="Multiplayer"
704
898
  //% blockid=piflife block="%player life"
705
899
  //% help=info/life
900
+ //% parts="multiplayer"
706
901
  life(): number {
707
- const state = this.getState();
708
- if (this.showLife === undefined) this.showLife = true;
709
- if (this.showPlayer === undefined) this.showPlayer = true;
710
-
711
- if (state.life === undefined) {
712
- state.life = 3;
713
- }
714
- return state.life || 0;
902
+ return this.impl.life();
715
903
  }
716
904
 
717
905
  /**
@@ -721,14 +909,9 @@ namespace info {
721
909
  //% blockId=pisetlife block="set %player life to %value"
722
910
  //% value.defl=3
723
911
  //% help=info/set-life
912
+ //% parts="multiplayer"
724
913
  setLife(value: number): void {
725
- const state = this.getState();
726
- if (!(infoState.visibilityFlag & Visibility._ExplicitlySetLife)) {
727
- updateFlag(Visibility.Life, true);
728
- }
729
-
730
- this.life(); // invoked for side effects
731
- state.life = (value | 0);
914
+ this.impl.setLife(value);
732
915
  }
733
916
 
734
917
  /**
@@ -739,8 +922,9 @@ namespace info {
739
922
  //% blockId=pichangelife block="change %player life by %value"
740
923
  //% value.defl=-1
741
924
  //% help=info/change-life-by
925
+ //% parts="multiplayer"
742
926
  changeLifeBy(value: number): void {
743
- this.setLife(this.life() + value);
927
+ this.impl.changeLifeBy(value);
744
928
  }
745
929
 
746
930
  /**
@@ -751,9 +935,9 @@ namespace info {
751
935
  //% group="Multiplayer"
752
936
  //% blockId=pihaslife block="%player has life"
753
937
  //% help=info/has-life
938
+ //% parts="multiplayer"
754
939
  hasLife(): boolean {
755
- const state = this.getState();
756
- return state.life !== undefined && state.life !== null;
940
+ return this.impl.hasLife();
757
941
  }
758
942
 
759
943
  /**
@@ -763,9 +947,9 @@ namespace info {
763
947
  //% group="Multiplayer"
764
948
  //% blockId=playerinfoonlifezero block="on %player life zero"
765
949
  //% help=info/on-life-zero
950
+ //% parts="multiplayer"
766
951
  onLifeZero(handler: () => void) {
767
- const state = this.getState();
768
- state.lifeZeroHandler = handler;
952
+ this.impl.onLifeZero(handler);
769
953
  }
770
954
 
771
955
  /**
@@ -781,21 +965,9 @@ namespace info {
781
965
  //% score.defl=100
782
966
  //% help=info/on-score
783
967
  //% group="Multiplayer"
968
+ //% parts="multiplayer"
784
969
  onScore(score: number, handler: () => void) {
785
- const state = this.getState();
786
- state.scoreReachedHandler = new ScoreReachedHandler(score, handler);
787
- }
788
-
789
- raiseLifeZero(gameOver: boolean) {
790
- const state = this.getState();
791
- if (state.life !== null && state.life <= 0) {
792
- state.life = null;
793
- if (state.lifeZeroHandler) {
794
- state.lifeZeroHandler();
795
- } else if (gameOver) {
796
- game.over();
797
- }
798
- }
970
+ this.impl.onScore(score, handler);
799
971
  }
800
972
 
801
973
  drawPlayer() {
@@ -809,8 +981,8 @@ namespace info {
809
981
  let lifeWidth = 0;
810
982
  const offsetX = 1;
811
983
  let offsetY = 2;
812
- let showScore = this.showScore && state.score !== undefined;
813
- let showLife = this.showLife && state.life !== undefined;
984
+ let showScore = this.impl.showScore && state.score !== undefined;
985
+ let showLife = this.impl.showLife && state.life !== undefined;
814
986
 
815
987
  if (showScore) {
816
988
  score = "" + state.score;
@@ -830,27 +1002,27 @@ namespace info {
830
1002
  // bump size for space between lines
831
1003
  if (showScore && showLife) height++;
832
1004
 
833
- const x = this.x - (this.left ? width : 0);
834
- const y = this.y - (this.up ? height : 0);
1005
+ const x = this.impl.x - (this.impl.left ? width : 0);
1006
+ const y = this.impl.y - (this.impl.up ? height : 0);
835
1007
 
836
1008
  // Bordered Box
837
1009
  if (showScore || showLife) {
838
- screen.fillRect(x, y, width, height, this.border);
839
- screen.fillRect(x + 1, y + 1, width - 2, height - 2, this.bg);
1010
+ screen.fillRect(x, y, width, height, this.impl.border);
1011
+ screen.fillRect(x + 1, y + 1, width - 2, height - 2, this.impl.bg);
840
1012
  }
841
1013
 
842
1014
  // print score
843
1015
  if (showScore) {
844
- const bump = this.left ? width - scoreWidth : 0;
845
- screen.print(score, x + offsetX + bump + 1, y + 2, this.fc, font);
1016
+ const bump = this.impl.left ? width - scoreWidth : 0;
1017
+ screen.print(score, x + offsetX + bump + 1, y + 2, this.impl.fc, font);
846
1018
  }
847
1019
 
848
1020
  // print life
849
1021
  if (showLife) {
850
- const xLoc = x + offsetX + (this.left ? width - lifeWidth : 0);
1022
+ const xLoc = x + offsetX + (this.impl.left ? width - lifeWidth : 0);
851
1023
 
852
1024
  let mult = infoState.multiplierImage.clone();
853
- mult.replace(1, this.fc);
1025
+ mult.replace(1, this.impl.fc);
854
1026
 
855
1027
  screen.drawTransparentImage(
856
1028
  infoState.heartImage,
@@ -866,24 +1038,24 @@ namespace info {
866
1038
  life,
867
1039
  xLoc + infoState.heartImage.width + infoState.multiplierImage.width + 1,
868
1040
  y + offsetY,
869
- this.fc,
1041
+ this.impl.fc,
870
1042
  font
871
1043
  );
872
1044
  }
873
1045
 
874
1046
  // print player icon
875
- if (this.showPlayer) {
1047
+ if (this.impl.showPlayer) {
876
1048
  const pNum = "" + this._player;
877
1049
 
878
1050
  let iconWidth = pNum.length * font.charWidth + 1;
879
1051
  const iconHeight = Math.max(height, font.charHeight + 2);
880
- let iconX = this.left ? (x - iconWidth + 1) : (x + width - 1);
1052
+ let iconX = this.impl.left ? (x - iconWidth + 1) : (x + width - 1);
881
1053
  let iconY = y;
882
1054
 
883
1055
  // adjustments when only player icon shown
884
1056
  if (!showScore && !showLife) {
885
- iconX += this.left ? -1 : 1;
886
- if (this.up) iconY -= 3;
1057
+ iconX += this.impl.left ? -1 : 1;
1058
+ if (this.impl.up) iconY -= 3;
887
1059
  }
888
1060
 
889
1061
  screen.fillRect(
@@ -891,20 +1063,20 @@ namespace info {
891
1063
  iconY,
892
1064
  iconWidth,
893
1065
  iconHeight,
894
- this.border
1066
+ this.impl.border
895
1067
  );
896
1068
  screen.print(
897
1069
  pNum,
898
1070
  iconX + 1,
899
1071
  iconY + (iconHeight >> 1) - (font.charHeight >> 1),
900
- this.bg,
1072
+ this.impl.bg,
901
1073
  font
902
1074
  );
903
1075
  }
904
1076
  }
905
1077
 
906
1078
  drawScore() {
907
- const s = this.score() | 0;
1079
+ const s = this.impl.score() | 0;
908
1080
 
909
1081
  let font: image.Font;
910
1082
  let offsetY: number;