パーティクルお絵かきとは
「パーティクルお絵かき」は、粒子を1マスずつ盤面に置いて、あとは物理と相互作用にまかせて眺めるブラウザ用のお絵かきツールです。盤面は最小120×180マス・最大200×300マスの格子で、1マスに1粒だけが入ります。毎フレーム、重力の下流の行から順に1マスずつ「落ちる・滑る・広がる・昇る」を判定していく、いわゆるセルオートマトンの作りです。それに加えて、バネとねじれでつながった「点」の層が別にあり、イモムシはそちらで動いています。ゴールも点数もありません。砂を積み、水をため、木を組んで、そこに火をひとなでする。それだけの道具です。
属性は数値で決まる
このツールでは、粒子の振る舞いを個別に書き分けていません。すべての粒子は同じ1本の規則で動いていて、違いは属性が持つ数値だけです。だからこそ、あなたが作った属性も最初からある属性とまったく同じ扱いで動きます。
| 数値 | 効くところ |
|---|---|
| 状態 | 固体は動かない。粉は落ちて斜めに滑る。液体は落ちてから横へ広がる。気体は昇る |
| 密度 | 流体どうしがぶつかったとき、どちらが上になるか。重いほうが軽いほうを押しのけて入れ替わる |
| 動きやすさ | 1マス動こうとする確率。小さいほどゆっくり落ちる/昇る |
| 可燃性 | 燃えているものに触れたとき、燃え移る確率 |
| 発火力 | 自分がまわりを燃やす強さ。0より大きいと「燃えているもの」として扱われる |
| 消火力 | 触れた炎を消す確率。水は1.0なので必ず消す |
| 寿命 | 消えるまでの秒数。0にすると消えない |
| 変化先 | 寿命が尽きたとき、または消火したときに何になるか |
| 拡散 | 液体と気体が横へ広がろうとする確率 |
| 摩擦 | 速度の減り方。0で無摩擦(勢いがついたまま何マスも進む)、1で即停止(1回に1マス)。組み込みは氷と砂鉄を除いて1 |
| 粘り気 | 斜めに滑る・横へ広がるのをやめる確率。粉なら安息角が立ち、液体ならどろりと流れる |
| 磁力の効き | 磁石にどれだけ引かれる/反発するか。0なら磁石を無視する |
| 発光 | 明るさの底上げとちらつきの幅(見た目だけ。動きには効かない) |
| 這う速さ | 生き物が前へ進む力。状態が「生き物」のときだけ効く |
| 体長 | 生き物の節の数(2〜24)。状態が「生き物」のときだけ効く |
| 立ち方 | 0 なら這う(イモムシ)、1 なら立って歩く(人)。状態が「生き物」のときだけ効く |
| 持ち前の温度 | 置かれたときの温度(-1 冷たい 〜 +1 熱い)。温度を使うときだけ効く |
| 冷えたときの変化先 | 持ち前より十分に冷えたときに何になるか(水なら氷)。温度を使うときだけ効く |
密度の比較だけで浮き沈みが決まるので、水(1.0)より軽い油(0.8)は自然に水面へ浮かび、水より重い砂(2.6)は沈みます。あなたが密度0.5の液体を作れば、それは油の上にさらに層を作ります。
相互作用の規則
粒子どうしの関わりは3つだけです。1つめは延焼で、発火力のある粒子は上下左右の可燃性のある粒子を、可燃性×発火力の確率で自分と同じ炎に変えます。2つめは消火で、燃えている粒子が消火力のある粒子に触れていると、そのぶんの確率で変化先(火なら煙)に変わります。消火は延焼より先に判定するので、水に浸かった炎が向こう側の木に燃え移ることはありません。3つめは寿命で、寿命のある粒子は時間が来ると変化先に変わります。火は煙に、煙は無に、蒸気は水に戻ります。この3つだけで、燃え広がる、煙が上がる、水をかけると消える、天井の蒸気から雨が降る、といった動きがすべて出てきます。
重力・磁力・摩擦
粒子を動かす力は「その位置に働く加速度」に均してから使っています。重力は向き(8方向)と強さ(0〜2)を持つ1本のベクトルで、真下に固定されていません。強さを0にすると何も落ちなくなり、向きを右にすると砂は右へ「落ち」ます。気体はいつでも重力と逆向きに昇ります。磁石は置いた場所からの距離の逆二乗で効きますが、分母には2マスぶんの下限を切ってあります。下限を切らないと、磁石に重なった粒の力が無限大になって位置が壊れます。強さは「10マス離れたところで重力の何倍か」で言い表しています。摩擦は速度に比例した減衰で、0なら無摩擦、1ならその場で止まります。組み込みの属性はほとんどが1なので、摩擦を足す前とまったく同じ動きのままです。
バネとねじれ
格子は1マス単位でしか動けないので、「自然長からの伸びに比例した力」は表現できません。そこで浮動小数の位置を持つ「点」の層を別に持っていて、バネとねじれはそちらに乗っています。バネはフックの法則そのもので、自然長で力0、伸びれば引き戻し、縮めば押し返します。減衰は飾りではなく必須の項目です。減衰が0だと振動が減らないだけでなく、時間刻みの誤差が溜まって振幅がじわじわ増え、最後は画面外へ飛びます。ねじれは3点のなす角を自然角へ戻す力で、これがあるとバネだけでは作れない「形を保つ構造」ができます。角度は必ず-π〜πに畳んでいます。畳まないと、+πをわずかに超えた瞬間に差が-2π側へ飛んで、戻す向きの力が反転して暴れます。発散させないための仕掛けは2つ入れてあり、1つは時間刻みを常に1/60秒に固定すること(端末が重くて間隔が空いても、バネが見る刻みは変わらない)、もう1つは力と速さに上限を切ることです。前者は「刻みが伸びる」側の、後者は「バネ定数が大きい」側の対策で、どちらか片方では足りません。
このバネとねじれは、ばねとねじれの道具で自分の手でも張れます。線の端は必ず「点」に結びます。格子の粒には印が無く、落ちれば別のマスへ入れ替わってしまうので、粒に結ぶと結んだ相手が毎回変わってしまうからです。人が置ける点は留め具(動かない点)とおもり(自由な点)の2つだけで、中身はどちらも同じ点、違いは「留めるかどうか」の1つだけです。張ったバネは伸び具合を自然長で割った値で色と太さを決めていて、緩んでいるうちは青、伸びきると赤くなります(青=良い・赤=危険は、このサイトのゲーム共通の決めごとです)。消しゴムは粒と同じ円で点と線も消します。このとき消えた点につながっていたバネとねじれも必ず一緒に消し、残った線が指す点の番号は付け直しています。番号を付け直さないと、消したあとの線が別の点を引っぱり始めます。
イモムシ
イモムシはこの点の層の上に立っています。節を鎖のように並べ、隣どうしをバネでつないで体長を保ち、3つ並びにねじれを掛けて急に折れ曲がらないようにしています。自分から動くのは頭だけで、後ろの節はバネに引かれて前の節を追いかけます。これだけで「体節がつながって進む」ように見えます。進む向きに直交する成分を波で足しているので、体がうねりながら這います。固体のマスには入れないので、壁に当たると向きを変えます。
作った属性の保存と共有
作った属性はブラウザのlocalStorageに保存され、次に開いたときにパレットへ復元されます。保存しているのは名前・色・状態と各数値だけで、盤面の絵は保存されません。ここまではすべてお使いのブラウザの中だけで完結し、外部に送信するものはありません。外へ出るのは、下に書く共有リンクと素材の受け渡しを自分で押したときだけです。
ほかの人に渡したいときは共有リンクを作ります。作った属性・磁石・重力・盤面の絵を1本のURLに畳むだけで、サーバーには何も置きません。盤面の絵は連長圧縮して載せますが、それでもURLが長くなりすぎるときは、盤面 → 磁石 の順に落として属性の定義だけを残します(何を落としたかは画面に出ます)。リンクを開いた側では、中身の一覧を見せて取り込むを押されたときだけ反映します。他人が作った定義をこちらの保存領域へ勝手に書き込まないためです。
素材だけをIDで渡す
盤面はいらない、作った素材そのものだけを渡したいという場面のために、もう1本の道があります。属性を作るの下の素材を渡す・受け取るで出すを押すと、素材の定義が置き場に預けられ、ID001のような短い番号が返ります。相手に伝えるのはこの番号だけです。長いURLを貼り合う必要がなく、口頭でも伝えられます。受け取った側は番号を入れて取り込むを押すだけで、自分のパレットに並びます。1つの番号には最大8件までまとめられるので、組になっている素材(寿命が尽きると別の自作素材に変わるもの、など)もひとまとめに渡せます。素材どうしの「変化先」の指定は、受け取った側で新しく振り直した番号へ自動的に結び直されます。
取り込みで守っていることが2つあります。1つめは必ずパレットの末尾に足すことです。盤面のマスは属性の「添字」を1バイトで持っているので、途中に割り込ませて並びが変わると、前に保存した盤面や前に配った共有リンクが別の属性で開いてしまいます(砂が水になる)。末尾に足すかぎり、既存の添字は1つも動きません。2つめは既にあるものを上書きしないことです。同じ名前の素材が既にあるときは、番号を付けた別名にして足します。相手の「溶岩」とこちらの「溶岩」が同じものとは限らず、どちらを残すかは受け取った側にしか決められないからです。逆に、名前も中身も完全に同じものが既にあるときは足しません(同じ番号を二度取り込んでも増えません)。
置き場に置くのは、素材の名前と数値を畳んだ短い文字列だけです。自由に書ける説明文の欄は作っていません。1つの番号に入る素材の数と1件あたりの大きさ、そして1つの端末から出せる件数にも上限があります。番号は連番なので、総当たりで誰でも中身を見られます。見られて困るものを置ける作りにしないことが、この設計の前提です。出した素材は画面の一覧からいつでも取り消せます。取り消しても番号そのものは空けません。空けてしまうと、同じ番号に別の中身が入り、渡した相手が別のものを取り込むことになるからです。
よくある質問
- 自分で属性を作るとき、どの数値が何に効きますか?
- 状態が動きの基本を決めます。固体はまったく動かず、粉は落ちて斜めに滑って積もり、液体は落ちてから左右へ広がり、気体は上へ昇ります。密度は「どちらが上か」を決める数値で、重いほうが軽い流体を押しのけて下へ入れ替わります。水は1.0、砂は2.6、油は0.8なので、油は水に浮き、砂は水に沈みます。動きやすさは1目盛りぶん動こうとする確率で、小さいほどゆっくり動きます。可燃性は火に触れたときに燃え移る確率、発火力は自分がまわりを燃やす強さ、消火力は触れた炎を消す確率です。寿命は消えるまでの秒数で、0にすると消えません。変化先は寿命が尽きたときと消火したときに何になるかで、たとえば火は煙に、蒸気は水に変わります。拡散は液体と気体が横へ広がろうとする確率です。ここまでに加えて、摩擦は速度の減り方で0なら無摩擦・1なら即停止、粘り気は斜めや横へ動くのをやめる確率、磁力の効きは磁石にどれだけ反応するか、発光は見た目の明るさです。状態を「生き物」にしたときだけ、這う速さと体長(節の数)が効きます。
- 作った属性はどこに保存されますか?
- お使いのブラウザのlocalStorageに保存されます。次に同じ端末の同じブラウザで開いたとき、作った属性はパレットに並んだ状態で復元されます。自動で外へ送るものは何もないので、ほかの端末やほかのブラウザには引き継がれません(別の端末へ持っていきたいときは、素材を渡す・受け取るで番号を作って、その番号を向こうで入れてください)。ブラウザの履歴やサイトデータを消すと一緒に消えます。属性を削除すると、その属性で描いた粒子も盤面から消えます。ただし削除は2回押さないと実行されず、消した直後だけ「削除を取り消す」が出て、属性の定義と盤面の粒の両方が元どおりになります(戻せるのは直前の1回ぶんだけです)。
- 火が広がりません。どうすれば燃えますか?
- 燃え移るのは可燃性が0より大きい属性だけです。標準の属性では木と油が燃え、砂・石・水は燃えません。木の可燃性は低めにしてあるので、1粒に火をつけただけでは消えてしまうことがあります。木をある程度の厚みで描いて、その上に火をひとなでしてみてください。火は気体なので上へ昇ります。燃やしたいものは火より上ではなく、火のまわりか下に置くほうが燃え広がります。水に触れている炎はすぐ消えるので、消したいときは水を1本引くのがいちばん確実です。
- 温度と気圧を入れると何が変わりますか?重くなりませんか?
- どちらも「世界の設定」で個別に入り切りでき、既定では切ってあります。温度を入れると、盤面の上に熱の場ができて熱が伝わります。火のそばの木は触れていなくても2マス先まで燃え出し、氷は溶けて水になり、水は蒸発して蒸気になります。逆に氷のまわりの水は端からだんだん凍っていきます。しきい値は「その粒の持ち前の温度からどれだけ離れたか」で見ています。絶対の温度で見ると、氷(持ち前 -0.9)が溶ける線と水(持ち前 0)が蒸発する線を1本の数値では両立できないためです。凍る・溶けるときには潜熱ぶんの出し入れも入れてあり、これが無いと凍り始めた水面がその場で端から端まで一気に凍ります。気圧を入れると、気体が詰まり具合で押し合うようになります。石で囲った部屋に気体を詰めて穴を開けると噴き出し、抜けて薄くなったところへは吸い込まれます。液体は壁として扱っていないので、水中の泡はこれまでどおり昇ります。重さは実測しています。盤面の9割を埋めた最悪ケースで、場を1枚作る費用は1回ぶんの計算の6.5%(温度)と5.8%(気圧)、いちばん広い200×300の盤面では0.54ミリ秒と0.48ミリ秒にあたります。毎回どちらも作ると予算8.3ミリ秒に対して余裕が0.7ミリ秒しか残らないので、2回に1回だけ、しかも温度と気圧を別の回に振っています。落ち着き先は回す回数を減らしても変わらないので、変わるのは熱が伝わる速さだけです。設定の画面には、いまの盤面での見積もりと、置ける人数・イモムシの数を出しています。
- 人は何ができますか?何人まで置けますか?
- 「人」を選んで盤面を押すと、そこに1人立ちます。中身はイモムシと同じ点の層の生き物で、違いは「立ち方」という数値ひとつです。這うものは頭を前へ押しますが、人は足を前へ押し、毎回すこしずつ背骨を重力の逆向きへ立て直しています。倒立振子は放っておけば必ず倒れるので、立たせるには立て直す仕掛けが要ります(力で立て直そうとすると重力に桁で負けて、置いた1秒後には地面を這っていました)。1マスの段差は乗り越え、2マス以上の段や壁に当たると向きを変えます。足場が無ければ落ち、水に頭まで浸かると4秒で溺れ、火に触れると1.5秒で燃え尽きてその場に火が残ります。同時に置ける人数は実測から決めています。人1体はイモムシ1匹の0.53倍の重さ(節が4つで、イモムシの8つの半分あまり)で、イモムシ1匹0.11ミリ秒に掛けて0.06ミリ秒。1回ぶんの予算8.3ミリ秒から盤面のぶんと温度・気圧のぶんを引いた残りを0.06で割ったものが上限で、標準の盤面なら上限の64人、いちばん広い盤面では28人(温度と気圧を両方入れると19人)です。いまの上限は「世界の設定」に出ています。
- スマートフォンでも動きますか?重いときはどうしますか?
- 操作はポインタイベントで統一しているので、指でもマウスでも同じように描けます。盤面の大きさは「世界の設定」から標準(120×180=21,600マス)・広い(160×240)・とても広い(200×300=60,000マス)の3段階で選べます。上限を200×300にしているのは実測からで、盤面をほぼ埋めた最悪ケースで1回ぶんの計算が8.3ミリ秒に収まるのがここまでだからです(240×360だと10.8ミリ秒かかり、混んだ盤面でこま落ちします)。1マスの表示ピクセル数は必ず整数にしているので、どの端末でもマスの幅が揃います(半端な比で拡大すると、マスの幅が2ピクセルと3ピクセルに割れて縞が出ます)。以前は「世界の全部を必ず画面に収める」計算だったので、世界を広げるほど1マスが5・4・3ピクセルと潰れ、しかも盤面の高さが画面をはみ出して縦にスクロールしないと下まで見えませんでした。いまは盤面を世界の一部を映す窓にしてあります。窓は画面の取れるだけを取り、倍率と見る場所は別に持ちます。1280×800の画面で実測すると、標準の盤面は1マス5→8ピクセル・画面に出ている絵が600×445→960×720ピクセル、いちばん広い盤面は1マス3→4ピクセル・600×445→800×720ピクセルになりました。引いたときの全体表示もそのまま残っていて、「全体」を押せば世界の全部が一度に出ます(いちばん広い盤面で1マス2ピクセル・400×600)。寄るのは+ボタン・ホイール・2本指のピンチ・+キー、見る場所を動かすのは「移動」の道具・2本指のドラッグ・矢印キー、全体に戻すのは「全体」ボタンか0キーです。つまんだ場所は動かないので、寄せたあとに探し直しになりません。寄っているときは窓に映っているマスしか塗りません。粒で埋めた200×300の盤面で1フレームの描画は、全体表示が0.59ミリ秒、1マス5ピクセルで0.27ミリ秒、いちばん寄った状態で0.037ミリ秒でした(以前はどの倍率でも0.60ミリ秒かかっていました)。狭い画面では1マスの大きさは以前と変わりません(375×812で5・4・3ピクセルのまま)。変わったのは、そこから最大12ピクセルまで寄れるようになったことです。よく使う操作は盤面の外の「操作」の箱に出してあります。画面が広いときは盤面の横に並ぶので、盤面の縦の取り分は1画素も減りません。横に並べられない狭い画面では盤面の下に積みます。積むと操作卓の高さぶん縦が減りますが、狭い画面の盤面は元から幅で頭打ちになっているので1マスの大きさは変わりません(375×812で実測)。縦を取り戻したいときは「畳む」でしまえます。動きが重いと感じたら、盤面を「標準」に戻すか、煙や蒸気のように長く残る粒子を減らすか、全消去で盤面を空にしてください。イモムシと磁石を大量に置いたときも重くなります。一時停止しているあいだも描けるので、じっくり配置してから再生すると重さを避けられます。