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
@@ -14,6 +14,22 @@ enum DialogLayout {
14
14
  }
15
15
 
16
16
  namespace game {
17
+ function padStr(len: number): string {
18
+ let str = "";
19
+ for (let i = 0; i < len; ++i) {
20
+ str += " ";
21
+ }
22
+ return str;
23
+ }
24
+
25
+ function replaceRange(dst: string, src: string, start: number, len: number): string {
26
+ return dst.substr(0, start) + src.substr(0, len) + dst.substr(start + len);
27
+ }
28
+
29
+ function screenColor(c: number): number {
30
+ return screen.isMono ? 1 : c;
31
+ }
32
+
17
33
  let dialogFrame: Image;
18
34
  let dialogCursor: Image;
19
35
  let dialogTextColor: number;
@@ -36,24 +52,21 @@ namespace game {
36
52
  textColor: number;
37
53
 
38
54
  constructor(width: number, height: number, frame?: Image, font?: image.Font, cursor?: Image) {
39
- this.image = image.create(width, height);
55
+ this.cursorCount = 0;
56
+ this.resize(width, height, frame, font, cursor);
57
+ }
40
58
 
59
+ resize(width: number, height: number, frame?: Image, font?: image.Font, cursor?: Image) {
41
60
  this.frame = frame || dialogFrame || (dialogFrame = defaultFrame());
42
-
43
- this.font = font || image.font8;
44
-
45
- this.cursor = cursor || dialogCursor || (dialogCursor = defaultCursorImage());
46
-
47
- this.textColor = dialogTextColor == undefined ? dialogTextColor = 15 : dialogTextColor;
48
-
49
61
  this.unit = Math.floor(this.frame.width / 3);
50
62
  this.columns = Math.floor(width / this.unit);
51
63
  this.rows = Math.floor(height / this.unit);
52
-
53
64
  this.innerLeft = (width - (this.columns * this.unit)) >> 1;
54
65
  this.innerTop = (height - (this.rows * this.unit)) >> 1;
55
-
56
- this.cursorCount = 0;
66
+ this.image = image.create(width, height);
67
+ this.font = font || image.font8;
68
+ this.cursor = cursor || dialogCursor || (dialogCursor = defaultCursorImage());
69
+ this.textColor = dialogTextColor == undefined ? dialogTextColor = 15 : dialogTextColor;
57
70
 
58
71
  this.drawBorder();
59
72
  this.clearInterior();
@@ -332,18 +345,150 @@ namespace game {
332
345
  }
333
346
  }
334
347
 
348
+ const img_trophy_sm = img`
349
+ . . . . . . .
350
+ . 4 5 5 5 1 .
351
+ . 4 5 5 5 1 .
352
+ . 4 5 5 5 1 .
353
+ . . 4 5 1 . .
354
+ . . . 5 . . .
355
+ . . 4 5 1 . .
356
+ . . . . . . .
357
+ `;
358
+
359
+ const img_trophy_lg = img`
360
+ . . . . . . . . . . . . . . . .
361
+ . . . . . . . . . . . . . . . .
362
+ . . . . . 5 5 5 5 5 5 . . . . .
363
+ . . . . 5 4 4 4 4 4 4 5 . . . .
364
+ . . . . 5 5 5 5 5 5 5 5 . . . .
365
+ . . . . 4 5 5 5 5 5 5 1 . . . .
366
+ . . . 5 4 4 5 5 5 5 1 1 5 . . .
367
+ . . 5 . 4 4 5 5 5 5 1 1 . 5 . .
368
+ . . 5 . 4 4 5 5 5 5 1 1 . 5 . .
369
+ . . . 5 4 4 5 5 5 5 1 1 5 . . .
370
+ . . . . 4 4 5 5 5 5 1 1 . . . .
371
+ . . . . . 4 5 5 5 1 1 . . . . .
372
+ . . . . . . 4 5 1 1 . . . . . .
373
+ . . . . . . . 4 1 . . . . . . .
374
+ . . . . . 4 4 5 5 1 1 . . . . .
375
+ . . . . . . . . . . . . . . . .
376
+ `;
377
+
378
+ const img_sleepy_sim = img`
379
+ . . . . . . . . . . . . . . . .
380
+ . . . 6 6 6 6 6 6 6 6 6 6 . . .
381
+ . . 6 f f f f f f f f f f 6 . .
382
+ . . 6 f f f f f f f f f f 6 . .
383
+ . . 6 f f 1 1 f f 1 1 f f 6 . .
384
+ . . 6 f f f f f f f f f f 6 . .
385
+ . . 6 f f f f 1 1 f f f f 6 . .
386
+ . . 6 f f f f f f f f f f 6 . .
387
+ . . 6 6 6 6 6 6 6 6 6 6 6 6 . .
388
+ . . 6 6 f 6 6 6 6 6 6 6 f 6 . .
389
+ . . 6 f f f 6 6 6 6 6 6 6 6 . .
390
+ . . 6 6 f 6 6 6 6 6 f 6 6 6 . .
391
+ . . 6 6 6 6 6 6 6 6 6 6 6 6 . .
392
+ . . . 6 6 6 6 6 6 6 6 6 6 . . .
393
+ . . . . . . . . . . . . . . . .
394
+ . . . . . . . . . . . . . . . .
395
+ `;
396
+
397
+ export class GameOverPlayerScore {
398
+ public str: string;
399
+ constructor(
400
+ public player: number,
401
+ public value: number,
402
+ public winner: boolean) { }
403
+ }
404
+
405
+ enum GameOverDialogFlags {
406
+ WIN = 1,
407
+ HAS_BEST = 2,
408
+ NEW_BEST = 4,
409
+ MULTIPLAYER = 8,
410
+ HAS_SCORES = 16
411
+ };
412
+
335
413
  export class GameOverDialog extends game.BaseDialog {
336
414
  protected cursorOn: boolean;
337
- protected isNewHighScore: boolean;
415
+ protected flags: GameOverDialogFlags;
416
+ protected height: number;
417
+
418
+ get isWinCondition() { return !!(this.flags & GameOverDialogFlags.WIN); }
419
+ get isJudgedGame() { return this.judged; }
420
+ get hasScores() { return !!(this.flags & GameOverDialogFlags.HAS_SCORES); }
421
+ get hasBestScore() { return !!(this.flags & GameOverDialogFlags.HAS_BEST); }
422
+ get isNewBestScore() { return !!(this.flags & GameOverDialogFlags.NEW_BEST); }
423
+ get isMultiplayerGame() { return !!(this.flags & GameOverDialogFlags.MULTIPLAYER); }
338
424
 
339
425
  constructor(
340
- protected win: boolean,
341
- protected score?: number,
342
- protected highScore?: number
426
+ win: boolean,
427
+ protected message: string,
428
+ protected judged: boolean,
429
+ protected scores: GameOverPlayerScore[],
430
+ protected bestScore?: number,
431
+ protected winnerOverride?: number
343
432
  ) {
344
433
  super(screen.width, 46, defaultSplashFrame());
345
434
  this.cursorOn = false;
346
- this.isNewHighScore = this.score > this.highScore;
435
+ this.flags = 0;
436
+
437
+ if (win) {
438
+ this.flags |= GameOverDialogFlags.WIN;
439
+ }
440
+
441
+ // Fixup states in case of winner override
442
+ if (winnerOverride) {
443
+ win = true;
444
+ this.flags |= GameOverDialogFlags.WIN;
445
+ // For display purposes, treat this as a multiplayer game
446
+ this.flags |= GameOverDialogFlags.MULTIPLAYER;
447
+ const score = scores.find(score => score.player === winnerOverride);
448
+ if (!score) {
449
+ scores.push(new GameOverPlayerScore(winnerOverride, null, true));
450
+ scores.sort((a, b) => a.player - b.player);
451
+ }
452
+ scores.forEach(score => score.winner = score.player === winnerOverride);
453
+ }
454
+
455
+ if (scores.length) {
456
+ // If any score present is other than player 1, this is a multiplayer game
457
+ scores.forEach(score => score.player > 1 && (this.flags |= GameOverDialogFlags.MULTIPLAYER));
458
+ if (win) {
459
+ let winner = scores.find(score => score.winner);
460
+ if (!winner && scores.length === 1) winner = scores[0];
461
+ if (winner) {
462
+ if (winner.value != null) {
463
+ if (bestScore == null) {
464
+ this.bestScore = winner.value;
465
+ this.flags |= GameOverDialogFlags.NEW_BEST;
466
+ } else if (info.isBetterScore(winner.value, bestScore)) {
467
+ this.bestScore = winner.value;
468
+ this.flags |= GameOverDialogFlags.NEW_BEST;
469
+ }
470
+ }
471
+ // Replace string tokens with resolved values
472
+ this.message = this.message
473
+ .replaceAll("${WINNER}", "PLAYER " + winner.player)
474
+ .replaceAll("${Winner}", "Player " + winner.player)
475
+ .replaceAll("${winner}", "player " + winner.player)
476
+ .replaceAll("${winner_short}", "P" + winner.player);
477
+ }
478
+ }
479
+ }
480
+
481
+ const scoresWithValues = scores.filter(score => score.value != null);
482
+ if (scoresWithValues.length) this.flags |= GameOverDialogFlags.HAS_SCORES;
483
+
484
+ if (this.isWinCondition && this.isJudgedGame && this.hasScores && (this.bestScore != null)) {
485
+ this.flags |= GameOverDialogFlags.HAS_BEST;
486
+ }
487
+
488
+ // Two scores per row
489
+ const scoreRows = Math.max(0, scoresWithValues.length - 1) >> 1;
490
+ this.height = 47 + scoreRows * image.font5.charHeight;
491
+ this.resize(screen.width, this.height, defaultSplashFrame());
347
492
  }
348
493
 
349
494
  displayCursor() {
@@ -359,44 +504,134 @@ namespace game {
359
504
  }
360
505
  }
361
506
 
362
- drawTextCore() {
363
- const titleHeight = 8;
507
+ drawMessage() {
508
+ const currY = 5;
364
509
  this.image.printCenter(
365
- this.win ? "YOU WIN!" : "GAME OVER!",
366
- titleHeight,
367
- screen.isMono ? 1 : 5,
510
+ this.message,
511
+ currY,
512
+ screenColor(5),
368
513
  image.font8
369
514
  );
515
+ }
370
516
 
371
- if (this.score !== undefined) {
372
- const scoreHeight = 23;
373
- const highScoreHeight = 34;
374
- const scoreColor = screen.isMono ? 1 : 2;
375
-
376
- this.image.printCenter(
377
- "Score:" + this.score,
378
- scoreHeight,
379
- scoreColor,
380
- image.font8
381
- );
517
+ drawScores() {
518
+ if (this.hasScores) {
519
+ const scores = this.scores.filter(score => score.value != null);
520
+ let currY = image.font5.charHeight + 16;
521
+ if (this.isMultiplayerGame) {
522
+ if (scores.length === 1) {
523
+ // Multiplayer special case: Only one player scored
524
+ const score = scores[0];
525
+ score.str = "P" + score.player + ":" + score.value;
526
+ this.image.printCenter(
527
+ score.str,
528
+ currY,
529
+ screenColor(1),
530
+ image.font5
531
+ );
532
+ if (score.winner) {
533
+ // In multiplayer, the winning score gets a trophy
534
+ const x = (this.image.width >> 1) - ((score.str.length * image.font5.charWidth) >> 1);
535
+ this.image.drawTransparentImage(img_trophy_sm, x - img_trophy_sm.width - 3, currY - 2);
536
+ }
537
+ } else {
538
+ // Multiplayer general case: Multiple players scored
539
+ // Compute max score width
540
+ const strlens = [0, 0];
541
+ for (let i = 0; i < scores.length; ++i) {
542
+ const col = i % 2;
543
+ const score = scores[i];
544
+ score.str = "P" + score.player + ":" + score.value;
545
+ strlens[col] = Math.max(strlens[col], score.str.length);
546
+ }
547
+ // Print scores in a grid, two per row
548
+ for (let i = 0; i < scores.length; ++i) {
549
+ const col = i % 2;
550
+ const score = scores[i];
551
+ let str = padStr(strlens[col]);
552
+ str = replaceRange(str, score.str, 0, score.str.length);
553
+ let x = 0;
554
+ if (col === 0) {
555
+ x = (this.image.width >> 1) - strlens[col] * image.font5.charWidth - 3;
556
+ } else {
557
+ x = (this.image.width >> 1) + 3;
558
+ }
559
+ if (score.winner) {
560
+ // In multiplayer, the winning score gets a trophy
561
+ if (i % 2 === 0) {
562
+ this.image.drawTransparentImage(img_trophy_sm, x - img_trophy_sm.width - 3, currY - 2);
563
+ } else {
564
+ this.image.drawTransparentImage(img_trophy_sm, x + score.str.length * image.font5.charWidth + 2, currY - 2);
565
+ }
566
+ }
567
+ this.image.print(
568
+ str,
569
+ x,
570
+ currY,
571
+ screenColor(1),
572
+ image.font5
573
+ );
574
+ if (i % 2 === 1) {
575
+ currY += image.font5.charHeight + 2;
576
+ }
577
+ }
578
+ }
579
+ } else {
580
+ // Single player case
581
+ const score = scores[0];
582
+ score.str = "Score:" + score.value;
583
+ this.image.printCenter(
584
+ score.str,
585
+ currY - 1,
586
+ screenColor(1),
587
+ image.font8 // Single player score gets a bigger font
588
+ );
589
+ }
590
+ } else if (this.isWinCondition) {
591
+ // No score, but there is a win condition. Show a trophy.
592
+ let currY = image.font5.charHeight + 14;
593
+ this.image.drawTransparentImage(img_trophy_lg, (this.image.width >> 1) - (img_trophy_lg.width >> 1), currY);
594
+ } else {
595
+ // No score, no win, show a generic game over icon (sleepy sim)
596
+ let currY = image.font5.charHeight + 14;
597
+ this.image.drawTransparentImage(img_sleepy_sim, (this.image.width >> 1) - (img_sleepy_sim.width >> 1), currY);
598
+ }
599
+ }
382
600
 
383
- if (this.isNewHighScore) {
601
+ drawBestScore() {
602
+ if (this.hasBestScore) {
603
+ const currY = this.height - image.font8.charHeight - 5;
604
+ if (this.isNewBestScore) {
605
+ const label = "New Best Score!";
384
606
  this.image.printCenter(
385
- "New High Score!",
386
- highScoreHeight,
387
- scoreColor,
388
- image.font5
607
+ label,
608
+ currY,
609
+ screenColor(9),
610
+ image.font8
389
611
  );
612
+ // In single player draw trophy icons on either side of the label.
613
+ // In multiplayer a trophy icon is drawn next to the winning score instead.
614
+ if (!this.isMultiplayerGame) {
615
+ const halfWidth = (label.length * image.font8.charWidth) >> 1;
616
+ this.image.drawTransparentImage(img_trophy_sm, (this.image.width >> 1) - halfWidth - img_trophy_sm.width - 2, currY);
617
+ this.image.drawTransparentImage(img_trophy_sm, (this.image.width >> 1) + halfWidth, currY);
618
+ }
390
619
  } else {
391
620
  this.image.printCenter(
392
- "HI" + this.highScore,
393
- highScoreHeight,
394
- scoreColor,
621
+ "Best:" + this.bestScore,
622
+ currY,
623
+ screenColor(9),
395
624
  image.font8
396
625
  );
397
626
  }
398
627
  }
399
628
  }
629
+
630
+ drawTextCore() {
631
+ this.drawMessage();
632
+ this.drawScores();
633
+ this.drawBestScore();
634
+ }
400
635
  }
401
636
 
402
637
  /**
@@ -56,7 +56,7 @@ const pxsim_pxtrt = pxsim.pxtrt;
56
56
  const pxsim_numops = pxsim.numops;
57
57
 
58
58
 
59
- function _main___P48572(s) {
59
+ function _main___P48685(s) {
60
60
  let r0 = s.r0, step = s.pc;
61
61
  s.pc = -1;
62
62
 
@@ -66,19 +66,19 @@ if (yieldSteps-- < 0 && maybeYield(s, step, r0) || runtime !== pxsim.runtime) re
66
66
  switch (step) {
67
67
  case 0:
68
68
 
69
- globals._intervals___48815 = (undefined);
70
- globals._pollEventQueue___48828 = (undefined);
69
+ globals._intervals___48928 = (undefined);
70
+ globals._pollEventQueue___48941 = (undefined);
71
71
  r0 = undefined;
72
72
  return leave(s, r0)
73
73
  default: oops()
74
74
  } } }
75
- _main___P48572.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"characterlcd.ts","functionName":"<main>","argumentNames":[]}
76
- _main___P48572.continuations = [ ]
75
+ _main___P48685.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"characterlcd.ts","functionName":"<main>","argumentNames":[]}
76
+ _main___P48685.continuations = [ ]
77
77
 
78
- function _main___P48572_mk(s) {
78
+ function _main___P48685_mk(s) {
79
79
  checkStack(s.depth);
80
80
  return {
81
- parent: s, fn: _main___P48572, depth: s.depth + 1,
81
+ parent: s, fn: _main___P48685, depth: s.depth + 1,
82
82
  pc: 0, retval: undefined, r0: undefined, overwrittenPC: false, lambdaArgs: null,
83
83
  } }
84
84
 
@@ -88,5 +88,5 @@ function _main___P48572_mk(s) {
88
88
 
89
89
  const breakpoints = setupDebugger(1, [])
90
90
 
91
- return _main___P48572
91
+ return _main___P48685
92
92
  })
@@ -56,7 +56,7 @@ const pxsim_pxtrt = pxsim.pxtrt;
56
56
  const pxsim_numops = pxsim.numops;
57
57
 
58
58
 
59
- function _main___P98048(s) {
59
+ function _main___P98387(s) {
60
60
  let r0 = s.r0, step = s.pc;
61
61
  s.pc = -1;
62
62
 
@@ -66,19 +66,19 @@ if (yieldSteps-- < 0 && maybeYield(s, step, r0) || runtime !== pxsim.runtime) re
66
66
  switch (step) {
67
67
  case 0:
68
68
 
69
- globals._intervals___98291 = (undefined);
70
- globals._pollEventQueue___98304 = (undefined);
69
+ globals._intervals___98630 = (undefined);
70
+ globals._pollEventQueue___98643 = (undefined);
71
71
  r0 = undefined;
72
72
  return leave(s, r0)
73
73
  default: oops()
74
74
  } } }
75
- _main___P98048.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"tsl2591.ts","functionName":"<main>","argumentNames":[]}
76
- _main___P98048.continuations = [ ]
75
+ _main___P98387.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"tsl2591.ts","functionName":"<main>","argumentNames":[]}
76
+ _main___P98387.continuations = [ ]
77
77
 
78
- function _main___P98048_mk(s) {
78
+ function _main___P98387_mk(s) {
79
79
  checkStack(s.depth);
80
80
  return {
81
- parent: s, fn: _main___P98048, depth: s.depth + 1,
81
+ parent: s, fn: _main___P98387, depth: s.depth + 1,
82
82
  pc: 0, retval: undefined, r0: undefined, overwrittenPC: false, lambdaArgs: null,
83
83
  } }
84
84
 
@@ -88,5 +88,5 @@ function _main___P98048_mk(s) {
88
88
 
89
89
  const breakpoints = setupDebugger(1, [])
90
90
 
91
- return _main___P98048
91
+ return _main___P98387
92
92
  })
@@ -56,7 +56,7 @@ const pxsim_pxtrt = pxsim.pxtrt;
56
56
  const pxsim_numops = pxsim.numops;
57
57
 
58
58
 
59
- function _main___P59874(s) {
59
+ function _main___P59987(s) {
60
60
  let r0 = s.r0, step = s.pc;
61
61
  s.pc = -1;
62
62
 
@@ -66,19 +66,19 @@ if (yieldSteps-- < 0 && maybeYield(s, step, r0) || runtime !== pxsim.runtime) re
66
66
  switch (step) {
67
67
  case 0:
68
68
 
69
- globals._intervals___60117 = (undefined);
70
- globals._pollEventQueue___60130 = (undefined);
69
+ globals._intervals___60230 = (undefined);
70
+ globals._pollEventQueue___60243 = (undefined);
71
71
  r0 = undefined;
72
72
  return leave(s, r0)
73
73
  default: oops()
74
74
  } } }
75
- _main___P59874.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"lora.ts","functionName":"<main>","argumentNames":[]}
76
- _main___P59874.continuations = [ ]
75
+ _main___P59987.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"lora.ts","functionName":"<main>","argumentNames":[]}
76
+ _main___P59987.continuations = [ ]
77
77
 
78
- function _main___P59874_mk(s) {
78
+ function _main___P59987_mk(s) {
79
79
  checkStack(s.depth);
80
80
  return {
81
- parent: s, fn: _main___P59874, depth: s.depth + 1,
81
+ parent: s, fn: _main___P59987, depth: s.depth + 1,
82
82
  pc: 0, retval: undefined, r0: undefined, overwrittenPC: false, lambdaArgs: null,
83
83
  } }
84
84
 
@@ -88,5 +88,5 @@ function _main___P59874_mk(s) {
88
88
 
89
89
  const breakpoints = setupDebugger(1, [])
90
90
 
91
- return _main___P59874
91
+ return _main___P59987
92
92
  })
@@ -56,7 +56,7 @@ const pxsim_pxtrt = pxsim.pxtrt;
56
56
  const pxsim_numops = pxsim.numops;
57
57
 
58
58
 
59
- function _main___P190524(s) {
59
+ function _main___P191315(s) {
60
60
  let r0 = s.r0, step = s.pc;
61
61
  s.pc = -1;
62
62
 
@@ -66,19 +66,19 @@ if (yieldSteps-- < 0 && maybeYield(s, step, r0) || runtime !== pxsim.runtime) re
66
66
  switch (step) {
67
67
  case 0:
68
68
 
69
- globals._intervals___190767 = (undefined);
70
- globals._pollEventQueue___190780 = (undefined);
69
+ globals._intervals___191558 = (undefined);
70
+ globals._pollEventQueue___191571 = (undefined);
71
71
  r0 = undefined;
72
72
  return leave(s, r0)
73
73
  default: oops()
74
74
  } } }
75
- _main___P190524.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"keypad.ts","functionName":"<main>","argumentNames":[]}
76
- _main___P190524.continuations = [ ]
75
+ _main___P191315.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"keypad.ts","functionName":"<main>","argumentNames":[]}
76
+ _main___P191315.continuations = [ ]
77
77
 
78
- function _main___P190524_mk(s) {
78
+ function _main___P191315_mk(s) {
79
79
  checkStack(s.depth);
80
80
  return {
81
- parent: s, fn: _main___P190524, depth: s.depth + 1,
81
+ parent: s, fn: _main___P191315, depth: s.depth + 1,
82
82
  pc: 0, retval: undefined, r0: undefined, overwrittenPC: false, lambdaArgs: null,
83
83
  } }
84
84
 
@@ -88,5 +88,5 @@ function _main___P190524_mk(s) {
88
88
 
89
89
  const breakpoints = setupDebugger(1, [])
90
90
 
91
- return _main___P190524
91
+ return _main___P191315
92
92
  })
@@ -1,6 +1,8 @@
1
1
  namespace music.sequencer {
2
2
  const BUFFER_SIZE = 12;
3
3
 
4
+ let currentSequencer: sequencer.Sequencer;
5
+
4
6
  /**
5
7
  * Byte encoding format for songs
6
8
  * FIXME: should this all be word aligned?
@@ -66,10 +68,11 @@ namespace music.sequencer {
66
68
  * 2 = sharp
67
69
  */
68
70
 
69
- export class Song {
71
+ export class Song extends Playable {
70
72
  tracks: Track[];
71
73
 
72
74
  constructor(public buf: Buffer) {
75
+ super();
73
76
  this.tracks = [];
74
77
 
75
78
  let currentOffset = 7;
@@ -128,6 +131,22 @@ namespace music.sequencer {
128
131
  get numberOfTracks(): number {
129
132
  return this.buf[6];
130
133
  }
134
+
135
+ play(playbackMode: PlaybackMode) {
136
+ if (currentSequencer) currentSequencer.stop();
137
+ currentSequencer = new sequencer.Sequencer(this);
138
+
139
+ if (playbackMode === PlaybackMode.UntilDone) {
140
+ currentSequencer.start(false);
141
+ pause(this.measures * this.beatsPerMeasure * this.beatsPerMinute * 60 * 1000)
142
+ }
143
+ else if (playbackMode === PlaybackMode.InBackground) {
144
+ currentSequencer.start(false);
145
+ }
146
+ else {
147
+ currentSequencer.start(true);
148
+ }
149
+ }
131
150
  }
132
151
 
133
152
  export class Envelope {
@@ -81,6 +81,7 @@ namespace music {
81
81
  //% blockNamespace=music
82
82
  //% weight=76 blockGap=8
83
83
  //% group="Tone"
84
+ //% deprecated=1
84
85
  export function playTone(frequency: number, ms: number): void {
85
86
  if (ms == 0)
86
87
  ms = 86400000 // 1 day
@@ -123,6 +124,7 @@ namespace music {
123
124
  //% melody.shadow="melody_editor"
124
125
  //% tempo.min=40 tempo.max=500
125
126
  //% tempo.defl=120
127
+ //% deprecated=1
126
128
  export function playMelody(melody: string, tempo: number) {
127
129
  let notes: string[] = melody.split(" ").filter(n => !!n);
128
130
  let formattedMelody = "";
@@ -181,6 +183,7 @@ namespace music {
181
183
  export function stopAllSounds() {
182
184
  Melody.stopAll();
183
185
  stopPlaying();
186
+ _stopPlayables();
184
187
  }
185
188
 
186
189
  //% fixedInstances
@@ -213,6 +216,7 @@ namespace music {
213
216
  //% parts="headphone"
214
217
  //% weight=92 blockGap=8
215
218
  //% group="Sounds"
219
+ //% deprecated=1
216
220
  stop() {
217
221
  if (this._player) {
218
222
  this._player.stop()
@@ -270,6 +274,7 @@ namespace music {
270
274
  //% parts="headphone"
271
275
  //% weight=93 blockGap=8
272
276
  //% group="Sounds"
277
+ //% deprecated=1
273
278
  loop(volume = 255) {
274
279
  this.playCore(volume, true)
275
280
  }
@@ -283,6 +288,7 @@ namespace music {
283
288
  //% parts="headphone"
284
289
  //% weight=95 blockGap=8
285
290
  //% group="Sounds"
291
+ //% deprecated=1
286
292
  play(volume = 255) {
287
293
  this.playCore(volume, false)
288
294
  }
@@ -297,6 +303,7 @@ namespace music {
297
303
  //% parts="headphone"
298
304
  //% weight=94 blockGap=8
299
305
  //% group="Sounds"
306
+ //% deprecated=1
300
307
  playUntilDone(volume = 255) {
301
308
  this.stop()
302
309
  const p = this._player = new MelodyPlayer(this)
@@ -583,24 +590,15 @@ namespace music {
583
590
  }
584
591
  }
585
592
 
586
- let currentSequencer: sequencer.Sequencer;
587
-
588
593
  //% shim=TD_ID
589
594
  //% blockId=music_song_field_editor
590
- //% block="$song"
595
+ //% block="song $song"
591
596
  //% song.fieldEditor=musiceditor
592
- export function _songFieldEditor(song: Buffer) {
593
- return song;
594
- }
595
-
596
- //% blockId=music_start_song
597
- //% block="start song $song looping $loop"
598
- //% song.shadow=music_song_field_editor
599
- export function startSong(song: Buffer, loop: boolean) {
600
- if (currentSequencer) currentSequencer.stop();
601
-
602
- currentSequencer = new sequencer.Sequencer(new sequencer.Song(song));
603
- currentSequencer.start(loop);
597
+ //% toolboxParent=music_playable_play
598
+ //% toolboxParentArgument=toPlay
599
+ //% group="Songs"
600
+ export function createSong(song: Buffer): Playable {
601
+ return new sequencer.Song(song);
604
602
  }
605
603
 
606
604
  export function playInstructions(when: number, instructions: Buffer) {