Skip to content

Commit c1b2823

Browse files
Now using FastRandom. Also added TilemapExt with block for sampling tile locations.
1 parent 0bfcc2f commit c1b2823

7 files changed

Lines changed: 39 additions & 22 deletions

File tree

.github/makecode/blocks.png

9.65 KB
Loading

.github/makecode/blocksdiff.png

141 KB
Loading

main.blocks

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="enZVp(wYA^KGcrR=P@z-">mySprite</variable><variable type="KIND_SpriteKind" id="RWZ@JVP3b@inZ{*W{;DD">Player</variable><variable type="KIND_SpriteKind" id="~aL]x04xDU=?){oKU1Mw">Projectile</variable><variable type="KIND_SpriteKind" id="zpFBQ!tGVMH,cq~pmTO4">Food</variable><variable type="KIND_SpriteKind" id=",}wYQz2I##DWvrGEo*=u">Enemy</variable></variables><block type="pxt-on-start" id="t;)IqYD1O:!}V5y:[#W/" x="0" y="0"><statement name="HANDLER"><block type="set_current_tilemap" id="rSgAhY/9Sc.Pj/Dwraye"><value name="tilemap"><shadow type="tiles_tilemap_editor"></shadow><block type="maze_generateTilemap" id="9(VWD-=2)aWF~xnc6)l*"><mutation xmlns="http://www.w3.org/1999/xhtml" _expanded="0" _input_init="true"></mutation><field name="algorithm">MazeAlgorithm.Ellers</field><value name="mazeWidth"><shadow type="math_number" id="LW9.R~`_3GFat`Onr370"><field name="NUM">8</field></shadow></value><value name="mazeHeight"><shadow type="math_number" id="Y(Rc!17,O;Bm8GyM6:#Z"><field name="NUM">8</field></shadow></value><value name="wall"><shadow type="tileset_tile_picker" id="DP=9t7}p0cA$rhpbW@1{"><field name="tile">sprites.dungeon.floorDark0</field></shadow></value><value name="floor"><shadow type="tileset_tile_picker" id="06GL@+aqbR+G~aTb`U0J"><field name="tile">sprites.castle.tileGrass2</field></shadow></value></block></value><next><block type="variables_set" id="PgaXwA8rP:vZ60{zzVfH"><field name="VAR" id="enZVp(wYA^KGcrR=P@z-">mySprite</field><value name="VALUE"><shadow type="math_number"><field name="NUM">0</field></shadow><block type="spritescreate" id="jB|wD?QgTIh6#ShZdg)R"><value name="img"><shadow type="screen_image_picker" id="|;EOlCt|jv}C7?S;+[42"><field name="img">img`
1+
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable type="KIND_SpriteKind" id="`}O?dISCnE!;@dE3J%0_">Player</variable><variable type="KIND_SpriteKind" id="(c{hv0CHhW$MCn=D{xrr">Projectile</variable><variable type="KIND_SpriteKind" id="vr!fYKM264Ic1]xg03Sc">Food</variable><variable type="KIND_SpriteKind" id="9ur_~EqG0TwKF?WC1Reh">Enemy</variable><variable id="WR{lx^-=?vmD;j/?h|c|">mySprite</variable><variable id="A,{^bz[yv}GoxP|3,~)a">value</variable><variable id=",iYv.,6Qo,4orRY:G@L-">list</variable></variables><block type="pxt-on-start" id="w[XHg?FkCqS6:M;.~I!z" x="0" y="0"><statement name="HANDLER"><block type="set_current_tilemap" id="qy5|%3EpVF6cL]Bqk82#"><value name="tilemap"><shadow type="tiles_tilemap_editor"></shadow><block type="maze_generateTilemap" id="*Rx9}]dQE1I(sl5pbu3*"><mutation xmlns="http://www.w3.org/1999/xhtml" _expanded="1" _input_init="true"></mutation><field name="algorithm">MazeAlgorithm.Ellers</field><value name="mazeWidth"><shadow type="math_number" id="C-w1G171ecowxZhS.-^W"><field name="NUM">8</field></shadow></value><value name="mazeHeight"><shadow type="math_number" id="4RQ-#0yp{.|sxXD*1`os"><field name="NUM">8</field></shadow></value><value name="wall"><shadow type="tileset_tile_picker" id="(%s*@w%bUkJ@Z_z5TsSn"><field name="tile">sprites.dungeon.floorDark0</field></shadow></value><value name="floor"><shadow type="tileset_tile_picker" id="g3;B2MCw,=7,4a-^DWor"><field name="tile">sprites.castle.tileGrass2</field></shadow></value><value name="corridorSize"><shadow type="math_number" id="0itND.9pQ(jMK6`n!]tr"><field name="NUM">2</field></shadow></value><value name="seed"><shadow type="math_number" id="3fm(bPnbcymXHGYg:K`e"><field name="NUM">0</field></shadow></value></block></value><next><block type="variables_set" id="_cDI{EFHzUgbgY_.[@vz"><field name="VAR" id="WR{lx^-=?vmD;j/?h|c|">mySprite</field><value name="VALUE"><shadow type="math_number"><field name="NUM">0</field></shadow><block type="spritescreate" id="jt}uU::S13(+xmA$*1pW"><value name="img"><shadow type="screen_image_picker" id="H%h*C/IU:r(-{iCq9fnk"><field name="img">img`
22
........................
33
.....ffff...............
44
...fff22fff.............
@@ -23,4 +23,4 @@ fbbbbf2222fd4...........
2323
........................
2424
........................
2525
........................
26-
`</field><data>{"commentRefs":[],"fieldData":{"img":null}}</data></shadow></value><value name="kind"><shadow type="spritekind" id="/3*=dSbF@e86tMJxp4ZI"><field name="MEMBER">Player</field></shadow></value></block></value><next><block type="mapplaceontile" id="@=XvX8AunMoqVIpzymgh"><value name="sprite"><shadow type="variables_get" id="u=j!hH[IbsjUg,6L|MJX"><field name="VAR" id="enZVp(wYA^KGcrR=P@z-">mySprite</field></shadow></value><value name="loc"><shadow type="mapgettile" id="dD^v%(GpbjP~sG{RKFP]"><value name="col"><shadow type="math_number" id="qn%~i$Wib]cVscwE%Q2y"><field name="NUM">2</field></shadow></value><value name="row"><shadow type="math_number" id="Pj.dN!Ut#yGu%5v6o-hV"><field name="NUM">2</field></shadow></value></shadow></value><next><block type="game_control_sprite" id="U_,E~iNf6$On@n63UhSx"><mutation xmlns="http://www.w3.org/1999/xhtml" _expanded="0" _input_init="true"></mutation><value name="sprite"><shadow type="variables_get" id="toc1Z[+JfsA;E7aAvTt."><field name="VAR" id="enZVp(wYA^KGcrR=P@z-">mySprite</field></shadow></value><next><block type="camerafollow" id="f]TzvgR]H^!|0$Dn9L6x"><value name="sprite"><shadow type="variables_get" id="+)}d#BcT3Z9G6`v;UA]3"><field name="VAR" id="enZVp(wYA^KGcrR=P@z-">mySprite</field></shadow></value><next><block type="controls_repeat_ext" id="exq_m{U]yP~}Uz:1/=3a"><value name="TIMES"><shadow type="math_whole_number" id="i+W(iq.72Chrv4{E`OUB"><field name="NUM">10</field></shadow></value><statement name="DO"><block type="mapsettileat" id="`oUC}3-R%6bGoxY_+M^K"><value name="tile"><shadow type="tileset_tile_picker" id="buXE(cYC~5r!pzbo0(]u"><field name="tile">sprites.dungeon.chestClosed</field></shadow></value><value name="loc"><shadow type="mapgettile"></shadow><block type="array_pickRandom" id="C[]AXAkZ(AdkEB;wpM}L"><value name="list"><block type="mapgettilestype" id="`o235XvM,sH?{MeD./@@"><value name="tile"><shadow type="tileset_tile_picker" id="6XHC*b7)V%S+JuUBh59?"><field name="tile">sprites.castle.tileGrass2</field></shadow></value></block></value></block></value></block></statement></block></next></block></next></block></next></block></next></block></next></block></statement></block></xml>
26+
`</field><data>{"commentRefs":[],"fieldData":{"img":"H%h*C/IU:r(-{iCq9fnk"}}</data></shadow></value><value name="kind"><shadow type="spritekind" id="T}`E1HD+CLQKrUA`F9{v"><field name="MEMBER">Player</field></shadow></value></block></value><next><block type="mapplaceontile" id="j]nDg]e*.ckV-MYe:lr@"><value name="sprite"><shadow type="variables_get" id=":/Zqf=1z:ttANcBbW`HT"><field name="VAR" id="WR{lx^-=?vmD;j/?h|c|">mySprite</field></shadow></value><value name="loc"><shadow type="mapgettile" id="AoZZXP*@wF@;LI[,z-J+"><value name="col"><shadow type="math_number" id="fMUam(l_iczY_wBIvxUo"><field name="NUM">2</field></shadow></value><value name="row"><shadow type="math_number" id="zeJsyIcGCTw$LvHBlIR6"><field name="NUM">2</field></shadow></value></shadow></value><next><block type="game_control_sprite" id="E[nB@r9c`%j`VVq`t}lk"><mutation xmlns="http://www.w3.org/1999/xhtml" _expanded="0" _input_init="true"></mutation><value name="sprite"><shadow type="variables_get" id="l7O~;]{H*P|0WlcJE(i_"><field name="VAR" id="WR{lx^-=?vmD;j/?h|c|">mySprite</field></shadow></value><next><block type="camerafollow" id="T5Gi2d;/gt*0cPcx#@V^"><value name="sprite"><shadow type="variables_get" id="Pa53eB1`iFl_:2j]IFve"><field name="VAR" id="WR{lx^-=?vmD;j/?h|c|">mySprite</field></shadow></value><next><block type="pxt_controls_for_of" id="9I!TH,9WbinrA8.{T-,k"><value name="VAR"><shadow type="variables_get_reporter" id="zNdI#;{8T.x3S#tq#gZ7"><field name="VAR" id="A,{^bz[yv}GoxP|3,~)a">value</field></shadow></value><value name="LIST"><shadow type="variables_get" id="f!`R!{S8-fU|J6rk10o1"><field name="VAR" id=",iYv.,6Qo,4orRY:G@L-">list</field></shadow><block type="getRandomTilesByType" id="@JB}}1(iL#Z9_5xq{+x["><value name="maxCount"><shadow type="math_number" id="$Nk}tD%pyP4h/@gqk?gS"><field name="NUM">10</field></shadow></value><value name="tile"><shadow type="tileset_tile_picker" id="v6~{8{j4f6usbC^e_=BZ"><field name="tile">sprites.castle.tileGrass2</field></shadow></value></block></value><statement name="DO"><block type="mapsettileat" id="LIjaz8$8:p17IVhatOJ%"><value name="tile"><shadow type="tileset_tile_picker" id="x~_?GX+oA~oWBLeA_D#("><field name="tile">sprites.dungeon.chestClosed</field></shadow></value><value name="loc"><shadow type="mapgettile" id="T2G)S`0i,GO^L@l4+qn|"></shadow><block type="variables_get" id="ZFYHca^Q6CkGHGv+:PGe"><field name="VAR" id="A,{^bz[yv}GoxP|3,~)a">value</field></block></value></block></statement></block></next></block></next></block></next></block></next></block></next></block></statement></block></xml>

main.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tiles.setCurrentTilemap(maze.generateTilemap(MazeAlgorithm.Ellers, 8, 8, sprites.dungeon.floorDark0, sprites.castle.tileGrass2))
1+
tiles.setCurrentTilemap(maze.generateTilemap(MazeAlgorithm.Ellers, 8, 8, sprites.dungeon.floorDark0, sprites.castle.tileGrass2, 2))
22
let mySprite = sprites.create(img`
33
........................
44
.....ffff...............
@@ -28,6 +28,6 @@ let mySprite = sprites.create(img`
2828
tiles.placeOnTile(mySprite, tiles.getTileLocation(2, 2))
2929
controller.moveSprite(mySprite)
3030
scene.cameraFollowSprite(mySprite)
31-
for (let index = 0; index < 10; index++) {
32-
tiles.setTileAt(tiles.getTilesByType(sprites.castle.tileGrass2)._pickRandom(), sprites.dungeon.chestClosed)
31+
for (let value of getRandomTilesByType(sprites.castle.tileGrass2, 10)) {
32+
tiles.setTileAt(value, sprites.dungeon.chestClosed)
3333
}

maze.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ enum MazeAlgorithm {
66

77
//% weight=100 color=#0fbc11 icon="╬"
88
namespace maze {
9-
109
/**
1110
* Generates a maze using the chosen algorithm
1211
* @param mazeWidth width of maze
@@ -15,15 +14,16 @@ namespace maze {
1514
* @param floor tile to use for floors
1615
* @param corridorSize width of corridors
1716
*/
18-
//% block="Create $algorithm maze tilemap, width $mazeWidth height $mazeHeight wall $wall floor $floor || corridorSize $corridorSize"
17+
//% block="Create $algorithm maze tilemap, width $mazeWidth height $mazeHeight wall $wall floor $floor || corridorSize $corridorSize seed $seed"
1918
//% wall.shadow=tileset_tile_picker
2019
//% floor.shadow=tileset_tile_picker
2120
//% corridorSize.defl=2
2221
//% inlineInputMode=inline
23-
export function generateTilemap(algorithm: MazeAlgorithm, mazeWidth: number, mazeHeight: number, wall: Image, floor: Image, corridorSize?: number): tiles.TileMapData {
24-
return algorithm === MazeAlgorithm.BinaryTree ? generateBinaryTreeTilemap(mazeWidth, mazeHeight, wall, floor, corridorSize || 2) :
25-
algorithm === MazeAlgorithm.Sidewinder ? generateSidewinderTilemap(mazeWidth, mazeHeight, wall, floor, corridorSize || 2) :
26-
generateEllersTilemap(mazeWidth, mazeHeight, wall, floor, corridorSize || 2);
22+
export function generateTilemap(algorithm: MazeAlgorithm, mazeWidth: number, mazeHeight: number, wall: Image, floor: Image, corridorSize?: number, seed?:number|undefined): tiles.TileMapData {
23+
const rng = new Math.FastRandom(seed);
24+
return algorithm === MazeAlgorithm.BinaryTree ? generateBinaryTreeTilemap(rng, mazeWidth, mazeHeight, wall, floor, corridorSize || 2) :
25+
algorithm === MazeAlgorithm.Sidewinder ? generateSidewinderTilemap(rng, mazeWidth, mazeHeight, wall, floor, corridorSize || 2) :
26+
generateEllersTilemap(rng, mazeWidth, mazeHeight, wall, floor, corridorSize || 2);
2727
}
2828

2929
function createTilemap(mazeWidth: number, mazeHeight: number, corridorSize: number, tmTiles: Image[]): tiles.TileMapData {
@@ -51,7 +51,7 @@ namespace maze {
5151
return arr
5252
}
5353

54-
function generateBinaryTreeTilemap(mazeWidth: number, mazeHeight: number, wall: Image, floor: Image, corridorSize: number): tiles.TileMapData {
54+
function generateBinaryTreeTilemap(rng: Math.FastRandom, mazeWidth: number, mazeHeight: number, wall: Image, floor: Image, corridorSize: number): tiles.TileMapData {
5555
let tmData = createTilemap(mazeWidth,mazeHeight,corridorSize,[floor,wall]);
5656
fillWalls(tmData);
5757

@@ -69,7 +69,7 @@ namespace maze {
6969
// If right edge, carve down
7070
x === xMax ? [0,1] :
7171
// Pick random
72-
Math.randomRange(0,1) ? [1,0]: [0,1];
72+
rng.randomBool() ? [1,0]: [0,1];
7373
// Set floor
7474
for (let by = 0; by < corridorSize + cy; ++by)
7575
for (let bx = 0; bx < corridorSize + cx; ++bx) {
@@ -81,7 +81,7 @@ namespace maze {
8181
return tmData;
8282
}
8383

84-
function generateSidewinderTilemap(mazeWidth: number, mazeHeight: number, wall: Image, floor: Image, corridorSize: number): tiles.TileMapData {
84+
function generateSidewinderTilemap(rng: Math.FastRandom, mazeWidth: number, mazeHeight: number, wall: Image, floor: Image, corridorSize: number): tiles.TileMapData {
8585
// https://weblog.jamisbuck.org/2011/2/3/maze-generation-sidewinder-algorithm.html
8686
let tmData = createTilemap(mazeWidth, mazeHeight, corridorSize, [floor, wall]);
8787
fillWalls(tmData);
@@ -106,7 +106,7 @@ namespace maze {
106106
// If right edge, carve down
107107
x === xMax ? [0,1] :
108108
// Pick random
109-
Math.randomRange(0,1) ? [1,0]: [0,1];
109+
rng.randomBool() ? [1,0]: [0,1];
110110

111111
if(cx === 1) {
112112
tx += corridorSize;
@@ -118,7 +118,7 @@ namespace maze {
118118
}
119119
if(cy === 1){
120120
ty += corridorSize;
121-
tx = Math.randomRange(start,end) * (corridorSize + 1) + 1;
121+
tx = rng.randomRange(start,end) * (corridorSize + 1) + 1;
122122
for (let i = 0; i < corridorSize; ++i) {
123123
tmData.setTile(tx+i, ty, 0);
124124
tmData.setWall(tx+i, ty, false);
@@ -130,7 +130,7 @@ namespace maze {
130130
return tmData;
131131
}
132132

133-
function generateEllersTilemap(mazeWidth: number, mazeHeight: number, wall: Image, floor: Image, corridorSize: number): tiles.TileMapData {
133+
function generateEllersTilemap(rng: Math.FastRandom, mazeWidth: number, mazeHeight: number, wall: Image, floor: Image, corridorSize: number): tiles.TileMapData {
134134
// https://weblog.jamisbuck.org/2010/12/29/maze-generation-eller-s-algorithm#
135135
let tmData = createTilemap(mazeWidth, mazeHeight, corridorSize, [floor, wall]);
136136
fillWalls(tmData);
@@ -144,7 +144,7 @@ namespace maze {
144144
for (let x = 0; x < mazeWidth; x++) {
145145
let tx = x * (corridorSize + 1) + 1;
146146

147-
const shouldMergeRight = x < xMax && currentRow[x] !== currentRow[x+1] && (y == yMax || Math.randomRange(0, 1));
147+
const shouldMergeRight = x < xMax && currentRow[x] !== currentRow[x+1] && (y == yMax || rng.randomBool());
148148

149149
if (shouldMergeRight ) {
150150
const setToAbsorb = currentRow[x + 1];
@@ -175,13 +175,13 @@ namespace maze {
175175
for (const s of Object.keys(sets)) {
176176
let xs = sets[s];
177177
for (let i = xs.length - 1; i > 0; i--) {
178-
const j = Math.floor(Math.random() * i);
178+
const j = Math.floor(rng.randomRange(0,i));
179179
const k = xs[i];
180180
xs[i] = xs[j];
181181
xs[j] = k;
182182
}
183183

184-
xs = xs.slice(0, Math.randomRange(1,xs.length));
184+
xs = xs.slice(0, rng.randomRange(1,xs.length));
185185

186186
for (const x of xs) {
187187
let tx = x * (corridorSize + 1) + 1;

pxt.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
},
88
"files": [
99
"README.md",
10-
"maze.ts"
10+
"maze.ts",
11+
"tilemapExt.ts"
1112
],
1213
"testFiles": [
1314
"main.blocks",
@@ -25,5 +26,5 @@
2526
"supportedTargets": [
2627
"arcade"
2728
],
28-
"preferredEditor": "tsprj"
29+
"preferredEditor": "blocksprj"
2930
}

tilemapExt.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Add your code here
2+
/**
3+
* Get a random tile of the given type
4+
* @param tile the type of tile to get a random selection of
5+
*/
6+
//% blockNamespace=scene
7+
//% group=Locations
8+
//% block="array of max $maxCount $tile locations"
9+
//% tile.shadow=tileset_tile_picker
10+
function getRandomTilesByType(tile: Image, maxCount: number): tiles.Location[] {
11+
const scene = game.currentScene();
12+
if (!tile || !scene.tileMap)
13+
return undefined;
14+
const index = scene.tileMap.getImageType(tile);
15+
return scene.tileMap.sampleTilesByType(index, maxCount);
16+
}

0 commit comments

Comments
 (0)