pxt-common-packages 9.4.1 → 9.4.5

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 (65) hide show
  1. package/built/common-sim.d.ts +8 -0
  2. package/built/common-sim.js +74 -0
  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 +7126 -6975
  7. package/libs/controller---none/built/debug/binary.js +7105 -6954
  8. package/libs/core---esp32/pins.cpp +30 -4
  9. package/libs/core---esp32/shims.d.ts +15 -0
  10. package/libs/core---esp32s2/shims.d.ts +15 -0
  11. package/libs/datalogger/built/debug/binary.js +63 -63
  12. package/libs/edge-connector/built/debug/binary.js +8 -8
  13. package/libs/esp32/built/debug/binary.js +462 -462
  14. package/libs/game/_locales/game-jsdoc-strings.json +10 -1
  15. package/libs/game/_locales/game-strings.json +18 -2
  16. package/libs/game/assetTemplates.ts +2 -0
  17. package/libs/game/built/debug/binary.js +7018 -6867
  18. package/libs/game/docs/reference/scene/get-tile-location.md +96 -0
  19. package/libs/game/docs/reference/scene/get-tiles-by-type.md +64 -43
  20. package/libs/game/docs/reference/scene/is-hitting-tile.md +87 -0
  21. package/libs/game/docs/reference/scene/on-hit-wall.md +88 -0
  22. package/libs/game/docs/reference/scene/on-overlap-tile.md +88 -0
  23. package/libs/game/docs/reference/scene/place-on-random-tile.md +95 -41
  24. package/libs/game/docs/reference/scene/place-on-tile.md +88 -0
  25. package/libs/game/docs/reference/scene/set-tile-at.md +45 -41
  26. package/libs/game/docs/reference/scene/set-tilemap.md +89 -0
  27. package/libs/game/docs/reference/scene/set-wall-at.md +86 -0
  28. package/libs/game/docs/reference/scene/tile-at-location-equals.md +97 -0
  29. package/libs/game/docs/reference/scene/tile-kind-at.md +118 -0
  30. package/libs/game/docs/reference/scene.md +20 -16
  31. package/libs/game/docs/reference/sprites/sprite/ax.md +34 -3
  32. package/libs/game/docs/reference/sprites/sprite/ay.md +34 -3
  33. package/libs/game/docs/reference/sprites/sprite/fx.md +123 -0
  34. package/libs/game/docs/reference/sprites/sprite/fy.md +123 -0
  35. package/libs/game/docs/reference/sprites.md +2 -0
  36. package/libs/game/physics.ts +1 -1
  37. package/libs/game/renderText.ts +74 -11
  38. package/libs/game/scenes.ts +5 -1
  39. package/libs/game/sprite.ts +23 -6
  40. package/libs/game/spriteevents.ts +7 -7
  41. package/libs/game/sprites.ts +16 -0
  42. package/libs/game/spritesay.ts +204 -51
  43. package/libs/game/tilemap.ts +173 -27
  44. package/libs/lcd/built/debug/binary.js +8 -8
  45. package/libs/light-spectrum-sensor/built/debug/binary.js +8 -8
  46. package/libs/lora/built/debug/binary.js +8 -8
  47. package/libs/matrix-keypad/built/debug/binary.js +8 -8
  48. package/libs/mqtt/built/debug/binary.js +176 -176
  49. package/libs/net/built/debug/binary.js +176 -176
  50. package/libs/net-game/built/debug/binary.js +8802 -8651
  51. package/libs/palette/built/debug/binary.js +7017 -6866
  52. package/libs/pixel/built/debug/binary.js +8 -8
  53. package/libs/power/built/debug/binary.js +8 -8
  54. package/libs/proximity/built/debug/binary.js +8 -8
  55. package/libs/radio/built/debug/binary.js +8 -8
  56. package/libs/radio-broadcast/built/debug/binary.js +8 -8
  57. package/libs/rotary-encoder/built/debug/binary.js +8 -8
  58. package/libs/screen/built/debug/binary.js +50 -50
  59. package/libs/servo/built/debug/binary.js +8 -8
  60. package/libs/storyboard/built/debug/binary.js +7017 -6866
  61. package/libs/text-to-speech/pxt.json +14 -0
  62. package/libs/text-to-speech/shims.d.ts +47 -0
  63. package/libs/text-to-speech/sim/tts.ts +72 -0
  64. package/libs/text-to-speech/tts.ts +70 -0
  65. package/package.json +1 -1
