asobi

全11章

はじめかた

インストールから、動く絵ができるまで。一歩ずつ。

01 / 11

インストールと、最初の1分

gem を入れます。必要なのは Ruby 3.2 以上だけです。ほかには何も要りません。

ターミナルで asobi と打ちます。最初のときは、play.rb という小さなスケッチを書いて、ブラウザで開きます。中身はこれです。

# Change anything and save. The picture follows.
flower = petal.repeat(8).in_fan.colored(:crimson, :navy)

show flower.spin(every: 8)
遊び場で開く

このステップの言葉 show

play.rb を好きなエディタで開いて、数字を1つ書き換えて保存してください。ブラウザの絵がひとりでに変わります。8 を 12 にしてみましょう。

flower = petal.repeat(12).in_fan.colored(:crimson, :navy)

show flower.spin(every: 8)
遊び場で開く

止めるときは、ターミナルで Ctrl-C を押します。ほかのファイルは asobi file.rb か ruby file.rb で動かせます。

02 / 11

形を作る

形の言葉が絵を作り、show がそれを画面に出します。最初の1枚は、これだけで描けます。

show circle
遊び場で開く

このステップの言葉 circle show

数字はどれも省けるので、書かなくても絵は出ます。自分で決めたいときは、数字に名前を付けて書きます。

show circle(radius: 30)
遊び場で開く

形はたくさんあります。1つずつ試してみてください。rect、triangle、star、heart、moon、cloud。

show star(points: 7, radius: 30)
遊び場で開く

このステップの言葉 star heart rect triangle moon cloud

絵は値なので、変数に入れておけます。シールのようなものだと思ってください。1枚作っておいて、あとからいろいろ頼みます。

dot = circle(10)
show dot
遊び場で開く

長さに単位はなく、絵は画面にぴったり収まります。大事なのは比率だけです。

03 / 11

増やす

repeat は絵を増やします。ここでは丸が5つあります。ただ、全部同じ場所に重なっているので、1つにしか見えません。

show circle.repeat(5)
遊び場で開く

このステップの言葉 repeat

それを横に並べます。増やすことと並べることは、別々の言葉です。

show circle.repeat(5).in_row
遊び場で開く

このステップの言葉 in_row

* は repeat の短い書き方です。asobi の記号は2つだけで、これはそのうちの1つです。

dots = circle * 5
show dots.in_row(gap: 6)
遊び場で開く

このステップの言葉 *

04 / 11

並べる

in_ring は、増やした絵を円周に等しく並べます。輪の大きさは書いていませんが、隣どうしがぶつからない大きさを自分で選びます。

show circle(5).repeat(12).in_ring
遊び場で開く

このステップの言葉 in_ring

in_grid は表にして並べます。列の数は、名前なしで書けます。

show square.repeat(12).in_grid(4, gap: 4)
遊び場で開く

このステップの言葉 in_grid

petal(花びら)は中心から真上へ伸びます。コピーして in_fan で少しずつ回すと、花になります。

show petal.repeat(8).in_fan
遊び場で開く

このステップの言葉 petal in_fan

並べ方はほかにもあります。in_spiral、in_row、in_column、それからランダムに置く scattered。ばらまいた絵は、実行のたびに変わりますが、保存し直しても動き回ったりはしません。

show circle(3).repeat(150).in_spiral
遊び場で開く

このステップの言葉 in_spiral in_column scattered

コピーを1つずつ違うように変えたいときは change_each を使います。ブロックには、絵と t(最初が 0.0、最後が 1.0 の少し手前)と番号が渡されます。

dots = circle(5).repeat(12).change_each { |dot, t| dot.grow(to: 1 + t * 2) }
show dots.in_row(gap: 4)
遊び場で開く

このステップの言葉 change_each grow

05 / 11

色を付ける

colored で色を塗ります。色は CSS の色名をシンボルで書きます。:crimson、:navy、:skyblue、:gold。何も書かなければ crimson です。

show heart.colored(:crimson)
遊び場で開く

このステップの言葉 colored

絵の集まりに色を複数渡すと、順番に使われます。

show petal.repeat(8).in_fan.colored(:crimson, :navy)
遊び場で開く

虹にするなら hsl を使います。色相は 0 から 360 の角度で、change_each の t は 0 から 1 へ進むので、色相がちょうど一周します。

dots = circle(8).repeat(12).change_each { |dot, t| dot.colored(hsl(t * 360, 80, 55)) }
show dots.in_ring
遊び場で開く

このステップの言葉 hsl

outlined は線だけにします。stroke は塗りを残して輪郭の線を足します。opacity は透け具合を変えます。

show star(radius: 30).colored(:gold).stroke(:orange, width: 3)
遊び場で開く

このステップの言葉 outlined stroke opacity

紙はふつう白です。show に on: を付けると、背景の色が変えられます。

show star(radius: 30).colored(:gold), on: :midnightblue
遊び場で開く

