pxt-common-packages 10.3.8 → 10.3.9

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 (49) hide show
  1. package/libs/azureiot/built/debug/binary.js +461 -461
  2. package/libs/color/built/debug/binary.js +8 -8
  3. package/libs/color-sensor/built/debug/binary.js +8 -8
  4. package/libs/controller/built/debug/binary.js +15488 -15343
  5. package/libs/controller---none/built/debug/binary.js +15467 -15322
  6. package/libs/datalogger/built/debug/binary.js +63 -63
  7. package/libs/edge-connector/built/debug/binary.js +8 -8
  8. package/libs/esp32/built/debug/binary.js +462 -462
  9. package/libs/game/_locales/game-jsdoc-strings.json +8 -3
  10. package/libs/game/_locales/game-strings.json +10 -0
  11. package/libs/game/ask.ts +0 -1
  12. package/libs/game/built/debug/binary.js +16092 -15947
  13. package/libs/game/game.ts +194 -45
  14. package/libs/game/gameutil.ts +0 -2
  15. package/libs/game/info.ts +98 -36
  16. package/libs/game/ns.ts +5 -0
  17. package/libs/game/numberprompt.ts +0 -1
  18. package/libs/game/particleeffects.ts +30 -0
  19. package/libs/game/prompt.ts +0 -1
  20. package/libs/game/pxt.json +1 -0
  21. package/libs/game/textDialogs.ts +275 -40
  22. package/libs/lcd/built/debug/binary.js +8 -8
  23. package/libs/light-spectrum-sensor/built/debug/binary.js +8 -8
  24. package/libs/lora/built/debug/binary.js +8 -8
  25. package/libs/matrix-keypad/built/debug/binary.js +8 -8
  26. package/libs/mixer/instrument.ts +20 -1
  27. package/libs/mixer/melody.ts +13 -15
  28. package/libs/mixer/playable.ts +181 -0
  29. package/libs/mixer/pxt.json +1 -0
  30. package/libs/mixer/soundEffect.ts +19 -2
  31. package/libs/mqtt/built/debug/binary.js +176 -176
  32. package/libs/multiplayer/ns.ts +6 -0
  33. package/libs/multiplayer/player.ts +21 -3
  34. package/libs/multiplayer/pxt.json +1 -0
  35. package/libs/music/ns.ts +1 -1
  36. package/libs/net/built/debug/binary.js +176 -176
  37. package/libs/net-game/built/debug/binary.js +20403 -20258
  38. package/libs/palette/built/debug/binary.js +16086 -15941
  39. package/libs/pixel/built/debug/binary.js +8 -8
  40. package/libs/power/built/debug/binary.js +8 -8
  41. package/libs/proximity/built/debug/binary.js +8 -8
  42. package/libs/radio/built/debug/binary.js +8 -8
  43. package/libs/radio-broadcast/built/debug/binary.js +8 -8
  44. package/libs/rotary-encoder/built/debug/binary.js +8 -8
  45. package/libs/screen/built/debug/binary.js +50 -50
  46. package/libs/servo/built/debug/binary.js +8 -8
  47. package/libs/sprite-scaling/built/debug/binary.js +16091 -15946
  48. package/libs/storyboard/built/debug/binary.js +16091 -15946
  49. package/package.json +1 -1
package/libs/game/game.ts CHANGED
@@ -1,18 +1,102 @@
1
1
  /**
2
2
  * Game transitions and dialog
3
3
  **/