@@ -72,6 +72,22 @@ namespace sprites {
72
72
  else return spritesByKind[kind].sprites();
73
73
  }
74
74
 
75
+ /**
76
+ * Destroys all sprites of the given kind.
77
+ */
78
+ //% group="Effects"
79
+ //% weight=79
80
+ //% blockId=sprites_destroy_all_sprites_of_kind
81
+ //% block="destroy all sprites of kind $kind || with $effect effect for $duration ms"
82
+ //% kind.shadow=spritekind
83
+ //% duration.shadow=timePicker
84
+ //% expandableArgumentMode="toggle"
85
+ export function destroyAllSpritesOfKind(kind: number, effect?: effects.ParticleEffect, duration?: number) {
86
+ for (const sprite of allOfKind(kind)) {
87
+ sprite.destroy(effect, duration);
88
+ }
89
+ }
90
+
75
91
  /**
76
92
  * Create a new sprite with a given speed, and place it at the edge of the screen so it moves towards the middle.
77
93
  * The sprite auto-destroys when it leaves the screen. You can modify position after it's created.
@@ -17,6 +17,206 @@ namespace sprites {
17
17
  }
18
18
 
19
19
  export class SpriteSayRenderer extends BaseSpriteSayRenderer {
20
+ static drawSayFrame(textLeft: number, textTop: number, textWidth: number, textHeight: number, speakerX: number, speakerY: number, color: number, canvas: Image) {
21
+ if (textLeft + textWidth < 0 || textTop + textHeight < 0 || textLeft > canvas.width || textTop > canvas.height) return;
22
+
23
+ if (textHeight) {
24
+ // Draw main rectangle
25
+ canvas.fillRect(
26
+ textLeft,
27
+ textTop,
28
+ textWidth,
29
+ textHeight,
30
+ color
31
+ );
32
+
33
+ // Draw lines around the rectangle to give it a bubble shape
34
+ canvas.fillRect(
35
+ textLeft - 1,
36
+ textTop + 1,
37
+ 1,
38
+ textHeight - 2,
39
+ color
40
+ );
41
+ canvas.fillRect(
42
+ textLeft + textWidth,
43
+ textTop + 1,
44
+ 1,
45
+ textHeight - 2,
46
+ color
47
+ );
48
+ canvas.fillRect(
49
+ textLeft + 1,
50
+ textTop - 1,
51
+ textWidth - 2,
52
+ 1,
53
+ color
54
+ );
55
+ canvas.fillRect(
56
+ textLeft + 1,
57
+ textTop + textHeight,
58
+ textWidth - 2,
59
+ 1,
60
+ color
61
+ );
62
+
63
+ // If the speaker location is within the bubble, don't draw an arrow
64
+ if (speakerX > textLeft && speakerX < textLeft + textWidth && speakerY > textTop && speakerY < textTop + textHeight) return;
65
+
66
+ const xDiff = Math.max(
67
+ Math.abs(speakerX - textLeft),
68
+ Math.abs(speakerX - (textLeft + textWidth))
69
+ );
70
+
71
+ const yDiff = Math.max(
72
+ Math.abs(speakerY - textHeight),
73
+ Math.abs(speakerY - (textHeight + textHeight))
74
+ );
75
+
76
+ // Draw the arrow
77
+ if (xDiff > yDiff) {
78
+ if (speakerX > textLeft + textWidth) {
79
+ const anchorY = Math.max(Math.min(speakerY, textTop + textHeight - 4), textTop + 5);
80
+ canvas.fillRect(
81
+ textLeft + textWidth + 1,
82
+ anchorY - 2,
83
+ 1,
84
+ 3,
85
+ color
86
+ );
87
+ canvas.fillRect(
88
+ textLeft + textWidth + 2,
89
+ anchorY - 1,
90
+ 1,
91
+ 1,
92
+ color
93
+ );
94
+ }
95
+ else if (speakerX < textLeft) {
96
+ const anchorY = Math.max(Math.min(speakerY, textTop + textHeight - 4), textTop + 5);
97
+ canvas.fillRect(
98
+ textLeft - 2,
99
+ anchorY - 2,
100
+ 1,
101
+ 3,
102
+ color
103
+ );
104
+ canvas.fillRect(
105
+ textLeft - 3,
106
+ anchorY - 1,
107
+ 1,
108
+ 1,
109
+ color
110
+ );
111
+ }
112
+ else if (speakerY > textTop + textHeight) {
113
+ const anchorX = Math.max(Math.min(speakerX, textLeft + textWidth - 4), textLeft + 5);
114
+ canvas.fillRect(
115
+ anchorX - 2,
116
+ textTop + textHeight + 1,
117
+ 3,
118
+ 1,
119
+ color
120
+ );
121
+ canvas.fillRect(
122
+ anchorX - 1,
123
+ textTop + textHeight + 2,
124
+ 1,
125
+ 1,
126
+ color
127
+ );
128
+ }
129
+ else if (speakerY < textTop) {
130
+ const anchorX = Math.max(Math.min(speakerX, textLeft + textWidth - 4), textLeft + 5);
131
+ canvas.fillRect(
132
+ anchorX - 2,
133
+ textTop - 2,
134
+ 3,
135
+ 1,
136
+ color
137
+ );
138
+ canvas.fillRect(
139
+ anchorX - 1,
140
+ textTop - 3,
141
+ 1,
142
+ 1,
143
+ color
144
+ );
145
+ }
146
+ }
147
+ else {
148
+ if (speakerY > textTop + textHeight) {
149
+ const anchorX = Math.max(Math.min(speakerX, textLeft + textWidth - 4), textLeft + 5);
150
+ canvas.fillRect(
151
+ anchorX - 2,
152
+ textTop + textHeight + 1,
153
+ 3,
154
+ 1,
155
+ color
156
+ );
157
+ canvas.fillRect(
158
+ anchorX - 1,
159
+ textTop + textHeight + 2,
160
+ 1,
161
+ 1,
162
+ color
163
+ );
164
+ }
165
+ else if (speakerY < textTop) {
166
+ const anchorX = Math.max(Math.min(speakerX, textLeft + textWidth - 4), textLeft + 5);
167
+ canvas.fillRect(
168
+ anchorX - 2,
169
+ textTop - 2,
170
+ 3,
171
+ 1,
172
+ color
173
+ );
174
+ canvas.fillRect(
175
+ anchorX - 1,
176
+ textTop - 3,
177
+ 1,
178
+ 1,
179
+ color
180
+ );
181
+ }
182
+ else if (speakerX > textLeft + textWidth) {
183
+ const anchorY = Math.max(Math.min(speakerY, textTop + textHeight - 4), textTop + 5);
184
+ canvas.fillRect(
185
+ textLeft + textWidth + 1,
186
+ anchorY - 2,
187
+ 1,
188
+ 3,
189
+ color
190
+ );
191
+ canvas.fillRect(
192
+ textLeft + textWidth + 2,
193
+ anchorY - 1,
194
+ 1,
195
+ 1,
196
+ color
197
+ );
198
+ }
199
+ else if (speakerX < textLeft) {
200
+ const anchorY = Math.max(Math.min(speakerY, textTop + textHeight - 4), textTop + 5);
201
+ canvas.fillRect(
202
+ textLeft - 2,
203
+ anchorY - 2,
204
+ 1,
205
+ 3,
206
+ color
207
+ );
208
+ canvas.fillRect(
209
+ textLeft - 3,
210
+ anchorY - 1,
211
+ 1,
212
+ 1,
213
+ color
214
+ );
215
+ }
216
+ }
217
+ }
218
+ }
219
+
20
220
  protected renderText: RenderText;
21
221
  protected animation: RenderTextAnimation;
22
222
 
@@ -45,62 +245,15 @@ namespace sprites {
45
245
  const t = Math.floor(owner.top - oy);
46
246
 
47
247
  const height = this.animation ? this.animation.currentHeight() : this.renderText.height;
48
- const sayLeft = l + (owner.width >> 1) - (this.renderText.width >> 1);
248
+ const width = this.animation ? this.animation.currentWidth() : this.renderText.width;
249
+ const sayLeft = l + (owner.width >> 1) - (width >> 1);
49
250
  const sayTop = t - height - 4;
50
251
 
252
+ if (sayLeft + width < 0 || sayTop + height < 0 || sayLeft > screen.width || sayTop > screen.height) return;
51
253
 
52
- if (sayLeft + this.renderText.width < 0 || sayTop + height < 0 || sayLeft > screen.width || sayTop > screen.height) return;
254
+ SpriteSayRenderer.drawSayFrame(sayLeft, sayTop, width, height, owner.x, owner.y, this.bgColor, screen);
53
255
 
54
256
  if (height) {
55
- screen.fillRect(
56
- sayLeft,
57
- sayTop,
58
- this.renderText.width,
59
- height,
60
- this.bgColor
61
- );
62
- screen.fillRect(
63
- sayLeft - 1,
64
- sayTop + 1,
65
- 1,
66
- height - 2,
67
- this.bgColor
68
- );
69
- screen.fillRect(
70
- sayLeft + this.renderText.width,
71
- sayTop + 1,
72
- 1,
73
- height - 2,
74
- this.bgColor
75
- );
76
- screen.fillRect(
77
- sayLeft + 1,
78
- sayTop - 1,
79
- this.renderText.width - 2,
80
- 1,
81
- this.bgColor
82
- );
83
- screen.fillRect(
84
- sayLeft + 1,
85
- sayTop + height,
86
- this.renderText.width - 2,
87
- 1,
88
- this.bgColor
89
- );
90
- screen.fillRect(
91
- sayLeft + (this.renderText.width >> 1) - 2,
92
- sayTop + height + 1,
93
- 3,
94
- 1,
95
- this.bgColor
96
- );
97
- screen.fillRect(
98
- sayLeft + (this.renderText.width >> 1) - 1,
99
- sayTop + height + 2,
100
- 1,
101
- 1,
102
- this.bgColor
103
- );
104
257
  if (this.animation) {
105
258
  this.animation.draw(screen, sayLeft, sayTop, this.fgColor);
106
259
  }
@@ -6,45 +6,124 @@ enum TileScale {
6
6
  //% block="32x32"
7
7
  ThirtyTwo = 5
8
8
  }
9
+
9
10
  namespace tiles {
10
11
 
11
12
  /**
12
13
  * A (col, row) location in the tilemap
13
14
  **/
