asobi 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/DESIGN.md +388 -0
- data/LICENSE +21 -0
- data/README.ja.md +154 -0
- data/README.md +157 -0
- data/docs/first-sketch.svg +1 -0
- data/exe/asobi +106 -0
- data/lib/asobi/art.rb +498 -0
- data/lib/asobi/color.rb +236 -0
- data/lib/asobi/core_ext.rb +28 -0
- data/lib/asobi/geometry.rb +126 -0
- data/lib/asobi/live.rb +256 -0
- data/lib/asobi/many.rb +235 -0
- data/lib/asobi/messages.rb +155 -0
- data/lib/asobi/motion.rb +471 -0
- data/lib/asobi/nodes.rb +230 -0
- data/lib/asobi/pure.rb +21 -0
- data/lib/asobi/random.rb +51 -0
- data/lib/asobi/reel.rb +113 -0
- data/lib/asobi/shapes.rb +314 -0
- data/lib/asobi/sketch.rb +207 -0
- data/lib/asobi/svg.rb +352 -0
- data/lib/asobi/top_level.rb +14 -0
- data/lib/asobi/version.rb +5 -0
- data/lib/asobi/web/live.html +34 -0
- data/lib/asobi/web/player.js +295 -0
- data/lib/asobi.rb +12 -0
- metadata +73 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d85221ad8a10d1484ffcde0c42fd47a55c0035e7e876a0f614df340b5a50bb19
|
|
4
|
+
data.tar.gz: fee1f511342cf1eec4eaed1120fbd2be148dfee92fd54c22d7d988f6d2024835
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6d4597d181770c36aa9ba52c2288b0e997082472e6fee69268f69cb8857f664d38b44c5e7f1cc516fd011ed780f7a976ec26c7dc70e1526d769ba2b696df81a5
|
|
7
|
+
data.tar.gz: 687f8f4aeb6daa466c1d3dbe4ae4e322fe11928ef6f3140db7c983f03420c6ecc7694482e0594d3dd31130e6ea7b4679a4c2009f584fa6eea7c38bf3aa3b360a
|
data/DESIGN.md
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
# asobi 設計書
|
|
2
|
+
|
|
3
|
+
Ruby のメディアアート用ライブラリ。gem 名は `asobi`(遊び)、モジュール名は `Asobi`。
|
|
4
|
+
この文書が実装の唯一の基準。コードと食い違ったら、この文書を正とする。
|
|
5
|
+
|
|
6
|
+
## 1. 哲学
|
|
7
|
+
|
|
8
|
+
1. **オブジェクトを絵として扱い、絵をオブジェクトとして扱う。**
|
|
9
|
+
- どの Ruby オブジェクトにも「絵になって」(`to_art`)と頼める。
|
|
10
|
+
- 絵は変数に入れられる値で、メソッドを呼ぶと新しい絵が返る。画面に命令して描くのではない。
|
|
11
|
+
2. **書く人が楽しく、わかりやすく、すぐに遊べる。**
|
|
12
|
+
- 3つがぶつかったら **すぐ遊べる** を一番に守る。次に わかりやすい、その次に 楽しい。
|
|
13
|
+
|
|
14
|
+
p5.js / Processing の `setup` / `draw` とは別物。グローバルな描画状態は持たない。
|
|
15
|
+
|
|
16
|
+
対象は「作品を作る人」。ただし Ruby を学び始めた人が読めること。
|
|
17
|
+
|
|
18
|
+
### 哲学から出る決まり
|
|
19
|
+
|
|
20
|
+
- **省略しても動く。** どの数字も省略でき、いい感じの値で絵が出る。必須の引数で止めない。
|
|
21
|
+
- **言葉で読める。** メソッド名は英語の単語。数字にはキーワード引数で名前を付けられる。
|
|
22
|
+
- **記号は2つだけ。** `*`(増やす)と `+`(重ねる)。
|
|
23
|
+
- **絵は不変。** どのメソッドも新しい絵を返し、元の絵は変わらない。同じ値の絵は `==` で等しい。
|
|
24
|
+
- **エラーは先生。** 何が足りないかと、直し方の例を必ず書く。パソコンの言語が日本語なら日本語、それ以外は英語。
|
|
25
|
+
- **外部ソフトに頼らない。** 実行時の依存は Ruby 標準ライブラリだけ。ブラウザ内(ruby.wasm)でもコアが動くこと。
|
|
26
|
+
|
|
27
|
+
## 2. 使い方の全体像
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
require "asobi"
|
|
31
|
+
|
|
32
|
+
petal = ellipse(width: 12, height: 32).move(up: 22)
|
|
33
|
+
flower = petal.repeat(8).in_fan.colored(:crimson, :navy)
|
|
34
|
+
|
|
35
|
+
show flower.spin(every: 4)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
$ ruby flower.rb # ブラウザが開いて絵が出る。保存するたびに差し替わる
|
|
40
|
+
$ asobi # 見本 play.rb を作って、同じように開く
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`require "asobi"` だけで、形の言葉(`circle` など)と `show` がどこでも使え、
|
|
44
|
+
数字・配列・文字などに `to_art` が付く。
|
|
45
|
+
Ruby 本体に手を入れたくない人は `require "asobi/pure"`(`Asobi.circle(...)`、`Asobi.art(8)` と書く)。
|
|
46
|
+
|
|
47
|
+
## 3. 単位
|
|
48
|
+
|
|
49
|
+
- **長さ**:単位なしの数字。絵の中での比率として効く。画面には自動で収める。
|
|
50
|
+
- **角度**:度。`rotate(45)` は時計回りに45度。`0.25.turn` は 90.0(`Numeric#turn` / `turns`)。
|
|
51
|
+
- **時間**:秒。
|
|
52
|
+
- **座標**:原点は絵の中心。x は右、y は下が正。ただし利用者には `up:` `down:` `left:` `right:` で書かせ、y の向きを意識させない。
|
|
53
|
+
|
|
54
|
+
## 4. 形(どれも原点が中心。引数はすべて省略可)
|
|
55
|
+
|
|
56
|
+
最初の位置引数は「主な大きさ」の短縮形として受け付ける(`circle(12)` は `circle(radius: 12)`)。
|
|
57
|
+
|
|
58
|
+
| 言葉 | 引数と既定値 |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `circle` | `radius: 10` |
|
|
61
|
+
| `ellipse` | `width: 30, height: 20` |
|
|
62
|
+
| `rect` | `width: 30, height: 20` |
|
|
63
|
+
| `square` | `size: 20` |
|
|
64
|
+
| `triangle` | `size: 20`(正三角形、上向き) |
|
|
65
|
+
| `polygon` | `sides: 6, radius: 10`(頂点が上) |
|
|
66
|
+
| `star` | `points: 5, radius: 10, inner: radius * 0.45` |
|
|
67
|
+
| `line` | `length: 20`(横向きの線。塗りなし・黒い線) |
|
|
68
|
+
| `text` | `text("ruby", size: 16, font: nil)` |
|
|
69
|
+
| `path` | `path([0, 0], [40, -30], [80, 0], closed: false, smooth: false)` 点を順につなぐ。`smooth: true` で滑らかな曲線 |
|
|
70
|
+
| `arc` | `radius: 20, from: 0, to: 180`(角度は真上が0、時計回り。線) |
|
|
71
|
+
| `wave` | `length: 100, height: 10, waves: 3`(線) |
|
|
72
|
+
| `ring` | `radius: 20, thickness: 4`(ドーナツ型。穴は透ける) |
|
|
73
|
+
| `heart` | `size: 20` |
|
|
74
|
+
| `petal` | `length: 20, width: 10`(根元が原点、上に伸びる) |
|
|
75
|
+
| `moon` | `size: 20`(三日月) |
|
|
76
|
+
| `drop` | `size: 20`(しずく) |
|
|
77
|
+
| `cloud` | `size: 30` |
|
|
78
|
+
| `space` | `width: 10, height: width`(見えないが場所を取る) |
|
|
79
|
+
| `nothing` | 何もない絵 |
|
|
80
|
+
|
|
81
|
+
色の助け:`hsl(hue, saturation = 70, lightness = 50)`(hue は度 0〜360、他は 0〜100)、`gray(0..100)`。
|
|
82
|
+
|
|
83
|
+
## 5. 絵にできること(`Asobi::Art`)
|
|
84
|
+
|
|
85
|
+
### 合わせる
|
|
86
|
+
|
|
87
|
+
| 言葉 | 意味 |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `a.on(b)` | b の上に a を置く(a が手前) |
|
|
90
|
+
| `a.under(b)` | a の上に b を置く(b が手前) |
|
|
91
|
+
| `a + b` | `a.under(b)` と同じ。あとに書いたほうが手前 |
|
|
92
|
+
| `a.repeat(12)` / `a * 12` | 12個に増やす(並べるまでは同じ場所に重なっている) |
|
|
93
|
+
| `a.beside(b, gap: 0)` | 横に並べる(a が左) |
|
|
94
|
+
| `a.above(b, gap: 0)` | 縦に並べる(a が上) |
|
|
95
|
+
|
|
96
|
+
`with` `|` `/` は用意しない。
|
|
97
|
+
|
|
98
|
+
### 変える
|
|
99
|
+
|
|
100
|
+
| 言葉 | 意味 |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `move(right: 0, left: 0, up: 0, down: 0)` | 動かす |
|
|
103
|
+
| `rotate(45)` | 時計回りに回す(度) |
|
|
104
|
+
| `scale(2)` / `scale(width: 2, height: 1)` | 拡大・縮小 |
|
|
105
|
+
| `grow(to: 2)` / `shrink(to: 0.5)` | `scale` の読みやすい別名 |
|
|
106
|
+
| `mirror` | 左右を反転 |
|
|
107
|
+
| `flip` | 上下を反転 |
|
|
108
|
+
|
|
109
|
+
### 色
|
|
110
|
+
|
|
111
|
+
| 言葉 | 意味 |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `colored(:crimson)` | 塗る色 |
|
|
114
|
+
| `colored(:crimson, :navy, ...)` | 並んだ絵(Many)なら、直下の要素に順番に繰り返して塗る。単独の絵なら最初の色 |
|
|
115
|
+
| `outlined(:black, width: 1)` | 塗りなしで線だけ |
|
|
116
|
+
| `stroke(:black, width: 1)` | 塗りはそのままで線を足す |
|
|
117
|
+
| `opacity(0.5)` | 透明度 |
|
|
118
|
+
|
|
119
|
+
色は CSS の色名のシンボル(`:crimson`)か文字列(`"#ff0066"`、`hsl(...)` の戻り値)。
|
|
120
|
+
既定は黒で塗り、線なし。背景は白(「白い紙に黒」)。
|
|
121
|
+
同じ絵に2回色を付けたら、あとのほうが勝つ。まとまりに付けた色は、中で個別に付けた色を上書きしない(SVG と同じ)。
|
|
122
|
+
|
|
123
|
+
### 効果
|
|
124
|
+
|
|
125
|
+
平らな塗りから先へ進むための言葉。絵にも動きにも使える。数字はすべて省略でき、大きさは絵の長さと同じ単位。
|
|
126
|
+
|
|
127
|
+
| 言葉 | 意味と既定値 |
|
|
128
|
+
|---|---|
|
|
129
|
+
| `glowing(size: 4, color: nil)` | 縁がにじんで光る。`color` を省くと絵自身の色で光る |
|
|
130
|
+
| `blurred(amount: 2)` | ぼかす |
|
|
131
|
+
| `blended(:screen)` | 下の絵との混ざり方。`:screen`(重なると明るく)、`:multiply`(暗く)、`:overlay`、`:lighten`、`:darken`、`:difference`、`:normal` |
|
|
132
|
+
| `shadowed(down: 2, right: 0, blur: 3, color: :black, opacity: 0.4)` | 影を落とす |
|
|
133
|
+
| `clipped_by(shape)` | `shape` の形の窓から覗いたように切り抜く。`shape` は置かれた位置のまま使う |
|
|
134
|
+
| `colored(from: :crimson, to: :navy)` | グラデーション。上から下へ色が変わる。`angle: 90` で向きを変え(度、時計回り)、`around: true` で中心から外へ。並んだ絵(Many)では全体にまたがって1回流れる |
|
|
135
|
+
|
|
136
|
+
- 最初の位置引数は主な数字の短縮形(`glowing(8)`、`blurred(4)`)。
|
|
137
|
+
- 光・ぼかし・影は絵の外側にはみ出す。`bounds` や画面への収め方は、はみ出しぶんを含める。
|
|
138
|
+
- 同じ絵は、効果を付けても `==` で等しく、SVG も同じ文字列になる(定義の id は中身から決め、乱数や連番を使わない)。
|
|
139
|
+
1つのページに複数の絵を埋め込んでも id がぶつかって壊れないこと。
|
|
140
|
+
- 効果は Ruby 標準ライブラリだけで SVG として書き出す(フィルター、グラデーション、クリップパス、`mix-blend-mode`)。
|
|
141
|
+
|
|
142
|
+
画面全体のざらつきは絵ではなく出し方の指定:
|
|
143
|
+
|
|
144
|
+
```ruby
|
|
145
|
+
show flower, grain: true # 紙やフィルムのような細かい粒を全体に乗せる
|
|
146
|
+
show flower, grain: 0.3 # 強さ(0 から 1。true は 0.12)
|
|
147
|
+
flower.save("flower.svg", grain: true)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 測る・出す
|
|
151
|
+
|
|
152
|
+
`width` `height` `bounds`、`to_svg`、`save("flower.svg")`。
|
|
153
|
+
|
|
154
|
+
## 6. 並べる(`Asobi::Many`)
|
|
155
|
+
|
|
156
|
+
`repeat` や配列の `to_art` が返す「絵の集まり」。それ自体が1枚の絵で、`Enumerable` でもある。
|
|
157
|
+
|
|
158
|
+
| 言葉 | 省略時 |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `in_row(gap: 0)` | すき間なし |
|
|
161
|
+
| `in_column(gap: 0)` | すき間なし |
|
|
162
|
+
| `in_grid(columns: nil, gap: 0)` | 列数は個数の平方根を切り上げ |
|
|
163
|
+
| `in_ring(radius: nil, facing_out: false)` | 隣どうしが重ならない半径を自動計算 |
|
|
164
|
+
| `in_fan(over: 360)` | 中心のまわりに少しずつ回す(花びら向け) |
|
|
165
|
+
| `in_spiral(spacing: nil)` | 絵の大きさから自動 |
|
|
166
|
+
| `scattered(over: nil, seed: nil)` | 広さは個数と大きさから自動。`over: 200` は正方形、`over: [300, 100]` は横×縦 |
|
|
167
|
+
| `change_each { \|one, t, i\| ... }` | 1つずつ変える。`t` は 0.0 から 1.0 未満、`i` は番号 |
|
|
168
|
+
|
|
169
|
+
どれも位置引数の短縮形を受け付ける(`in_ring(60)`、`in_grid(4)`)。
|
|
170
|
+
|
|
171
|
+
### ランダム
|
|
172
|
+
|
|
173
|
+
- `seed:` を書かなければ、**実行のたびに違う絵**になる。
|
|
174
|
+
- ただし1回の起動の中では変わらない。ライブ表示中にファイルを保存し直しても、ばらまき方は保たれる。
|
|
175
|
+
- 仕組み:起動時に「その回の種」を1つ決める。スケッチを評価するたびに呼び出しカウンタを0に戻し、
|
|
176
|
+
`seed:` のない `scattered` は「その回の種 + 何番目の呼び出しか」から乱数を作る。
|
|
177
|
+
- `seed: 7` と書けば、いつ誰が実行しても同じ絵。
|
|
178
|
+
|
|
179
|
+
## 7. to_art(オブジェクトを絵にする)
|
|
180
|
+
|
|
181
|
+
| 頼む相手 | なる絵 |
|
|
182
|
+
|---|---|
|
|
183
|
+
| 数字 `8` | 大きさ8の丸。`8.to_art(as: star)` で形を渡せる(その形を、半分の大きさが8になるよう拡大縮小) |
|
|
184
|
+
| マイナスの数字 | 同じ大きさで、塗りなしの線だけ |
|
|
185
|
+
| `0` | 何もない絵 |
|
|
186
|
+
| 配列・範囲 | 中身をそれぞれ絵にして横に並べる(すき間4)。`as:` は中身すべてに伝わる |
|
|
187
|
+
| 配列の配列 | 行を縦に積む(表になる) |
|
|
188
|
+
| 文字列・シンボル | その文字そのままの絵(`text` と同じ) |
|
|
189
|
+
| ハッシュ | 1組ずつ「キーの絵 beside 値の絵」を作り、縦に積む |
|
|
190
|
+
| `nil` | 何もない絵 |
|
|
191
|
+
| 動き(Motion)を含む配列 | 全体が動きになる |
|
|
192
|
+
| `to_art` を持つオブジェクト | その `to_art` の結果 |
|
|
193
|
+
|
|
194
|
+
自作クラスは **`to_art` を書くだけ** で、`show`、配列の `to_art`、`on` / `under` / `beside` などの相手として渡せる。
|
|
195
|
+
`planet.rotate(20)` のように直接メソッドを呼びたいときだけ、クラスに `include Asobi::Art` を足す
|
|
196
|
+
(`Enumerable` が `each` だけを求めるのと同じ)。
|
|
197
|
+
|
|
198
|
+
`Asobi.art(object, as: nil)` が変換の入口。変換できないときは、`to_art` を書けばよいことを伝えるエラーにする。
|
|
199
|
+
|
|
200
|
+
## 8. 動き(`Asobi::Motion`)
|
|
201
|
+
|
|
202
|
+
動きは「時刻(秒)→ 絵」の関数。フレーム番号や内部状態は持たない。
|
|
203
|
+
だから途中で差し替えても続きから再生でき、同じ時刻は必ず同じ絵になる。
|
|
204
|
+
|
|
205
|
+
| 言葉 | 意味と既定値 |
|
|
206
|
+
|---|---|
|
|
207
|
+
| `spin(every: 4, clockwise: true)` | 回り続ける |
|
|
208
|
+
| `pulse(every: 1, to: 1.2)` | 膨らんで戻る |
|
|
209
|
+
| `sway(every: 2, by: 10)` | 左右に揺れる(度) |
|
|
210
|
+
| `orbit(radius: nil, every: 4)` | 円周を回る。半径は省略時、絵の大きさの2倍 |
|
|
211
|
+
| `fade(every: 2, to: 0.2)` | 薄くなって戻る |
|
|
212
|
+
| `bounce(height: 20, every: 1)` | 弾む |
|
|
213
|
+
| `drift(right: 0, left: 0, up: 0, down: 0, every: 4)` | 行って戻る。全部省略なら右に絵の幅ぶん |
|
|
214
|
+
| `shift_color(from: nil, to: :crimson, every: 4)` | 色が移り変わって戻る。`from` 省略時は黒 |
|
|
215
|
+
| `one_by_one` | 並んだ絵の動きを、1つずつ時間差にする(波になる)。動きの言葉の直後に書く |
|
|
216
|
+
| `trail(count: 5, gap: nil)` | 残像。`gap` 秒ずつ前の時刻の絵を、だんだん薄くして下に重ねる。`gap` を省くと見た目のよい短い間隔。止まった絵に付けても何も変わらない |
|
|
217
|
+
| `animate(4) { \|picture, t\| ... }` | 自作。`t` は 0.0 から 1.0 未満を繰り返す |
|
|
218
|
+
|
|
219
|
+
- 動きにも、絵と同じ言葉(第5・6節)がすべて使える。その場合はどの時刻の絵にも同じことをする。
|
|
220
|
+
例:`flower.spin(every: 8).pulse(every: 1).colored(:crimson)`
|
|
221
|
+
- 絵と動きを合わせると動きになる(`ring.on(dot.pulse)`)。
|
|
222
|
+
- `at(seconds)` でその時刻の絵、`frames(fps: 30)` で1周ぶんの絵の遅延列(Enumerator::Lazy)。
|
|
223
|
+
- `every` は「元に戻るまでの秒数」。合成したときは最小公倍数(60秒を超えるなら長いほう)。
|
|
224
|
+
- `save("flower.html")` で、単体で再生できるページを書き出す。
|
|
225
|
+
|
|
226
|
+
マウス・音・拍などの外からの入力は、最初の版では扱わない。
|
|
227
|
+
|
|
228
|
+
## 9. 画面に出す
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
show flower # 自動で画面にぴったり収める
|
|
232
|
+
show flower, on: :black # 背景色
|
|
233
|
+
show flower, paper: [800, 800] # 800×800 の紙の中央に置く(はみ出たら切れる)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
- `show` を複数回呼んだら、最後のものが出る。
|
|
237
|
+
- **`ruby flower.rb` で実行したとき**:スクリプトの終わりに(`at_exit`)ライブ表示を始める。
|
|
238
|
+
ブラウザを開き、そのファイルを見張り、保存のたびに評価し直して差し替える。Ctrl-C で終了。
|
|
239
|
+
- **irb で `show` したとき**:裏でライブ表示を始め、`show` のたびに差し替える。
|
|
240
|
+
- 書き間違いがあるときは、最後に出せた絵を残したまま、エラーを画面の下に出す。
|
|
241
|
+
- ポートは 4567。使用中なら次の番号を試す。
|
|
242
|
+
- 環境変数 `ASOBI_LIVE=0` のときはライブ表示を始めない(テストや CI 用)。
|
|
243
|
+
|
|
244
|
+
### ブラウザの画面
|
|
245
|
+
|
|
246
|
+
- ふだんは絵だけ。
|
|
247
|
+
- マウスを動かしたときだけ、端に小さく操作(録画、コード表示)が出て、数秒で消える。
|
|
248
|
+
- `c` キーで、いまのコードを絵に半透明で重ねる。`r` キーで録画の開始・停止。
|
|
249
|
+
- 録画はブラウザの機能だけで行い、動画ファイルをダウンロードさせる。
|
|
250
|
+
|
|
251
|
+
### 絵をブラウザに渡す形(Reel)
|
|
252
|
+
|
|
253
|
+
Ruby 側と再生画面の間の取り決め。ライブ表示、`save("x.html")`、Web の遊び場が同じ再生プログラムを使う。
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"frames": ["<g>...</g>", "..."],
|
|
258
|
+
"fps": 30,
|
|
259
|
+
"view": [-76.0, -76.0, 152.0, 152.0],
|
|
260
|
+
"background": "white",
|
|
261
|
+
"code": "require \"asobi\"\n...",
|
|
262
|
+
"error": null
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
- `frames`:SVG の中身(`<svg>` タグは含まない)。止まった絵は1枚で `fps` は 1。
|
|
267
|
+
- `view`:viewBox `[x, y, 幅, 高さ]`。動きのときは全フレームを含む範囲。`paper:` 指定時は紙の範囲。
|
|
268
|
+
- `error`:文字列なら、`frames` などは省かれていてよい。画面は前の絵を残してエラーを出す。
|
|
269
|
+
- フレーム数の上限は 900。超えるときは fps を下げる。
|
|
270
|
+
- 再生は「ページを開いてからの経過秒 × fps」を frames の数で割った余り。差し替えても時計は進み続ける。
|
|
271
|
+
|
|
272
|
+
## 10. コマンド
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
asobi play.rb がなければ見本を作り、ライブ表示する
|
|
276
|
+
asobi FILE.rb そのスケッチをライブ表示する
|
|
277
|
+
asobi version
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## 11. サイト(`site/`):説明書と遊び場
|
|
281
|
+
|
|
282
|
+
説明書と遊び場を1つの静的サイトにまとめ、互いにつなげる(p5js.org がリファレンス・見本・エディタをつないでいるのと同じ考え方)。
|
|
283
|
+
インストールなしで読めて、その場で試せる。ruby.wasm でコアをブラウザ内で動かす。
|
|
284
|
+
|
|
285
|
+
### ページ
|
|
286
|
+
|
|
287
|
+
| ページ | 中身 |
|
|
288
|
+
|---|---|
|
|
289
|
+
| トップ | 哲学を2行で。動いている見本。「遊んでみる」ボタン |
|
|
290
|
+
| はじめかた | インストールから最初の絵まで。形 → 増やす → 並べる → 色 → 動かす の順に読める手引き |
|
|
291
|
+
| リファレンス | すべての言葉の一覧。言葉ごとに、短い説明・引数と既定値・コード例・その結果の絵 |
|
|
292
|
+
| 見本集 | 完成した作品のコードと絵 |
|
|
293
|
+
| 遊び場 | 左にコード、右に絵。書き換えると絵が変わる |
|
|
294
|
+
|
|
295
|
+
### つなぎ方
|
|
296
|
+
|
|
297
|
+
- **どのコード例も、その場で動く。** 説明書の中のコード例はすべて、隣に実際の絵(動きなら動いている絵)が出る。
|
|
298
|
+
- **どのコード例からも遊び場へ行ける。** 各例に「遊び場で開く」ボタンがあり、そのコードが入った状態で遊び場が開く(コードは URL の `#` 以降に入れる。サーバーには送らない)。
|
|
299
|
+
- **遊び場から説明書へ戻れる。** 遊び場に言葉の一覧を置き、選ぶとその言葉のリファレンスが開く。
|
|
300
|
+
- **遊び場のコードは URL で共有できる。**
|
|
301
|
+
|
|
302
|
+
### 決まり
|
|
303
|
+
|
|
304
|
+
- 英語と日本語の両方(`/` と `/ja/`)。
|
|
305
|
+
- 外部サービスに頼らない静的ファイルだけ。`rake site` で `site/` 以下から `_site/` に書き出す。
|
|
306
|
+
作るための道具は Ruby 標準ライブラリ(ERB、YAML など)だけ。
|
|
307
|
+
- 言葉の説明とコード例は1か所のデータ(YAML)に持ち、リファレンスのページと遊び場の言葉一覧の両方をそこから作る。
|
|
308
|
+
- **コード例はビルド時に実際に実行する。** 動かない例があればビルドを失敗させる(説明書とコードの食い違いを防ぐ)。
|
|
309
|
+
そのとき最初の絵を SVG としてページに埋め込み、ruby.wasm の読み込みを待たずに絵が見えるようにする。
|
|
310
|
+
- 再生プログラムは第9節と共通(`lib/asobi/web/player.js`)。
|
|
311
|
+
- ソケットやファイル監視など、ブラウザで動かないものはコアに混ぜない。
|
|
312
|
+
|
|
313
|
+
## 12. エラーメッセージ
|
|
314
|
+
|
|
315
|
+
`Asobi::Messages` に英語と日本語を並べて持つ。`LC_ALL` → `LC_MESSAGES` → `LANG` の順に見て、`ja` で始まれば日本語。
|
|
316
|
+
`Asobi.language = :ja` で切り替えられる。どのメッセージにも直し方の例を入れる。
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
in_grid の columns には 1 以上の整数を渡してください。例:in_grid(columns: 3)
|
|
320
|
+
in_grid needs a whole number of columns, like in_grid(columns: 3)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## 13. 作り
|
|
324
|
+
|
|
325
|
+
- Ruby 3.2 以上。実行時の依存は標準ライブラリだけ。テストは minitest(`rake test`)。
|
|
326
|
+
- 絵の実体は不変の値(`Data`)。`Asobi::Art` は `to_art` だけを頼りにするミックスイン。
|
|
327
|
+
- ファイル構成:
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
lib/asobi.rb 全部入り(pure + core_ext + top_level + sketch)
|
|
331
|
+
lib/asobi/pure.rb Ruby 本体に手を入れないコアだけ
|
|
332
|
+
lib/asobi/version.rb
|
|
333
|
+
lib/asobi/geometry.rb アフィン変換、外接箱
|
|
334
|
+
lib/asobi/art.rb Asobi::Art、Asobi.art
|
|
335
|
+
lib/asobi/nodes.rb 形の実体(Circle、Rect、Path、Text、Styled、Transformed ...)
|
|
336
|
+
lib/asobi/many.rb Asobi::Many と並べ方
|
|
337
|
+
lib/asobi/shapes.rb 形の言葉(第4節)
|
|
338
|
+
lib/asobi/color.rb 色名の表、補間、hsl
|
|
339
|
+
lib/asobi/svg.rb SVG への書き出し
|
|
340
|
+
lib/asobi/messages.rb エラーメッセージ(英語・日本語)
|
|
341
|
+
lib/asobi/random.rb その回の種と呼び出しカウンタ
|
|
342
|
+
lib/asobi/motion.rb Asobi::Motion と動きの言葉
|
|
343
|
+
lib/asobi/reel.rb Reel(第9節)
|
|
344
|
+
lib/asobi/core_ext.rb to_art と turn を Ruby 本体に付ける
|
|
345
|
+
lib/asobi/top_level.rb circle などと show をどこでも使えるようにする
|
|
346
|
+
lib/asobi/sketch.rb show、スケッチの評価
|
|
347
|
+
lib/asobi/live.rb ライブ表示のサーバー(ソケットを使うのはここだけ)
|
|
348
|
+
lib/asobi/web/player.js 再生プログラム(ライブ・書き出し・遊び場で共通)
|
|
349
|
+
lib/asobi/web/live.html ライブ表示のページ
|
|
350
|
+
exe/asobi
|
|
351
|
+
site/ 説明書と遊び場の元(第11節)。rake site で _site/ に書き出す
|
|
352
|
+
test/
|
|
353
|
+
examples/
|
|
354
|
+
README.md / README.ja.md
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## 14. 実装で決まった細部
|
|
358
|
+
|
|
359
|
+
設計の時点で決めていなかったが、実装で決めたこと。上の節と食い違う場合はこちらが正。
|
|
360
|
+
|
|
361
|
+
- **省略時の値**:`repeat` は2個、`rotate` は45度、`scale` は2倍、`opacity` は0.5、`colored` は `:crimson`、`text` は "asobi"。
|
|
362
|
+
- **名前なしの短縮形**:動きの言葉も最初の値は名前なしで書ける(`spin(8)`、`shift_color(:navy, :gold)`)。
|
|
363
|
+
- **`orbit` の半径**:省略時は絵の長いほうの辺の長さ。
|
|
364
|
+
- **並べ方の言葉は1つの絵にも使える**:1つだけの集まりとして扱う(`circle.in_ring`)。
|
|
365
|
+
- **`one_by_one`**:並んだ絵の1つ1つが、自分の中心のまわりで順番に動く(輪の形は崩れない)。動きの言葉の直後に書く。
|
|
366
|
+
`one_by_one` を付けないときは、まとまり全体が原点のまわりで動く。
|
|
367
|
+
- **変える言葉は原点のまわりで働く**:`mirror` `flip` `rotate` `scale` は絵自身の中心ではなく原点が基準。
|
|
368
|
+
- **`colored` と線**:線だけの絵(`line`、`arc` など)に `colored` すると線の色が変わる。
|
|
369
|
+
- **スケッチの評価**:`Asobi::Sketch.run(source, name:)` が文字列から、`evaluate(path)` がファイルから Reel を返す。
|
|
370
|
+
スケッチのエラーでは例外を投げず、エラーの Reel を返す。
|
|
371
|
+
- **Reel の fps**:1周を等間隔に切るので、fps は小数になることがある(`fps = コマ数 / every`)。
|
|
372
|
+
- **サイト**:ページは `guide.html`、`ja/guide.html` のような平らなファイル。動く例の Reel は1つ 1.5MB まで。
|
|
373
|
+
超えるとコマを間引いて警告する。遊び場は ruby.wasm(`@ruby/3.4-wasm-wasi`、jsDelivr から読み込む)で動く。
|
|
374
|
+
- **効果の細部**:
|
|
375
|
+
- `colored` は `from:` `to:` `angle:` `around:` のどれかがあればグラデーションになる。省いた色は crimson → navy。
|
|
376
|
+
向きは 0 が上から下、90 が右から左。絵を回すとグラデーションも一緒に回る。
|
|
377
|
+
- 並んだ絵(Many)へのグラデーションは全体に1回流れ、中の絵が個別に持っていた色は消える。
|
|
378
|
+
- 同じ効果をもう一度書くと置き換わる。効果は書いた順に外側へ重なり、`blended` だけは常に一番外側になる。
|
|
379
|
+
- `clipped_by` を形なしで書くと、絵の中央の丸い窓で切り抜く。
|
|
380
|
+
- `trail` の間隔は省略時 0.05 秒。重ねる絵は 0.5 から 0.1 へ薄くなる。残像の枚数ぶん、1コマのデータが増える。
|
|
381
|
+
- ざらつきは各コマの末尾に同じ小さな定義を足して実現する(再生プログラムは変更なし)。
|
|
382
|
+
画面の形が絵と違うときの左右・上下の余白にもかかるよう、絵の範囲の3倍に敷く。
|
|
383
|
+
- **まだない安全装置**:ライブ表示には、終わらないスケッチ(無限ループ)を打ち切る仕組みがない。遊び場は15秒で打ち切る。
|
|
384
|
+
|
|
385
|
+
## 15. 最初の版に入れないもの
|
|
386
|
+
|
|
387
|
+
マウス・音・拍への反応、画像ファイルの読み込み、別の絵への変身、PNG 書き出し、
|
|
388
|
+
実行そのものを絵にする機能(別の哲学なので入れない)。
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hayato1031
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.ja.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# asobi
|
|
2
|
+
|
|
3
|
+
[English](README.md)
|
|
4
|
+
|
|
5
|
+
asobi(遊び)は、Ruby で図形を組み合わせて、SVG の静止画やループアニメーションを作るライブラリです。たとえば花びらを8枚並べると、ひとつの花ができます。花も Ruby のオブジェクトなので、`spin` を呼ぶと花ごと回ります。
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
require "asobi"
|
|
9
|
+
|
|
10
|
+
flower = petal.repeat(8).in_fan.colored(:crimson, :navy)
|
|
11
|
+
show flower.spin(every: 8)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
<img src="docs/first-sketch.svg" width="240" alt="深紅と紺の花びらが交互に8枚並んだ花。">
|
|
15
|
+
|
|
16
|
+
## 最初のスケッチを動かす
|
|
17
|
+
|
|
18
|
+
用意するのは Ruby 3.2 以上とブラウザです。リポジトリのルートで次のコマンドを実行します。ライブラリの実行に追加の gem は要りません。
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
ruby exe/asobi
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
初回は、上の花を描く `play.rb` が作られ、ブラウザで花が回り始めます。すでに同名のファイルがある場合は、そのスケッチが開きます。
|
|
25
|
+
|
|
26
|
+
`repeat(8)` を `repeat(12)` に変えて保存すると、花びらが12枚に増えます。`spin(every: 8)` の `8` を `2` に変えると、今度は2秒で1回転します。ファイルを保存するたびに表示が更新されます。終了するには、コマンドを実行したターミナルで Ctrl+C を押します。
|
|
27
|
+
|
|
28
|
+
ほかの作品を開くには、`ruby exe/asobi examples/flower.rb` のようにファイルを指定します。ブラウザを自分で開く場合は `--no-open` を付けて、ターミナルに表示された URL にアクセスしてください。`--port 5000` を付けると、5000 番から空いているポートを探します(既定は 4567 番)。
|
|
29
|
+
|
|
30
|
+
別のディレクトリでも `asobi` コマンドを使いたいときは、リポジトリのルートで gem を作ってインストールします。その後は、作品を置きたいディレクトリで `asobi` を実行できます。既存のスケッチは `asobi sketch.rb` や `ruby sketch.rb` で開けます。
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
gem build asobi.gemspec --output asobi.gem
|
|
34
|
+
gem install --local ./asobi.gem
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## スケッチの書き方
|
|
38
|
+
|
|
39
|
+
この節の例を試すときは、`play.rb` の先頭にある `require "asobi"` を残し、その下を例のコードに置き換えてください。
|
|
40
|
+
|
|
41
|
+
### 図形を重ねる、並べる
|
|
42
|
+
|
|
43
|
+
`petal(40, 16)` は長さ40、幅16の花びらです。`in_fan` で根元を中心に放射状に並べ、`+` で金色の円を手前に重ねます。`scale(0.6)` は元の60%の大きさの花を返します。`beside` で元の花と並べると、大きな花と小さな花がひとつの絵になります。
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
petals = petal(40, 16).repeat(8).in_fan.colored(:crimson, :navy)
|
|
47
|
+
flower = petals + circle(5).colored(:gold)
|
|
48
|
+
show flower.beside(flower.scale(0.6), gap: 12)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
長さは絵の中での大きさを表します。表示するときは絵全体が画面に収まるように拡大・縮小されます。回転角は度で指定し、`rotate(90)` なら時計回りに4分の1回転します。
|
|
52
|
+
|
|
53
|
+
### 数列を絵にする
|
|
54
|
+
|
|
55
|
+
`to_art` は Ruby の値を絵に変換します。この例ではフィボナッチ数列の各項が星の大きさになり、小さな星から順に横一列に並びます。`as:` を省くと、各項を半径とする円になります。
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
fib = [1, 1, 2, 3, 5, 8, 13, 21]
|
|
59
|
+
show fib.to_art(as: star).colored(:gold, :orange), on: :black
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 自分のクラスで絵を作る
|
|
63
|
+
|
|
64
|
+
自作クラスに絵を返す `to_art` を定義すると、そのインスタンスを `show` に渡せます。さらに `Asobi::Art` をインクルードすると、インスタンスに対して直接 `spin` や `beside` を呼べます。
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
class Flower
|
|
68
|
+
include Asobi::Art
|
|
69
|
+
|
|
70
|
+
def initialize(count, color)
|
|
71
|
+
@count = count
|
|
72
|
+
@color = color
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def to_art
|
|
76
|
+
petal.repeat(@count).in_fan.colored(@color)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
show Flower.new(7, :coral).spin(every: 4)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 動きに時間差をつける
|
|
84
|
+
|
|
85
|
+
輪に並べた点を `pulse` で2倍まで膨らませ、元の大きさに戻します。直後に `one_by_one` を付けると、それぞれの点が少しずつ遅れて膨らみ、波が輪を一周します。
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
dots = circle(5).repeat(24).in_ring.colored(:gold, :orange)
|
|
89
|
+
show dots.pulse(every: 2, to: 2).one_by_one, on: :black
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
| やりたいこと | 主なメソッドとオプション |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| 形を作る | `circle`、`rect`、`star`、`text`、`path`、`wave`、`heart`、`petal` |
|
|
95
|
+
| 図形を配置する | `in_row` で横一列、`in_grid` で格子状、`in_ring` で円周上、`in_spiral` でらせん状に並べる |
|
|
96
|
+
| 色や質感を変える | `colored(from: :gold, to: :crimson)` でグラデーション、`glowing` で発光、`shadowed` で影、`clipped_by` で切り抜き |
|
|
97
|
+
| 動きを作る | `spin` で回転、`sway` で揺れ、`orbit` で公転、`trail` で残像を付ける。独自の動きは `animate` で定義する |
|
|
98
|
+
| 表示を整える | `show` の `on:` で背景色、`paper:` で用紙の寸法、`grain: true` で粒子感を指定する |
|
|
99
|
+
|
|
100
|
+
## 作品の保存と録画
|
|
101
|
+
|
|
102
|
+
静止画は SVG、アニメーションはブラウザでそのまま再生できる HTML に保存できます。次の例は、スケッチを実行したディレクトリに2つのファイルを書き出し、同じアニメーションをライブ表示します。
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
flower = petal.repeat(8).in_fan.colored(:crimson, :navy)
|
|
106
|
+
motion = flower.spin(every: 4)
|
|
107
|
+
|
|
108
|
+
flower.save("flower.svg")
|
|
109
|
+
motion.save("flower.html")
|
|
110
|
+
show motion
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
アニメーションの途中を静止画にするには、`motion.at(1).save("frame.svg")` のように秒数を指定します。
|
|
114
|
+
|
|
115
|
+
ライブ表示中にポインターを動かすと操作ボタンが現れます。`c` キーでソースコードの表示を切り替えられます。録画に対応しているブラウザでは、`r` キーで録画を開始し、もう一度押すと動画をダウンロードできます。形式はブラウザによって MP4 または WebM です。編集中にエラーが起きたときは、直前に描けた絵とエラーメッセージが表示されます。
|
|
116
|
+
|
|
117
|
+
## 既存の Ruby プログラムに組み込む
|
|
118
|
+
|
|
119
|
+
`require "asobi"` を使うと、`circle` などをトップレベルで呼べるようになり、数値や配列に `to_art` が加わります。既存のプログラムで Ruby の標準クラスを拡張せずに使うには、`asobi/pure` を読み込みます。次のコードをリポジトリのルートに `export.rb` として保存し、`ruby -Ilib export.rb` を実行すると、紺色の星を3つ並べた `stars.svg` ができます。
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
require "asobi/pure"
|
|
123
|
+
|
|
124
|
+
stars = Asobi.art([3, 1, 4], as: Asobi.star)
|
|
125
|
+
stars.colored(:navy).save("stars.svg")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 作例とドキュメント
|
|
129
|
+
|
|
130
|
+
リポジトリには、1ファイルで動くスケッチが入っています。
|
|
131
|
+
|
|
132
|
+
- 数列を形にする仕組みを試すなら [数列の星](examples/sequence.rb)
|
|
133
|
+
- 発光、色の合成、残像を重ねるなら [ネオンの花](examples/neon_flower.rb)
|
|
134
|
+
- 自作クラスで複数の軌道を描くなら [惑星](examples/planets.rb)
|
|
135
|
+
- ほかの作品を探すなら [作例一覧](examples/README.md)
|
|
136
|
+
|
|
137
|
+
日本語のドキュメントには、入門ガイド、引数や既定値を調べるリファレンス、作例を編集して動かせる「遊び場」があります。リポジトリのルートで次のコマンドを実行して、ドキュメントを生成します。
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
bundle install
|
|
141
|
+
bundle exec rake site
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
生成された `_site/ja/index.html` をブラウザで開くと、日本語版を読めます。「遊び場」でコードを編集して実行するには、CDN から ruby.wasm を読み込むためのインターネット接続が必要です。
|
|
145
|
+
|
|
146
|
+
テストは `bundle exec rake test` で実行できます。ライブラリ本体に加え、ドキュメントや作例のスケッチも検証します。ライブラリの設計については[設計書](DESIGN.md)を参照してください。
|
|
147
|
+
|
|
148
|
+
## 不具合報告・機能提案
|
|
149
|
+
|
|
150
|
+
日本語・英語どちらでも歓迎です。不具合の場合は、問題が起きる短いスケッチがあると再現しやすくなります。機能のアイデアは「こんな絵を描きたい」「こんな動きを作りたい」から気軽にどうぞ。[Issue を作成する](https://github.com/Hayato1031/asobi/issues/new/choose)
|
|
151
|
+
|
|
152
|
+
## ライセンス
|
|
153
|
+
|
|
154
|
+
[MIT ライセンス](LICENSE)
|