06 / 11

合わせる

on は、絵を別の絵の上に置きます。

show circle(8).colored(:gold).on(circle(20).colored(:navy))
遊び場で開く

このステップの言葉 on

+ も絵を重ねます。あとに書いたものが手前です。もう1つの、asobi の記号です。

sun = circle(30).colored(:gold)
show sun + circle(14).colored(:orange) + circle(5).colored(:crimson)
遊び場で開く

このステップの言葉 + under

beside は横に、above は縦に並べます。できあがりは、やはり1枚の絵です。

show circle.beside(square).above(triangle)
遊び場で開く

このステップの言葉 beside above

ここが大事なところです。何を作っても1枚の絵なので、それをまたコピーしたり、並べたり、塗ったりできます。小さな絵を重ねて顔を作ってみます。

eyes = circle(3).repeat(2).in_row(gap: 12)
smile = arc(10, from: 90, to: 270).outlined(:black, width: 2)
face = eyes.above(smile, gap: 6).on(circle(24).colored(:gold))
show face.repeat(4).in_row(gap: 6)
遊び場で開く

このステップの言葉 arc

07 / 11

オブジェクトに「絵になって」と頼む

どんなオブジェクトにも、to_art で「絵になって」と頼めます。数字は、その半径の丸になります。配列は、絵が横に並びます。

show [4, 8, 12, 16].to_art
遊び場で開く

このステップの言葉 to_art

数字は丸でなくてもかまいません。as: で形を渡すと、数字は大きさになります。

fib = [1, 1, 2, 3, 5, 8, 13]
show fib.to_art(as: star).colored(:gold, :orange), on: :black
遊び場で開く

文字列は文字の絵になります。chars で1文字ずつに分けると、1文字ずつが別の絵になり、色を付けられます。

show "asobi".chars.to_art.colored(:crimson, :navy)
遊び場で開く

このステップの言葉 text

配列の配列は表になります。内側の配列が1行です。

table = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
show table.to_art(as: square).colored(:teal, :navy)
遊び場で開く

show は代わりに to_art を頼んでくれるので、数字のリストをそのまま出すだけなら省けます。色を塗ったり動かしたりするときは、先に頼みます。

show [3, 6, 9, 12]
遊び場で開く

08 / 11

動かす

動きの言葉を付けると、絵が動く絵になります。every は1周にかかる秒数です。

show star(radius: 30).colored(:gold).spin(every: 3)
遊び場で開く

このステップの言葉 spin

動きの言葉は続けて書けます。colored のような、いままでの言葉も動きにそのまま使えます。

flower = petal.repeat(8).in_fan.colored(:crimson, :navy)
show flower.spin(every: 8).pulse(every: 1.5)
遊び場で開く

このステップの言葉 pulse sway bounce orbit fade drift shift_color

one_by_one は、並んだ絵の動きを、1つずつ時間をずらします。丸は自分の中心で脈打つので、輪の形は崩れません。

dots = circle(5).repeat(24).in_ring.colored(:crimson, :orange)
show dots.pulse(every: 2, to: 2).one_by_one
遊び場で開く

このステップの言葉 one_by_one

one_by_one は、ずらしたい動きの言葉のすぐあとに書きます。2つの動きをずらしたいときは、それぞれのあとに書きます。ここでは、色も弾みも1つずつずれます。

hearts = heart(20).repeat(5).in_row(gap: 6)
show hearts.shift_color(:crimson, :orchid).one_by_one.bounce(height: 24).one_by_one
遊び場で開く

動く絵と止まった絵も合わせられます。合わせたものは動きになります。

sun = circle(10).colored(:gold)
planet = circle(4).colored(:skyblue).orbit(radius: 30, every: 5)
show sun + planet, on: :black
遊び場で開く

自分で動きを作りたいときは animate です。絵と t が渡され、t は 0.0 から 1.0 へ進んでは最初に戻ります。

show star(radius: 20).animate(4) { |picture, t| picture.rotate(t * 360).grow(to: 1 + t) }
遊び場で開く

このステップの言葉 animate

09 / 11

光らせる

ここまでの絵は、白い紙に塗ったインクのような、平らな色でした。それが出発点です。豊かさは、あとから1つずつ言葉を足して作ります。まず、暗い背景に、平らな花を置きます。

flower = petal(40, 16).repeat(8).in_fan.colored(:hotpink, :gold)
show flower, on: :black
遊び場で開く

glowing を足します。縁が、絵自身の色で光ります。光は暗い背景でないと見えないので、黒にしてあります。

flower = petal(40, 16).repeat(8).in_fan.colored(:hotpink, :gold)
show flower.glowing, on: :black
遊び場で開く

このステップの言葉 glowing blurred

blended は、絵が下にある絵とどう混ざるかを選びます。:screen(省いたときの値)では光が足し算され、丸が重なったところが明るくなります。下に何かあるから見えるので、ここでは、もう1つの丸と、黒い背景が「下にあるもの」です。