14
- //% blockNamespace=scene color="#401255" blockGap=8
15
+ //% blockNamespace=scene color="#401255"
15
16
  export class Location {
16
17
  protected _row: number;
17
18
  protected _col: number;
18
- protected tileMap: TileMap;
19
19
 
20
- get col() {
20
+ constructor(col: number, row: number, map: TileMap) {
21
+ this._col = col;
22
+ this._row = row;
23
+ }
24
+
25
+ get tileMap() {
26
+ return game.currentScene().tileMap;
27
+ }
28
+
29
+ //% group="Locations" blockSetVariable="location"
30
+ //% blockCombine block="column"
31
+ //% weight=100
32
+ get column() {
21
33
  return this._col;
22
34
  }
23
35
 
36
+ //% group="Locations" blockSetVariable="location"
37
+ //% blockCombine block="row"
38
+ //% weight=100
24
39
  get row() {
25
40
  return this._row;
26
41
  }
27
42
 
28
- constructor(col: number, row: number, map: TileMap) {
29
- this._col = col;
30
- this._row = row;
31
- this.tileMap = map;
32
- }
33
-
43
+ //% group="Locations" blockSetVariable="location"
44
+ //% blockCombine block="x"
45
+ //% weight=100
34
46
  get x(): number {
35
47
  const scale = this.tileMap.scale;
36
48
  return (this._col << scale) + (1 << (scale - 1));
37
49
  }
38
50
 
51
+ //% group="Locations" blockSetVariable="location"
52
+ //% blockCombine block="y"
53
+ //% weight=100
39
54
  get y(): number {
40
55
  const scale = this.tileMap.scale;
41
56
  return (this._row << scale) + (1 << (scale - 1));
42
57
  }
43
58
 
59
+ //% group="Locations" blockSetVariable="location"
60
+ //% blockCombine block="left"
61
+ //% weight=100
62
+ get left(): number {
63
+ return (this._col << this.tileMap.scale);
64
+ }
65
+
66
+ //% group="Locations" blockSetVariable="location"
67
+ //% blockCombine block="top"
68
+ //% weight=100
69
+ get top(): number {
70
+ return (this._row << this.tileMap.scale);
71
+ }
72
+
73
+ //% group="Locations" blockSetVariable="location"
74
+ //% blockCombine block="right"
75
+ //% weight=100
76
+ get right(): number {
77
+ return this.left + (1 << this.tileMap.scale);
78
+ }
79
+
80
+ //% group="Locations" blockSetVariable="location"
81
+ //% blockCombine block="bottom"
82
+ //% weight=100
83
+ get bottom(): number {
84
+ return this.top + (1 << this.tileMap.scale);
85
+ }
86
+
44
87
  get tileSet(): number {
45
88
  return this.tileMap.getTileIndex(this._col, this._row);
46
89
  }
47
90
 
91
+ // deprecated
92
+ get col() {
93
+ return this.column;
94
+ }
95
+
96
+ public isWall(): boolean {
97
+ return this.tileMap.isObstacle(this._col, this._row);
98
+ }
99
+
100
+ public getImage(): Image {
101
+ return this.tileMap.getTileImage(this.tileSet);
102
+ }
103
+
104
+ /**
105
+ * Returns the neighboring location in a specifc direction from a location in a tilemap
106
+ * @param direction The direction to fetch the location in
107
+ */
108
+ //% blockId=tiles_location_get_neighboring_location
109
+ //% block="tilemap location $direction of $this"
110
+ //% this.defl=location
111
+ //% this.shadow=variables_get
112
+ //% group="Locations" blockGap=8
113
+ //% weight=10
114
+ public getNeighboringLocation(direction: CollisionDirection): Location {
115
+ switch (direction) {
116
+ case CollisionDirection.Top:
117
+ return this.tileMap.getTile(this._col, this._row - 1);
118
+ case CollisionDirection.Right:
119
+ return this.tileMap.getTile(this._col + 1, this._row);
120
+ case CollisionDirection.Bottom:
121
+ return this.tileMap.getTile(this._col, this._row + 1);
122
+ case CollisionDirection.Left:
123
+ return this.tileMap.getTile(this._col - 1, this._row);
124
+ }
125
+ }
126
+
48
127
  /**
49
128
  * Center the given sprite on this tile
50
129
  * @param sprite
@@ -94,7 +173,7 @@ namespace tiles {
94
173
  * @param sprite
95
174
  */
96
175
  //% blockId=gameplaceontile block="on top of %tile(myTile) place %sprite=variables_get(mySprite)"
97
- //% blockNamespace="scene" group="Tiles"
176
+ //% blockNamespace="scene" group="Tilemap Operations"
98
177
  //% weight=25
99
178
  //% help=tiles/place
100
179
  //% deprecated=1
@@ -465,9 +544,24 @@ namespace tiles {
465
544
  //% tilemap.fieldOptions.decompileArgumentAsString="true"
466
545
  //% tilemap.fieldOptions.filter="tile"
467
546
  //% tilemap.fieldOptions.taggedTemplate="tilemap"
468
- //% blockNamespace="scene" group="Tiles" duplicateShadowOnDrag
469
- //% help=tiles/set-tile-map
547
+ //% blockNamespace="scene" duplicateShadowOnDrag
548
+ //% help=scene/set-tilemap
549
+ //% deprecated=1
470
550
  export function setTilemap(tilemap: TileMapData) {
551
+ setCurrentTilemap(tilemap);
552
+ }
553
+
554
+ /**
555
+ * Sets the given tilemap to be the current active tilemap in the game
556
+ *
557
+ * @param tilemap The tilemap to set as the current tilemap
558
+ */
559
+ //% blockId=set_current_tilemap block="set tilemap to $tilemap"
560
+ //% weight=201 blockGap=8
561
+ //% tilemap.shadow=tiles_tilemap_editor
562
+ //% blockNamespace="scene" group="Tilemaps" duplicateShadowOnDrag
563
+ //% help=tiles/set-tile-map
564
+ export function setCurrentTilemap(tilemap: TileMapData) {
471
565
  scene.setTileMapLevel(tilemap);
472
566
  }
473
567
 
@@ -479,8 +573,9 @@ namespace tiles {
479
573
  //% blockId=mapsettileat block="set $tile at $loc=mapgettile"
480
574
  //% tile.shadow=tileset_tile_picker
481
575
  //% tile.decompileIndirectFixedInstances=true
482
- //% blockNamespace="scene" group="Tiles" blockGap=8
483
- //% help=tiles/set-tile-at
576
+ //% blockNamespace="scene" group="Tilemap Operations" blockGap=8
577
+ //% help=scene/set-tile-at
578
+ //% weight=70
484
579
  export function setTileAt(loc: Location, tile: Image): void {
485
580
  const scene = game.currentScene();
486
581
  if (!loc || !tile || !scene.tileMap) return null;
@@ -496,8 +591,9 @@ namespace tiles {
496
591
  */
497
592
  //% blockId=mapsetwallat block="set wall $on at $loc"
498
593
  //% on.shadow=toggleOnOff loc.shadow=mapgettile
499
- //% blockNamespace="scene" group="Tiles" blockGap=8
500
- //% help=tiles/set-wall-at
594
+ //% blockNamespace="scene" group="Tilemap Operations"
595
+ //% help=scene/set-wall-at
596
+ //% weight=60
501
597
  export function setWallAt(loc: Location, on: boolean): void {
502
598
  const scene = game.currentScene();
503
599
  if (!loc || !scene.tileMap) return null;
@@ -511,9 +607,9 @@ namespace tiles {
511
607
  * @param row
512
608
  */
513
609
  //% blockId=mapgettile block="tilemap col $col row $row"
514
- //% blockNamespace="scene" group="Tiles"
515
- //% weight=25 blockGap=8
516
- //% help=tiles/get-tile-location
610
+ //% blockNamespace="scene" group="Locations"
611
+ //% weight=100 blockGap=8
612
+ //% help=scene/get-tile-location
517
613
  export function getTileLocation(col: number, row: number): Location {
518
614
  const scene = game.currentScene();
519
615
  if (col == undefined || row == undefined || !scene.tileMap) return null;
@@ -549,13 +645,45 @@ namespace tiles {
549
645
  //% blockId=maplocationistile block="tile at $location is $tile"
550
646
  //% location.shadow=mapgettile
551
647
  //% tile.shadow=tileset_tile_picker tile.decompileIndirectFixedInstances=true
552
- //% blockNamespace="scene" group="Collisions" blockGap=8
648
+ //% blockNamespace="scene" group="Locations" blockGap=8
649
+ //% weight=40 help=scene/tile-at-location-equals
553
650
  export function tileAtLocationEquals(location: Location, tile: Image): boolean {
554
651
  const scene = game.currentScene();
555
652
  if (!location || !tile || !scene.tileMap) return false;
556
653
  return location.tileSet === scene.tileMap.getImageType(tile);
557
654
  }
558
655
 
656
+ /**
657
+ * Returns true if the tile at the given location is a wall in the current tilemap;
658
+ * otherwise returns false
659
+ * @param location The location to check for a wall
660
+ */
661
+ //% blockId=tiles_tile_at_location_is_wall
662
+ //% block="tile at $location is wall"
663
+ //% location.shadow=mapgettile
664
+ //% blockNamespace="scene" group="Locations" blockGap=8
665
+ //% weight=30
666
+ export function tileAtLocationIsWall(location: Location): boolean {
667
+ if (!location || !location.tileMap) return false;
668
+ return location.isWall();
669
+ }
670
+
671
+ /**
672
+ * Returns the image of the tile at the given location in the current tilemap
673
+ *
674
+ * @param location The location of the image to fetch
675
+ */
676
+ //% blockId=tiles_image_at_location
677
+ //% block="tile image at $location"
678
+ //% location.shadow=mapgettile
679
+ //% weight=0
680
+ //% blockNamespace="scene" group="Locations"
681
+ export function tileImageAtLocation(location: Location): Image {
682
+ const scene = game.currentScene();
683
+ if (!location || !scene.tileMap) return img``;
684
+ return location.getImage();
685
+ }
686
+
559
687
  /**
560
688
  * Center the given sprite on a given location
561
689
  * @param sprite
@@ -563,10 +691,11 @@ namespace tiles {
563
691
  */
564
692
  //% blockId=mapplaceontile block="place $sprite=variables_get(mySprite) on top of $loc"
565
693
  //% loc.shadow=mapgettile
566
- //% blockNamespace="scene" group="Tiles" blockGap=8
567
- //% help=tiles/place
694
+ //% blockNamespace="scene" group="Tilemap Operations" blockGap=8
695
+ //% help=scene/place
696
+ //% weight=100
568
697
  export function placeOnTile(sprite: Sprite, loc: Location): void {
569
- if (!sprite || !loc || !game.currentScene().tileMap) return;
698
+ if (!sprite || !loc || !loc.tileMap) return;
570
699
  loc.place(sprite);
571
700
  }
572
701
 
@@ -578,8 +707,9 @@ namespace tiles {
578
707
  //% blockId=mapplaceonrandomtile block="place $sprite=variables_get(mySprite) on top of random $tile"
579
708
  //% tile.shadow=tileset_tile_picker
580
709
  //% tile.decompileIndirectFixedInstances=true
581
- //% blockNamespace="scene" group="Tiles" blockGap=8
582
- //% help=tiles/place-on-random-tile
710
+ //% blockNamespace="scene" group="Tilemap Operations"
711
+ //% help=scene/place-on-random-tile
712
+ //% weight=90
583
713
  export function placeOnRandomTile(sprite: Sprite, tile: Image): void {
584
714
  if (!sprite || !game.currentScene().tileMap) return;
585
715
  const loc = getRandomTileByType(tile);
@@ -594,8 +724,9 @@ namespace tiles {
594
724
  //% blockId=mapgettilestype block="array of all $tile locations"
595
725
  //% tile.shadow=tileset_tile_picker
596
726
  //% tile.decompileIndirectFixedInstances=true
597
- //% blockNamespace="scene" group="Tiles" blockGap=8
598
- //% help=tiles/get-tiles-by-type
727
+ //% blockNamespace="scene" group="Locations" blockGap=8
728
+ //% help=scene/get-tiles-by-type
729
+ //% weight=10
599
730
  export function getTilesByType(tile: Image): Location[] {
600
731
  const scene = game.currentScene();
601
732
  if (!tile || !scene.tileMap) return [];
@@ -615,4 +746,19 @@ namespace tiles {
615
746
  const sample = scene.tileMap.sampleTilesByType(index, 1);
616
747
  return sample[0];
617
748
  }
749
+
750
+ /**
751
+ * A tilemap
752
+ */
753
+ //% blockId=tiles_tilemap_editor shim=TD_ID
754
+ //% weight=200 blockGap=8
755
+ //% block="tilemap $tilemap"
756
+ //% tilemap.fieldEditor="tilemap"
757
+ //% tilemap.fieldOptions.decompileArgumentAsString="true"
758
+ //% tilemap.fieldOptions.filter="tile"
759
+ //% tilemap.fieldOptions.taggedTemplate="tilemap"
760
+ //% blockNamespace="scene" group="Tilemaps" duplicateShadowOnDrag
761
+ export function _tilemapEditor(tilemap: TileMapData): TileMapData {
762
+ return tilemap;
763
+ }
618
764
  }
@@ -56,7 +56,7 @@ const pxsim_pxtrt = pxsim.pxtrt;
56
56
  const pxsim_numops = pxsim.numops;
57
57
 
58
58
 
59
- function _main___P48394(s) {
59
+ function _main___P48426(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___48635 = (undefined);
70
- globals._pollEventQueue___48648 = (undefined);
69
+ globals._intervals___48667 = (undefined);
70
+ globals._pollEventQueue___48680 = (undefined);
71
71
  r0 = undefined;
72
72
  return leave(s, r0)
73
73
  default: oops()
74
74
  } } }
75
- _main___P48394.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"characterlcd.ts","functionName":"<main>","argumentNames":[]}
76
- _main___P48394.continuations = [ ]
75
+ _main___P48426.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"characterlcd.ts","functionName":"<main>","argumentNames":[]}
76
+ _main___P48426.continuations = [ ]
77
77
 
78
- function _main___P48394_mk(s) {
78
+ function _main___P48426_mk(s) {
79
79
  checkStack(s.depth);
80
80
  return {
81
- parent: s, fn: _main___P48394, depth: s.depth + 1,
81
+ parent: s, fn: _main___P48426, 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___P48394_mk(s) {
88
88
 
89
89
  const breakpoints = setupDebugger(1, [])
90
90
 
91
- return _main___P48394
91
+ return _main___P48426
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___P95856(s) {
59
+ function _main___P95952(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___96097 = (undefined);
70
- globals._pollEventQueue___96110 = (undefined);
69
+ globals._intervals___96193 = (undefined);
70
+ globals._pollEventQueue___96206 = (undefined);
71
71
  r0 = undefined;
72
72
  return leave(s, r0)
73
73
  default: oops()
74
74
  } } }
75
- _main___P95856.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"tsl2591.ts","functionName":"<main>","argumentNames":[]}
76
- _main___P95856.continuations = [ ]
75
+ _main___P95952.info = {"start":0,"length":0,"line":0,"column":0,"endLine":0,"endColumn":0,"fileName":"tsl2591.ts","functionName":"<main>","argumentNames":[]}
76
+ _main___P95952.continuations = [ ]
77
77
 
78
- function _main___P95856_mk(s) {
78
+ function _main___P95952_mk(s) {
79
79
  checkStack(s.depth);
80
80
  return {
81
- parent: s, fn: _main___P95856, depth: s.depth + 1,
81
+ parent: s, fn: _main___P95952, 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___P95856_mk(s) {
88
88
 
89
89
  const breakpoints = setupDebugger(1, [])
90
90
 
91
- return _main___P95856
91
+ return _main___P95952
92
92
  })