var finalSize = 10;
var startSize = size;
var startSteps = 5;
function draw(x, y, width, height, xMovement, yMovement, steps) {
// We will fill this in
}
draw(0, 0, startSize, startSize, 0, 0, startSteps);
var finalSize = 3;
var startSteps;
var offset = 2;
var tileStep = (size - offset * 2) / 7;
var startSize = tileStep;
var directions = [-1, 0, 1];
现在也许看起来有点奇怪,因为我们还没将这些变量应用上。
for( var x = offset; x < size - offset; x += tileStep) {
for( var y = offset; y < size - offset; y += tileStep) {
startSteps = 3
draw(x, y, startSize, startSize, 1, 1, startSteps - 1);
}
}
现在可以开始玩耍啦,可以为 steps 赋予随机数。
startSteps = 2 + Math.ceil(Math.random() * 3)
再设置随机方向!
var xDirection = directions[Math.floor(Math.random() * directions.length)]
var yDirection = directions[Math.floor(Math.random() * directions.length)]
draw(x, y, startSize, startSize, xDirection, yDirection, startSteps - 1);
原文:Hypnotic Squares
William Kolomyjec 的工作让我们再次想起一些以前(old school)的生成艺术,专注于简单图形、平铺和递归。
今天我们要复现他的作品之一——催眠方块。
页面中仅有一个 320x320 像素的
<canvas>
。老规矩,以下是初始化代码,其中包括设置 canvas 大小和使用
window.devicePixelRatio
缩放 canvas 以适配视网膜屏幕。现在,需要定义一些变量和创建
draw
函数。该函数会被递归调用,不断在方块内绘制方块,直至方块达到指定的最小尺寸。如果对递归不太了解也没关系,后续会讲解。
draw 函数内的
steps
参数 代表方块递归的次数。目前是固定值,但随后我们会赋予它一些随机性。finalSize
是绘制方块的最小尺寸,即当方块达到此尺寸时,我们将停止绘制。startSteps
在递归时用于计算越来越小的方块尺寸。我们先在 draw 函数内单纯画一个方块。
现在有了一个方块,接着进行递归操作,即 draw 函数会调用自身多次,直至满足某个条件。该条件非常重要,否则会造成死循环。这里我们使用
steps
作为倒数的开始点。哇喔,这就是递归!下面让我解释一下上述代码。
不同的 startSteps 就会有不同的递归程度。
或
当为该值赋予随机数时会有不同的效果。但现在先让我们添加其他效果。
xMovement
和yMovement
两个变量是用于将方块放置在特定方向上。先更改 draw 函数的调用参数,即 xMovement 和 yMovement 均置为 1。此举是为了让方块放置在右下方。
然后计算下方变量。
这看起来有点复杂。我们计算了相邻方块的间距,然后将其按照剩步数(译者注:代码中是
steps + 2
)切分。+2
是为了确保新方块永远不会触碰到上一个方块的边界(译者注:若 + 1,则当 steps 最后为 0 时,会导致发生碰撞)。依次更改 draw 函数的
xMovement
和yMovement
两个参数,你将会看到它是如何移动的。接着我们需要做先前 瓷砖线 教程的事了——将其作为一个瓷砖,然后平铺。
首先定义变量,如方块的平铺密度、方块的偏移量等。我们会将最终尺寸变得更小,并根据
canvas
宽度减去offset
后的大小分割成想要的份数(7)。directions
数组存储着所有可能的方向:-1, 0 & 1
。现在也许看起来有点奇怪,因为我们还没将这些变量应用上。
现在可以开始玩耍啦,可以为
steps
赋予随机数。再设置随机方向!
这就是最终效果——催眠方块。这是使用递归的好例子,也是一副易于上色的艺术作品,特别是在较大的 canvas 上。