tiles-1
2012. 06. 01.

A variation of tiles-0.

» launch tiles-1

rint = (a, b) -> parseInt random(a, b)
Array::sample  = -> this[rint(0, this.length)]
Object::keys   = -> _(this).keys()
String::sample = -> this.substr(rint(0, this.length), 1)
Object::each   = (f) ->
  for k, v of this
    f(k, v) if this.hasOwnProperty(k)
  null
Array::each    = (f) -> _(this).each(f)


p5     = processing
sizes  = {}
grids  = {}
shapes = 5
sr     = 0.5

pick_slots = (sz) ->
  slots = []
  sz = parseInt sz
  x  = grids[sz].keys().sample()
  return {ok: false, slots: slots} unless x?

  y = grids[sz][x].keys().sample()

  l2r = random() < 0.5
  target_length = rint(2, 7)
  while x? and y? and slots.length < target_length
    x  = parseInt x
    y  = parseInt y
    slots.push { x: x, y: y }

    # Left-to-right
    if l2r
      x = if grids[sz][x + sz]? then x + sz else null
      y = if x? and grids[sz][x][y]? then y else null
    # Top-to-bottom
    else
      y = if grids[sz][x]? and grids[sz][x][y + sz]? then y + sz else null

  slots.each (p) -> occupy sz, p.x, p.y
  {ok: true, l2r: l2r, slots: slots}

occupy = (sz, x, y) ->
  sizes.each (s, cnt) ->
    s = parseInt s
    step = parseInt s * sr

    sx = floor((x - s) / step) * step
    sy = floor((y - s) / step) * step

    for xx in [sx...(x + sz)] by step
      for yy in [sy...(y + sz)] by step
        if grids[s][xx]? and xx > sx and yy > sy
          delete grids[s][xx][yy]
          if grids[s][xx].keys().length == 0
            delete grids[s][xx]
  null

setup = ->
  stroke 0
  colorMode HSB, 1.0
  rectMode  CENTER
  noFill()
  noLoop()
  mousePressed()

mousePressed = ->
  size       $(window).width(), $(window).height()
  background 1

  colors = for i in [0...rint(5, 10)]
      color(random(1.0), random(0.0, 1.0), random(0.3, 1.0))

  grids = {}
  sizes = {}
  for i in [0...shapes]
    sz = rint(10, 80)
    sizes[sz] = parseInt(p5.width * p5.height /
                         (shapes + 1 + 4) / pow(sz, 2))
  sizes.each (sz, count) ->
    sz = parseInt sz
    step = parseInt sz * sr

    grids[sz] = {}
    for x in [0..p5.width - sz] by step
      grids[sz][x] = {}
      for y in [0..p5.height - sz] by step
        grids[sz][x][y] = 1

  rsizes = _(sizes.keys()).sortBy((e) -> -parseInt(e))
  _(rsizes).each (sz) ->
    sz = parseInt sz
    count = sizes[sz]
    for i in [0...count]
      ret = pick_slots(sz)
      break unless ret.ok

      slots = ret.slots
      l2r = ret.l2r
      if slots.length > 0
        f = slots[0]
        l = _(slots).last()
        w = l.x - f.x + sz
        h = l.y - f.y + sz
        cx = (slots[0].x + _(slots).last().x + sz) / 2
        cy = (slots[0].y + _(slots).last().y + sz) / 2
        pushMatrix()
        translate cx, cy
        rotate(0.015 * random(-PI, PI))
        fill colors.sample()
        rect 0, 0, w, h
        popMatrix()
» capture | close