@@ -5,10 +5,59 @@ enum LineType {
55
66//% blockNamespace=scene
77namespace tilesExt {
8+ import TL = tiles . Location ;
89
10+ /**
11+ * Iterates over a line between two locations. If the handler returns Truelike, then the iteration is stopped
12+ * and the handlers return value is returned, otherwise the iteration runs to completion and returns undefined.
13+ * @param lineType width of maze
14+ * @param l1 start
15+ * @param l2 end
16+ * @param exclusive exclude the endpoints
17+ * @param handler a handler which is invoked for each point
18+ * @returns undefined if the whole line was iterated
19+ */
20+ //% blickId=tilesExt_line
21+ //% block="A $lineType line from $l1 to $l2 || exclusive $exclusive"
22+ //% exclusive.defl=false
23+ //% inlineInputMode=inline
924 //% l1.shadow=mapgettile
1025 //% l2.shadow=mapgettile
11- export function coveringLineBetweenTiles < T > ( l1 : tiles . Location , l2 : tiles . Location , exclusive : boolean , handler : ( col : number , row : number ) => T ) : T {
26+ //% draggableParameters="reporter"
27+ export function line < T > ( lineType : LineType , l1 : TL , l2 : TL , exclusive : boolean , handler : ( col : number , row : number ) => T ) : T {
28+ return lineType === LineType . Diagonal ? diagonalLine ( l1 , l2 , exclusive , handler ) :
29+ lineType === LineType . Covering ? coveringLine ( l1 , l2 , exclusive , handler ) :
30+ undefined ;
31+ }
32+
33+ function lerp ( start : number , end : number , t : number ) {
34+ return start * ( 1.0 - t ) + t * end ;
35+ }
36+
37+ function diagonalLine < T > ( l1 : TL , l2 : TL , exclusive : boolean , handler : ( col : number , row : number ) => T ) : T {
38+ const dx = l2 . col - l1 . col , dy = l2 . row - l1 . row ;
39+ const N = Math . max ( Math . abs ( dx ) , Math . abs ( dy ) ) ;
40+ if ( N <= 0 ) {
41+ return exclusive ? undefined : handler ( l1 . col , l1 . row ) ;
42+ } else {
43+ const lastN = N - ( exclusive ? 1 : 0 ) ;
44+ for ( let step = ( exclusive ? 1 : 0 ) ; step <= lastN ; step ++ ) {
45+ let t = step / N ;
46+ const res = handler (
47+ Math . round ( lerp ( l1 . col , l2 . col , t ) ) ,
48+ Math . round ( lerp ( l1 . row , l2 . row , t ) )
49+ ) ;
50+ if ( res ) return res ;
51+ }
52+ }
53+
54+ return undefined ;
55+ }
56+
57+
58+
59+
60+ export function coveringLine < T > ( l1 : TL , l2 : TL , exclusive : boolean , handler : ( col : number , row : number ) => T ) : T {
1261 // https://www.redblobgames.com/grids/line-drawing/#stepping
1362 const dx = l2 . col - l1 . col , dy = l2 . row - l1 . row ;
1463 const absx = Math . abs ( dx ) , absy = Math . abs ( dy ) ;
@@ -45,16 +94,16 @@ namespace tilesExt {
4594 return undefined ;
4695 }
4796
48- export function isWallBetweenLocations ( l1 : tiles . Location , l2 : tiles . Location , tileMap ?: tiles . TileMap ) : tiles . Location | undefined {
97+ export function isWallBetweenLocations ( l1 : TL , l2 : TL , tileMap ?: tiles . TileMap ) : TL | undefined {
4998 tileMap = tileMap || game . currentScene ( ) . tileMap ;
50- return coveringLineBetweenTiles ( l1 , l2 , true , ( x , y ) => tileMap . isObstacle ( x , y ) ? new tiles . Location ( x , y , l1 . tileMap ) : undefined ) ;
99+ return coveringLine ( l1 , l2 , true , ( x , y ) => tileMap . isObstacle ( x , y ) ? new TL ( x , y , l1 . tileMap ) : undefined ) ;
51100 }
52101
53102
54- export function setTileBetweenLocations ( l1 : tiles . Location , l2 : tiles . Location , im : Image , tileMap ?: tiles . TileMap ) : void {
103+ export function setTileBetweenLocations ( l1 : TL , l2 : TL , im : Image , tileMap ?: tiles . TileMap ) : void {
55104 tileMap = tileMap || game . currentScene ( ) . tileMap ;
56105 const index = tileMap . getImageType ( im ) ;
57- coveringLineBetweenTiles ( l1 , l2 , false , ( x , y ) => tileMap . setTileAt ( x , y , index ) ) ;
106+ coveringLine ( l1 , l2 , false , ( x , y ) => tileMap . setTileAt ( x , y , index ) ) ;
58107 }
59108
60109
@@ -66,7 +115,7 @@ namespace tilesExt {
66115 //% group=Locations
67116 //% block="array of max $maxCount $tile locations"
68117 //% tile.shadow=tileset_tile_picker
69- export function getRandomTilesByType ( tile : Image , maxCount : number ) : tiles . Location [ ] {
118+ export function getRandomTilesByType ( tile : Image , maxCount : number ) : TL [ ] {
70119 const scene = game . currentScene ( ) ;
71120 if ( ! tile || ! scene . tileMap )
72121 return undefined ;
0 commit comments