red = circle(30).colored(:crimson).move(left: 14)
blue = circle(30).colored(:dodgerblue).move(right: 14)
show red.blended + blue.blended, on: :black
遊び場で開く

このステップの言葉 blended

colored はグラデーションも作れます。始まりと終わりの色を書きます。絵の集まりでは、全体にまたがって1回流れます。around: true にすると、中心から外へ流れます。

petals = petal(50, 18).repeat(8).in_fan.colored(from: :hotpink, to: :gold, around: true)
show petals.glowing, on: :black
遊び場で開く

このステップの言葉 colored

trail は、動く絵のうしろに、少し前の姿を薄く残します。止まった絵に付けても何も変わりません。

comet = circle(5).colored(:gold).orbit(radius: 30, every: 3).trail(10)
show comet.glowing, on: :black
遊び場で開く

このステップの言葉 trail

最後に、show に grain: true を付けると、紙やフィルムのような細かい粒が全体に乗ります。絵ではなく出し方の指定なので、絵ではなく show に書きます。

comet = circle(5).colored(:gold).orbit(radius: 30, every: 3).trail(10)
show comet.glowing, on: :black, grain: true
遊び場で開く

明るい背景では、shadowed で影を落とすと、切り抜いた紙を重ねたような絵になります。

sun = circle(22).colored(:gold).move(up: 20, right: 40)
hill = ellipse(220, 70).colored(:seagreen).move(down: 50)
show sun.shadowed + hill.shadowed, on: :oldlace
遊び場で開く

このステップの言葉 shadowed

clipped_by は、ある形の窓から覗いたように絵を切り抜きます。ここでは、しま模様をハートの窓から覗きます。

stripes = rect(10, 80).repeat(10).in_row.colored(:crimson, :gold)
show stripes.clipped_by(heart(60))
遊び場で開く

このステップの言葉 clipped_by

10 / 11

ライブで見る、録画する

スケッチを動かすとブラウザが開き、ファイルを見張ります。保存するたびに新しい絵に差し替わり、動きは続きから再生されます。

show circle(30).colored(:crimson).pulse
遊び場で開く

書き間違えても、何も閉じません。最後に出せた絵が残り、画面の下にエラーと直し方のヒントが出ます。直して保存すれば、続きから遊べます。

マウスを動かすと、数秒だけ端に小さな操作が出ます。c キーでコードが絵の上に重なります。r キーで録画を始め、もう一度 r で止めると、ブラウザが動画ファイルを保存します。

show には、背景の色(on:)と紙の大きさ(paper:)も渡せます。

show star(radius: 30).colored(:gold).spin(every: 4), on: :black, paper: [400, 400]
遊び場で開く

絵を残したいときは save です。止まった絵は SVG ファイルに、動きはひとりでに動く HTML ページになります。(試すときは # を消してください。)

flower = petal.repeat(8).in_fan.colored(:crimson, :navy)

# flower.save("flower.svg")
# flower.spin(every: 8).save("flower.html")

show flower.spin(every: 8)
遊び場で開く

このステップの言葉 save

11 / 11

自分のクラスを絵にする

ここが asobi の考え方です。オブジェクトを絵として扱い、絵をオブジェクトとして扱います。自分のクラスに to_art というメソッドを書いて、そのオブジェクトがどんな絵かを教えます。

class Flower
  def initialize(petals, color)
    @petals = petals
    @color = color
  end

  def to_art
    petal(30, 12).repeat(@petals).in_fan.colored(@color)
  end
end

show Flower.new(8, :crimson)
遊び場で開く

これで、自分のオブジェクトを、絵が入れるところなら、どこにでも入れられます。配列の中でも、ほかの絵の隣でも、上でも。

class Flower
  def initialize(petals, color)
    @petals = petals
    @color = color
  end

  def to_art
    petal(30, 12).repeat(@petals).in_fan.colored(@color)
  end
end

garden = [Flower.new(5, :crimson), Flower.new(8, :navy), Flower.new(12, :gold)]
show garden.to_art
遊び場で開く

flower.spin のように、自分のオブジェクトに絵の言葉を直接使いたいときは、クラスに include Asobi::Art の1行を足します。Enumerable と同じ仕組みです。each を書くと map や select が使えるように、to_art を書くと spin や move や colored が使えます。

class Flower
  include Asobi::Art

  def initialize(petals, color)
    @petals = petals
    @color = color
  end

  def to_art
    petal(30, 12).repeat(@petals).in_fan.colored(@color)
  end
end

show Flower.new(8, :navy).spin(every: 6)
遊び場で開く

どんなものでも絵になれます。数字でも名前でも日付でも、クラスが持っているものを、自分でどう見せるか決められます。次は見本集を眺めたり、リファレンスで言葉を調べたりしてみてください。