4
- //% color=#8854d0 weight=97 icon="\uf111"
5
- //% groups='["Gameplay", "Prompt"]'
6
4
  namespace game {
7
5
  /**
8
6
  * Determines if diagnostics are shown
9
7
  */
10
8
  export let debug = false;
11
9
  export let stats = false;
12
- export let winEffect: effects.BackgroundEffect = undefined;
13
- export let loseEffect: effects.BackgroundEffect = undefined;
14
- let loseSound: music.Melody = undefined;
15
- let winSound: music.Melody = undefined;
10
+
11
+ export enum ScoringType {
12
+ //% block="high score"
13
+ HighScore,
14
+ //% block="low score"
15
+ LowScore,
16
+ //% block="none"
17
+ None
18
+ }
19
+
20
+ export class GameOverConfig {
21
+ scoringType: ScoringType;
22
+ winEffect: effects.BackgroundEffect;
23
+ loseEffect: effects.BackgroundEffect;
24
+ loseSound: music.Melody;
25
+ winSound: music.Melody;
26
+ winMessage: string;
27
+ winMessageMultiplayer: string;
28
+ loseMessage: string;
29
+ effectSetByUser: boolean;
30
+ soundSetByUser: boolean;
31
+ messageSetByUser: boolean;
32
+ scoringTypeSetByUser: boolean;
33
+
34
+ constructor() {
35
+ this.init();
36
+ }
37
+
38
+ init() {
39
+ this.scoringType = ScoringType.HighScore;
40
+ this.winEffect = effects.confetti;
41
+ this.loseEffect = effects.melt;
42
+ this.winSound = music.powerUp;
43
+ this.loseSound = music.wawawawaa;
44
+ this.winMessage = "YOU WIN!";
45
+ this.winMessageMultiplayer = "${WINNER} WINS!";
46
+ this.loseMessage = "GAME OVER";
47
+ this.effectSetByUser = false;
48
+ this.soundSetByUser = false;
49
+ this.messageSetByUser = false;
50
+ this.scoringTypeSetByUser = false;
51
+ }
52
+
53
+ setScoringType(type: ScoringType, explicit?: boolean) {
54
+ if (!explicit && this.scoringTypeSetByUser) return;
55
+ this.scoringType = type;
56
+ if (explicit) this.scoringTypeSetByUser = true;
57
+ }
58
+
59
+ setEffect(win: boolean, effect: effects.BackgroundEffect, explicit?: boolean) {
60
+ if (!explicit && this.effectSetByUser) return;
61
+ if (win) this.winEffect = effect;
62
+ else this.loseEffect = effect;
63
+ if (explicit) this.effectSetByUser = true;
64
+ }
65
+ getEffect(win: boolean) {
66
+ return win ? this.winEffect : this.loseEffect;
67
+ }
68
+
69
+ setSound(win: boolean, sound: music.Melody, explicit?: boolean) {
70
+ if (!explicit && this.soundSetByUser) return;
71
+ if (win) this.winSound = sound;
72
+ else this.loseSound = sound;
73
+ if (explicit) this.soundSetByUser = true;
74
+ }
75
+ getSound(win: boolean) {
76
+ return win ? this.winSound : this.loseSound;
77
+ }
78
+
79
+ setMessage(win: boolean, message: string, explicit?: boolean) {
80
+ if (!explicit && this.messageSetByUser) return;
81
+ if (win) this.winMessage = message;
82
+ else this.loseMessage = message;
83
+ if (explicit) this.messageSetByUser = true;
84
+ }
85
+ getMessage(win: boolean, preferMultiplayer?: boolean) {
86
+ if (this.messageSetByUser)
87
+ return win ? this.winMessage : this.loseMessage;
88
+ else if (preferMultiplayer)
89
+ return win ? this.winMessageMultiplayer : this.loseMessage;
90
+ else
91
+ return win ? this.winMessage : this.loseMessage;
92
+ }
93
+ }
94
+
95
+ let _gameOverConfig: GameOverConfig;
96
+ export const gameOverConfig = () => {
97
+ if (!_gameOverConfig) _gameOverConfig = new GameOverConfig();
98
+ return _gameOverConfig;
99
+ }
16
100
 
17
101
  let _scene: scene.Scene;
18
102
  let _sceneStack: scene.Scene[];
@@ -48,16 +132,6 @@ namespace game {
48
132
  _scene = new scene.Scene(control.pushEventContext(), _scene);
49
133
  }
50
134
  _scene.init();
51
-
52
- if (!winEffect)
53
- winEffect = effects.confetti;
54
- if (!loseEffect)
55
- loseEffect = effects.melt;
56
-
57
- if (!winSound)
58
- winSound = music.powerUp;
59
- if (!loseSound)
60
- loseSound = music.wawawawaa;
61
135
  }
