Wanted: en.wikipedia.org/wiki/wanted_(2008_film)
(If you don't see the effect, hit "Compile & Run" a couple of times on the same mode while staring at the image (in rounded mode you still might need to search)).
Log in to post a comment.
// You can find the Turtle API reference here: https://turtletoy.net/syntax Canvas.setpenopacity(.7); const mode = 2; // min=0, max=3, step=1 (Rounded, Cornered, Classic, Random) const tileSize = 15; // min=2, max=40, step=1 const threadSize = .55; // min=0, max=.9, step=.05 class Grid { constructor(tileSize) { this.size = tileSize; this.half = this.size / 2; this.centers = []; let nTiles = Math.ceil(100 / this.size); for(let i = Math.floor((nTiles) * -this.size); i <= Math.floor((nTiles) * this.size); i += this.size) { this.centers.push(i); } this.gridSize = this.centers.length; } draw(t) { for(let i = 0; i < this.gridSize; i++) { turtle.jump(this.centers[i] - this.half, -110); turtle.goto(this.centers[i] - this.half, 110); turtle.jump(-110, this.centers[i] - this.half); turtle.goto(110, this.centers[i] - this.half); } } getCenterFor(column, row) { return [this.centers[column], this.centers[row]]; } } // Global code will be evaluated once. const turtle = new Turtle(); const grid = new Grid(tileSize); //grid.draw(turtle); const delta = (tileSize * threadSize) / 2 // The walk function will be called until it returns false. function walk(i) { let col = i % grid.gridSize; let row = i / grid.gridSize | 0; let tile = grid.getCenterFor(col, row); turtle.jump(tile[0], tile[1] - 2); switch(mode) { case 0: roundedThread(col, row, grid, tile, delta); break; case 1: cornerThread(col, row, grid, tile, delta); break; case 2: loom(col, row, grid, tile, delta); break; case 3: random(col, row, grid, tile, delta); break; } return i < (grid.gridSize * grid.gridSize); } const mistakeRow = Math.ceil(Math.random() * (grid.gridSize - 4)) + 2; const mistakeCol = Math.ceil(Math.random() * (grid.gridSize - 4)) + 2; function cornerThread(col, row, grid, tile, delta) { if(col % 2 == 0) { if(row % 2 == 0) { crossVerticalOverHorizontal(grid, tile, delta, mistakeCol == col && mistakeRow == row); } else { diagonalBottomLeftToTopRight(grid, tile, delta, mistakeCol == col && mistakeRow == row); } } else if(row % 2 == 0) { diagonalBottomRightToTopLeft(grid, tile, delta, mistakeCol == col && mistakeRow == row); } else { crossVerticalOverHorizontal(grid, tile, delta, mistakeCol == col && mistakeRow == row); } } function roundedThread(col, row, grid, tile, delta) { if(col % 2 == 0) { if(row % 2 == 0) { crossVerticalOverHorizontal(grid, tile, delta, mistakeCol == col && mistakeRow == row); } else { roundedBottomLeftToTopRight(grid, tile, delta, mistakeCol == col && mistakeRow == row); } } else if(row % 2 == 0) { roundedBottomRightToTopLeft(grid, tile, delta, mistakeCol == col && mistakeRow == row); } else { crossVerticalOverHorizontal(grid, tile, delta, mistakeCol == col && mistakeRow == row); } } function loom(col, row, grid, tile, delta) { if(((col % 2) + row) % 2 == 0) { crossHorizontalOverVertical(grid, tile, delta, mistakeCol == col && mistakeRow == row); } else { crossVerticalOverHorizontal(grid, tile, delta, mistakeCol == col && mistakeRow == row); } } function random(col, row, grid, tile, delta) { switch(Math.ceil(Math.random() * 6)) { case 1: crossVerticalOverHorizontal(grid, tile, delta); break; case 2: diagonalBottomLeftToTopRight(grid, tile, delta); break; case 3: diagonalBottomRightToTopLeft(grid, tile, delta); break; case 4: crossHorizontalOverVertical(grid, tile, delta); break; case 5: roundedBottomLeftToTopRight(grid, tile, delta); break; case 6: roundedBottomRightToTopLeft(grid, tile, delta); break; } } function crossVerticalOverHorizontal(grid, tile, delta, mistake = false) { if(mistake) { return crossHorizontalOverVertical(grid, tile, delta); } //vertical turtle.jump(tile[0] - delta, tile[1] - grid.half); turtle.goto(tile[0] - delta, tile[1] + grid.half); turtle.jump(tile[0] + delta, tile[1] - grid.half); turtle.goto(tile[0] + delta, tile[1] + grid.half); //horizontal turtle.jump(tile[0] - grid.half, tile[1] - delta); turtle.goto(tile[0] - delta, tile[1] - delta); turtle.jump(tile[0] + grid.half, tile[1] - delta); turtle.goto(tile[0] + delta, tile[1] - delta); turtle.jump(tile[0] - grid.half, tile[1] + delta); turtle.goto(tile[0] - delta, tile[1] + delta); turtle.jump(tile[0] + grid.half, tile[1] + delta); turtle.goto(tile[0] + delta, tile[1] + delta); } function crossHorizontalOverVertical(grid, tile, delta, mistake = false) { if(mistake) { return crossVerticalOverHorizontal(grid, tile, delta); } //horizontal turtle.jump(tile[0] - grid.half, tile[1] - delta); turtle.goto(tile[0] + grid.half, tile[1] - delta); turtle.jump(tile[0] - grid.half, tile[1] + delta); turtle.goto(tile[0] + grid.half, tile[1] + delta); //vertical turtle.jump(tile[0] - delta, tile[1] - grid.half); turtle.goto(tile[0] - delta, tile[1] - delta); turtle.jump(tile[0] - delta, tile[1] + grid.half); turtle.goto(tile[0] - delta, tile[1] + delta); turtle.jump(tile[0] + delta, tile[1] - grid.half); turtle.goto(tile[0] + delta, tile[1] - delta); turtle.jump(tile[0] + delta, tile[1] + grid.half); turtle.goto(tile[0] + delta, tile[1] + delta); } function diagonalBottomLeftToTopRight(grid, tile, delta, mistake = false) { if(mistake) { return diagonalBottomRightToTopLeft(grid, tile, delta); } //inside turtle.jump(tile[0] - grid.half, tile[1] - delta); turtle.goto(tile[0] - delta, tile[1] - grid.half); turtle.jump(tile[0] + grid.half, tile[1] + delta); turtle.goto(tile[0] + delta, tile[1] + grid.half); //outside-top turtle.jump(tile[0] - grid.half, tile[1] + delta); turtle.goto(tile[0] - grid.half + (delta / 2), tile[1] + delta); turtle.goto(tile[0] + delta, tile[1] - grid.half + (delta / 2)); turtle.goto(tile[0] + delta, tile[1] - grid.half); let maxx = tile[0] + delta; let maxy = tile[1] + delta; //outside-bottom turtle.jump(tile[0] + grid.half, tile[1] - delta); if(tile[0] + grid.half - (delta / 2) < maxx) { turtle.goto(maxx, tile[1] - delta); turtle.jump(tile[0] - delta, maxy); } else { turtle.goto(tile[0] + grid.half - (delta / 2), tile[1] - delta); turtle.goto(tile[0] - delta, tile[1] + grid.half - (delta / 2)); } turtle.goto(tile[0] - delta, tile[1] + grid.half); } function diagonalBottomRightToTopLeft(grid, tile, delta, mistake = false) { if(mistake) { return diagonalBottomLeftToTopRight(grid, tile, delta); } //inside turtle.jump(tile[0] + grid.half, tile[1] - delta); turtle.goto(tile[0] + delta, tile[1] - grid.half); turtle.jump(tile[0] - grid.half, tile[1] + delta); turtle.goto(tile[0] - delta, tile[1] + grid.half); //outside-bottom turtle.jump(tile[0] - grid.half, tile[1] - delta); turtle.goto(tile[0] - grid.half + (delta / 2), tile[1] - delta); turtle.goto(tile[0] + delta, tile[1] + grid.half - (delta / 2)); turtle.goto(tile[0] + delta, tile[1] + grid.half); let maxx = tile[0] + delta; let miny = tile[1] - delta; //outside-top turtle.jump(tile[0] + grid.half, tile[1] + delta); if(tile[0] + grid.half - (delta / 2) < maxx) { turtle.goto(maxx, tile[1] + delta); turtle.jump(tile[0] - delta, miny); } else { turtle.goto(tile[0] + grid.half - (delta / 2), tile[1] + delta); turtle.goto(tile[0] - delta, tile[1] - grid.half + (delta / 2)); } turtle.goto(tile[0] - delta, tile[1] - grid.half); } var angles = [90]; var r = grid.half + delta; if(Math.sqrt(grid.size * grid.size * 2) < r * 2) { angles = []; let aa = (180 / Math.PI) * Math.acos(Math.sqrt(grid.size * grid.size * 2) / (r*2)); angles.push(45 - aa); angles.push(aa * 2); angles.push(45 - aa); } function roundedBottomLeftToTopRight(grid, tile, delta, mistake = false) { if(mistake) { return roundedBottomRightToTopLeft(grid, tile, delta); } //inside turtle.jump(tile[0] - grid.half, tile[1] - delta); turtle.setheading(0); turtle.circle(-(grid.half - delta), 90)//tile[0] - delta, tile[1] - grid.half); turtle.jump(tile[0] + grid.half, tile[1] + delta); turtle.setheading(180); turtle.circle(-(grid.half - delta), 90)//tile[0] - delta, tile[1] - grid.half); //outside-top turtle.jump(tile[0] - grid.half, tile[1] + delta); turtle.setheading(0); turtle.circle(-r, 90)//tile[0] - delta, tile[1] - grid.half); //outside-bottom turtle.jump(tile[0] + grid.half, tile[1] - delta); turtle.setheading(180); for(let i = 0; i < angles.length; i++) { if(i%2 == 0) { turtle.pendown(); } else { turtle.penup(); } turtle.circle(-r, angles[i])//tile[0] - delta, tile[1] - grid.half); } } function roundedBottomRightToTopLeft(grid, tile, delta, mistake = false) { if(mistake) { return roundedBottomLeftToTopRight(grid, tile, delta); } //inside turtle.jump(tile[0] + grid.half, tile[1] - delta); turtle.setheading(180); turtle.circle((grid.half - delta), 90)//tile[0] - delta, tile[1] - grid.half); turtle.jump(tile[0] - grid.half, tile[1] + delta); turtle.setheading(0); turtle.circle((grid.half - delta), 90)//tile[0] - delta, tile[1] - grid.half); //outside-top turtle.jump(tile[0] + grid.half, tile[1] + delta); turtle.setheading(180); turtle.circle(r, 90)//tile[0] - delta, tile[1] - grid.half); //outside-bottom turtle.jump(tile[0] - grid.half, tile[1] - delta); turtle.setheading(0); for(let i = 0; i < angles.length; i++) { if(i%2 == 0) { turtle.pendown(); } else { turtle.penup(); } turtle.circle(r, angles[i])//tile[0] - delta, tile[1] - grid.half); } }