62
136
 
63
137
  export function pushScene() {
@@ -139,31 +213,81 @@ namespace game {
139
213
 
140
214
  /**
141
215
  * Set the effect that occurs when the game is over
142
- * @param win whether the animation should run on a win (true)
216
+ * @param win whether the effect should run on a win (true) or lose (false)
143
217
  * @param effect
144
218
  */
219
+ //% blockId=game_setgameovereffect
220
+ //% block="use effect $effect for $win"
221
+ //% effect.defl=effects.confetti
222
+ //% win.shadow=toggleWinLose
223
+ //% win.defl=true
224
+ //% group="Game Over"
225
+ //% weight=80
226
+ //% blockGap=8
227
+ //% help=game/set-game-over-effect
145
228
  export function setGameOverEffect(win: boolean, effect: effects.BackgroundEffect) {
146
229
  init();
147
- if (!effect) return;
148
- if (win)
149
- winEffect = effect;
150
- else
151
- loseEffect = effect;
230
+ const goc = game.gameOverConfig();
231
+ goc.setEffect(win, effect, true);
152
232
  }
153
233
 
154
234
  /**
155
- * Set the music that occurs when the player wins
156
- * @param win
235
+ * Set the music that occurs when the game is over
236
+ * @param win whether the sound should play on a win (true) or lose (false)
157
237
  * @param effect
158
238
  */
239
+ //% blockId=game_setgameoversound
240
+ //% block="use sound $sound for $win"
241
+ //% sound.defl=music.powerUp
242
+ //% win.shadow=toggleWinLose
243
+ //% win.defl=true
244
+ //% group="Game Over"
245
+ //% weight=80
246
+ //% blockGap=8
247
+ //% help=game/set-game-over-sound
159
248
  export function setGameOverSound(win: boolean, sound: music.Melody) {
160
249
  init();
161
- if (!sound) return;
162
- if (win)
163
- winSound = sound;
164
- else
165
- loseSound = sound;
250
+ const goc = game.gameOverConfig();
251
+ goc.setSound(win, sound, true);
166
252
  }
253
+
254
+ /**
255
+ * Set the message that displays when the game is over
256
+ * @param win whether the message should show on a win (true) or lose (false)
257
+ * @param message
258
+ */
259
+ //% blockId=game_setgameovermessage
260
+ //% block="use message $message for $win"
261
+ //% message.defl="GAME OVER!"
262
+ //% win.shadow=toggleWinLose
263
+ //% win.defl=true
264
+ //% group="Game Over"
265
+ //% weight=80
266
+ //% blockGap=8
267
+ //% help=game/set-game-over-message
268
+ export function setGameOverMessage(win: boolean, message: string) {
269
+ init();
270
+ const goc = game.gameOverConfig();
271
+ goc.setMessage(win, message, true);
272
+ }
273
+
274
+ /**
275
+ * Set the method of judging the best score for the game
276
+ * @param type the scoring type
277
+ */
278
+ //% blockId=game_setgameoverscoringtype
279
+ //% block="use $type as best score"
280
+ //% type.defl=ScoringType.HighScore
281
+ //% group="Game Over"
282
+ //% weight=80
283
+ //% blockGap=8
284
+ //% help=game/set-game-over-scoring-type
285
+ export function setGameOverScoringType(type: ScoringType) {
286
+ init();
287
+ const goc = game.gameOverConfig();
288
+ goc.setScoringType(type, true);
289
+ }
290
+
167
291
  /**
168
292
  * Set the function to call on game over. The 'win' boolean is
169
293
  * passed to the handler.
@@ -179,7 +303,30 @@ namespace game {
179
303
  //% group="Gameplay"
180
304
  //% blockId=gameOver block="game over %win=toggleWinLose || with %effect effect"
181
305
  //% weight=80 help=game/over
306
+ //% deprecated=true
182
307
  export function over(win: boolean = false, effect?: effects.BackgroundEffect) {
308
+ // Match legacy behavior unless effect was set by user
309
+ const goc = game.gameOverConfig();
310
+ goc.setEffect(win, effect, false);
311
+ _gameOverImpl(win);
312
+ }
313
+
314
+ //% blockId=gameOver2 block="game over $win"
315
+ //% win.shadow=toggleWinLose
316
+ //% win.defl=true
317
+ //% weight=80
318
+ //% blockGap=8
319
+ //% help=game/over
320
+ //% group="Game Over"
321
+ export function gameOver(win: boolean) {
322
+ _gameOverImpl(win);
323
+ }
324
+
325
+ export function gameOverPlayerWin(player: number) {
326
+ _gameOverImpl(true, player);
327
+ }
328
+
329
+ function _gameOverImpl(win: boolean, winnerOverride?: number) {
183
330
  init();
184
331
  if (__isOver) return;
185
332
  __isOver = true;
@@ -187,18 +334,24 @@ namespace game {
187
334
  if (__gameOverHandler) {
188
335
  __gameOverHandler(win);
189
336
  } else {
190
- if (!effect) {
191
- effect = win ? winEffect : loseEffect;
192
- }
337
+ const goc = game.gameOverConfig();
193
338
 
194
- // Save all scores as relevant to the game.
195
- info.saveAllScores();
339
+ const judged = !winnerOverride && goc.scoringType !== ScoringType.None;
340
+ const playersWithScores = info.playersWithScores();
341
+ const prevBestScore = judged && info.highScore();
342
+ const winner = judged && win && info.winningPlayer();
343
+ const scores = playersWithScores.map(player => new GameOverPlayerScore(player.number, player.impl.score(), player === winner));
196
344
 
197
- // collect the scores before poping the scenes
198
- const scoreInfo = info.player1.getState();
199
- const highScore = info.highScore();
200
- if (scoreInfo.score > highScore)
345
+ // Save scores if this was a judged game and there was a winner (don't save in the LOSE case).
346
+ if (judged && winner) {
347
+ info.saveAllScores();
201
348
  info.saveHighScore();
349
+ }
350
+
351
+ const preferMultiplayer = !!winnerOverride || (judged && info.multiplayerScoring());
352
+ const message = goc.getMessage(win, preferMultiplayer);
353
+ const effect = goc.getEffect(win);
354
+ const sound = goc.getSound(win);
202
355
 
203
356
  // releasing memory and clear fibers. Do not add anything that releases the fiber until background is set below,
204
357
  // or screen will be cleared on the new frame and will not appear as background in the game over screen.
@@ -209,16 +362,12 @@ namespace game {
209
362
  pushScene();
210
363
  scene.setBackgroundImage(screen.clone());
211
364
 
212
- if (win)
213
- winSound.play();
214
- else
215
- loseSound.play();
216
-
217
- effect.startScreenEffect();
365
+ if (sound) sound.play();
366
+ if (effect) effect.startScreenEffect();
218
367
 
219
368
  pause(400);
220
369
 
221
- const overDialog = new GameOverDialog(win, scoreInfo.score, highScore);
370
+ const overDialog = new GameOverDialog(win, message, judged, scores, prevBestScore, winnerOverride);
222
371
  scene.createRenderable(scene.HUD_Z, target => {
223
372
  overDialog.update();
224
373
  target.drawTransparentImage(
@@ -1,8 +1,6 @@
1
1
  /**
2
2
  * Game transitions and dialog
3
3
  **/
4
- //% color=#8854d0 weight=97 icon="\uf111"
5
- //% groups='["Gameplay", "Prompt"]'
6
4
  namespace game {
7
5
 
8
6
  /**
package/libs/game/info.ts CHANGED
@@ -35,7 +35,17 @@ namespace info {
35
35
  public lifeZeroHandler: () => void;
36
36
  public scoreReachedHandler: ScoreReachedHandler
37
37
 
38
- constructor() { }
38
+ public showScore?: boolean;
39
+ public showLife?: boolean;
40
+ public visibility: Visibility;
41
+ public showPlayer?: boolean;
42
+
43
+ constructor() {
44
+ this.visibility = Visibility.None;
45
+ this.showScore = undefined;
46
+ this.showLife = undefined;
47
+ this.showPlayer = undefined;
48
+ }
39
49
  }
40
50
 
41
51
  class InfoState {
@@ -148,7 +158,11 @@ namespace info {
148
158
  if (infoState.countdownEndHandler) {
149
159
  infoState.countdownEndHandler();
150
160
  } else {
151
- game.over();
161
+ // Clear effect and sound, unless set by user
162
+ const goc = game.gameOverConfig();
163
+ goc.setEffect(false, null, false);
164
+ goc.setSound(false, null, false);
165
+ game.gameOver(false);
152
166
  }
153
167
  }
154
168
  }
@@ -212,11 +226,26 @@ namespace info {
212
226
  `;
213
227
  }
214
228
 
229
+ export function multiplayerScoring() {
230
+ const pws = playersWithScores();
231
+ for (const p of pws) {
232
+ if (p.number > 1) {
233
+ return true;
234
+ }
235
+ }
236
+ return false;
237
+ }
238
+
239
+ export function playersWithScores(): PlayerInfo[] {
240
+ return players ? players.filter(item => item.impl.hasScore()) : [];
241
+ }
242
+
215
243
  export function saveAllScores() {
216
244
  const allScoresKey = "all-scores";
217
245
  let allScores: number[];
218
- if (players) {
219
- allScores = players.filter(item => item.impl.hasScore()).map(item => item.impl.score());
246
+ const pws = playersWithScores();
247
+ if (pws) {
248
+ allScores = pws.map(item => item.impl.score());
220
249
  }
221
250
  else {
222
251
  allScores = [];
@@ -225,15 +254,44 @@ namespace info {
225
254
  settings.writeJSON(allScoresKey, allScores);
226
255
  }
227
256
 
257
+ export function winningPlayer(): PlayerInfo {
258
+ let winner: PlayerInfo = null;
259
+ const pws = playersWithScores();
260
+ if (pws) {
261
+ const goc = game.gameOverConfig();
262
+ let hs: number = null;
263
+ pws.forEach(p => {
264
+ const s = p.impl.score();
265
+ if (isBetterScore(s, hs)) {
266
+ hs = s;
267
+ winner = p;
268
+ }
269
+ });
270
+ }
271
+ return winner;
272
+ }
273
+
274
+ export function isBetterScore(newScore: number, prevScore: number): boolean {
275
+ const goc = game.gameOverConfig();
276
+ switch (goc.scoringType) {
277
+ case game.ScoringType.HighScore: {
278
+ return prevScore == null || newScore > prevScore;
279
+ }
280
+ case game.ScoringType.LowScore: {
281
+ return prevScore == null || newScore < prevScore;
282
+ }
283
+ }
284
+ return false;
285
+ }
286
+
228
287
  export function saveHighScore() {
229
- if (players) {
230
- let hs = 0;
231
- players
232
- .filter(p => p && p.impl.hasScore())
233
- .forEach(p => hs = Math.max(hs, p.impl.score()));
234
- const curr = settings.readNumber("high-score")
235
- if (curr == null || hs > curr)
288
+ const winner = winningPlayer();
289
+ if (winner) {
290
+ let hs = winner.impl.score();
291
+ let curr = settings.readNumber("high-score");
292
+ if (isBetterScore(hs, curr)) {
236
293
  settings.writeNumber("high-score", hs);
294
+ }
237
295
  }
238
296
  }
239
297
 
@@ -576,10 +634,6 @@ namespace info {
576
634
  public bg: number; // background color
577
635
  public border: number; // border color
578
636
  public fc: number; // font color
579
- public showScore?: boolean;
580
- public showLife?: boolean;
581
- public visibility: Visibility;
582
- public showPlayer?: boolean;
583
637
  public x?: number;
584
638
  public y?: number;
585
639
  public left?: boolean; // if true banner goes from x to the left, else goes rightward
@@ -589,10 +643,6 @@ namespace info {
589
643
  this._player = player;
590
644
  this.border = 1;
591
645
  this.fc = 1;
592
- this.visibility = Visibility.None;
593
- this.showScore = undefined;
594
- this.showLife = undefined;
595
- this.showPlayer = undefined;
596
646
  this.left = undefined;
597
647
  this.up = undefined;
598
648
  if (this._player === 1) {
@@ -640,11 +690,11 @@ namespace info {
640
690
  }
641
691
 
642
692
  score(): number {
643
- if (this.showScore === undefined) this.showScore = true;
644
- if (this.showPlayer === undefined) this.showPlayer = true;
645
-
646
693
  const state = this.getState();
647
694
 
695
+ if (state.showScore === undefined) state.showScore = true;
696
+ if (state.showPlayer === undefined) state.showPlayer = true;
697
+
648
698
  if (state.score == null)
649
699
  state.score = 0;
650
700
  return state.score;
@@ -680,8 +730,9 @@ namespace info {
680
730
 
681
731
  life(): number {
682
732
  const state = this.getState();
683
- if (this.showLife === undefined) this.showLife = true;
684
- if (this.showPlayer === undefined) this.showPlayer = true;
733
+
734
+ if (state.showLife === undefined) state.showLife = true;
735
+ if (state.showPlayer === undefined) state.showPlayer = true;
685
736
 
686
737
  if (state.life === undefined) {
687
738
  state.life = 3;
@@ -725,7 +776,11 @@ namespace info {
725
776
  if (state.lifeZeroHandler) {
726
777
  state.lifeZeroHandler();
727
778
  } else if (gameOver) {
728
- game.over();
779
+ // Clear effect and sound, unless set by user
780
+ const goc = game.gameOverConfig();
781
+ goc.setEffect(false, null, false);
782
+ goc.setSound(false, null, false);
783
+ game.gameOver(false);
729
784
  }
730
785
  }
731
786
  }
@@ -753,6 +808,13 @@ namespace info {
753
808
  }
754
809
  }
755
810
 
811
+ /**
812
+ * Returns the one-based number of the player
813
+ */
814
+ get number() {
815
+ return this._player;
816
+ }
817
+
756
818
  get bg(): number {
757
819
  return this.impl.bg;
758
820
  }
@@ -778,35 +840,35 @@ namespace info {
778
840
  }
779
841
 
780
842
  get showScore(): boolean {
781
- return this.impl.showScore;
843
+ return this.impl.getState().showScore;
782
844
  }
783
845
 
784
846
  set showScore(value: boolean) {
785
- this.impl.showScore = value;
847
+ this.impl.getState().showScore = value;
786
848
  }
787
849
 
788
850
  get showLife(): boolean {
789
- return this.impl.showLife;
851
+ return this.impl.getState().showLife;
790
852
  }
791
853
 
792
854
  set showLife(value: boolean) {
793
- this.impl.showLife = value;
855
+ this.impl.getState().showLife = value;
794
856
  }
795
857
 
796
858
  get visibility(): Visibility {
797
- return this.impl.visibility;
859
+ return this.impl.getState().visibility;
798
860
  }
799
861
 
800
862
  set visibility(value: Visibility) {
801
- this.impl.visibility = value;
863
+ this.impl.getState().visibility = value;
802
864
  }
803
865
 
804
866
  get showPlayer(): boolean {
805
- return this.impl.showPlayer;
867
+ return this.impl.getState().showPlayer;
806
868
  }
807
869
 
808
870
  set showPlayer(value: boolean) {
809
- this.impl.showPlayer = value;
871
+ this.impl.getState().showPlayer = value;
810
872
  }
811
873
 
812
874
  get x(): number {
@@ -981,8 +1043,8 @@ namespace info {
981
1043
  let lifeWidth = 0;
982
1044
  const offsetX = 1;
983
1045
  let offsetY = 2;
984
- let showScore = this.impl.showScore && state.score !== undefined;
985
- let showLife = this.impl.showLife && state.life !== undefined;
1046
+ let showScore = state.showScore && state.score !== undefined;
1047
+ let showLife = state.showLife && state.life !== undefined;
986
1048
 
987
1049
  if (showScore) {
988
1050
  score = "" + state.score;
@@ -1044,7 +1106,7 @@ namespace info {
1044
1106
  }
1045
1107
 
1046
1108
  // print player icon
1047
- if (this.impl.showPlayer) {
1109
+ if (state.showPlayer) {
1048
1110
  const pNum = "" + this._player;
1049
1111
 
1050
1112
  let iconWidth = pNum.length * font.charWidth + 1;
@@ -0,0 +1,5 @@
1
+ //% color=#8854d0 weight=97 icon="\uf111"
2
+ //% blockGap=8
3
+ //% groups='["Gameplay", "Game Over", "Prompt", "Dialogs"]'
4
+ namespace game {
5
+ }
@@ -5,7 +5,6 @@ namespace game {
5
5
  * @param message The message to display on the text-entry screen
6
6
  * @param answerLength The maximum number of digits the user can enter (1 - 10)
7
7
  */
8
- //% group="Gameplay"
9
8
  //% weight=10 help=game/ask-for-number
10
9
  //% blockId=gameaskfornumber block="ask for number %message || and max length %answerLength"
11
10
  //% message.shadow=text
@@ -337,4 +337,34 @@ namespace effects {
337
337
  source.z = -2;
338
338
  return source;
339
339
  });
340
+
341
+ //% fixedInstance whenUsed block="none"
342
+ export const none = new ScreenEffect(0, 0, 0, function (anchor: particles.ParticleAnchor, particlesPerSecond: number) {
343
+ class NullParticleSource extends particles.ParticleSource {
344
+ constructor() {
345
+ super(null, 0);
346
+ this._prune();
347
+ }
348
+
349
+ __draw(camera: scene.Camera) {}
350
+
351
+ _update(dt: number) {}
352
+
353
+ // remove self at next opportunity
354
+ _prune() {
355
+ const scene = game.currentScene();
356
+ if (!scene)
357
+ return;
358
+ scene.allSprites.removeElement(this);
359
+ const sources = scene.particleSources;
360
+ if (sources && sources.length)
361
+ sources.removeElement(this);
362
+ }
363
+ destroy() { this._prune(); }
364
+ clear() { this.head = undefined; }
365
+ }
366
+ const source = new NullParticleSource();
367
+
368
+ return source;
369
+ });
340
370
  }
@@ -16,7 +16,6 @@ namespace game {
16
16
  * @param message The message to display on the text-entry screen
17
17
  * @param answerLength The maximum number of characters the user can enter (1 - 24)
18
18
  */
19
- //% group="Gameplay"
20
19
  //% weight=10 help=game/ask-for-string
21
20
  //% blockId=gameaskforstring block="ask for string %message || and max length %answerLength"
22
21
  //% message.shadow=text
@@ -2,6 +2,7 @@
2
2
  "name": "game",
3
3
  "description": "The game and sprite library - beta",
4
4
  "files": [
5
+ "ns.ts",
5
6
  "gameoverrides.ts",
6
7
  "basesprite.ts",
7
8
  "constants.ts",