Boids 0.5
全体構成
Boidsを構築していくために、以下のような全体構成とした。
- HTML
- WordPressのテキストエディタで、入力やボタン、canvasなどの必要な要素を書き込む。
- 外部スクリプトファイル
- 各バージョンのBoidsを実行するための外部スクリプトファイルを用意する。バージョンごとにパッケージ化する。
HTML
個体数をセットするためのinput要素のタイプは”number”とした。こうすることにより、ボックスの右側に値をコントロールする矢印が出たり、最小値の指定などができる。
ボタンはWordPressでonclickを使うと問題が生じるので、HTMLでは単にボタンを表示させるだけとし、リスナについてはコード側で対応する。
canvas要素は書き方によってWordPressで勝手に変更されてしまうので注意。
input要素とcanvasについては、コード側から参照するためのidを付与している。
スクリプトについては、jQueryはWordPress側で読み込まれるとのこと。外部スクリプトファイルは、</body>タグの直前あたりを想定して、WordPressのテキストモードで最後尾にscript要素を書いた。<script type="..." src="..."></script>とテキストモードで書いても、ビジュアルモードを経由すると以下のように書き換えられてしまう。
- 勝手にCDATAのパターンが挿入され、間に改行が入ってしまう
- srcとtypeの指定順序が逆になってしまう
| 1 2 3 4 5 6 7 8 9 10 | <!-- Boids 0.5--> <input id="boids05_population" min="1" type="number" value="1" /> <input id="boids05_generate" type="button" value="Generate" /> <canvas id="boids05_canvas" style="background-color: #e0e0e0;" width="400" height="300"> </canvas> <!-- テキストモードで最後尾に以下を追加 --> <script src="../coffee/boids/boids_0_5.js" type="text/javascript">// <![CDATA[ // ]]></script> | 
クラス構成
クラスは以下の4つを準備
- Boidsの活動領域となるFieldクラス
- 個々の個体を表現するCreatureクラス
- 複数のCreatureが集まった群を表現するClusterクラス
- 各オブジェクトを生成し、ボタン操作に対応してアニメーションをコントロールするControlerクラス
パッケージ
異なるバージョンのBoidsを同じページで動かすため、バージョンごとのパッケージに上記4つのクラスを入れることとした。
初めのバージョンに対応したパッケージ名はboids05で、グローバルにアクセスするのはControlerオブジェクトだけとし、Boids05.Controlerを定義している。
そして最後に、このスクリプトファイルが読み込まれたときにボタンに対するリスナを登録するための処理を記述している。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # Boidsの準備として、個体を運動させる # Boids 0.5 # 指定した数の個体を発生させ、canvas内のランダムな位置に表示させる Boids05 = {} # パッケージBoids05の本体 do ->   # Boidsが活動する空間のクラス   # このバージョンでは、canvasオブジェクトの上下左右の座標を持つ長方形   class Field   # Boidsの個体を実現するクラス   # 位置座標と速度ベクトルの成分を保持する   # 自らが活動するFieldクラスのオブジェクトへの参照も保持する   class Creature   # Boidsの群を管理するクラスで、以下を保持する   # ・群を構成する複数の個体   # ・個体を描画するcanvasとそのcontextのオブジェクトを保持する   class Cluster   # Boidsアプリケーションの動作を統括するクラス   # Creatureや   class Controler   # Boids 0.5で用いるための名前空間を設定   Boids05.Controler = Controler # Boids 0.5に対応したDOMの操作に対応し、このパッケージを操作する # DOMがすべて読み込まれてから以下を実行するよう保証 jQuery ($) -> | 
各ブロックとクラスの説明
リスナ登録
jQueryの構文を用いている。WordPressでjQueryを用いる場合、”$”が別のエイリアスに定義されているらしいので、1行目のように書くとのこと。
1つ目のブロックではcanvas要素のDOMオブジェクトを取得し、controlerオブジェクトを生成して初期値をセットしている。
この段階では速度関係は必要ないが、次のステップの前にとりあえず実装したため、Controler.setVMax()メソッドを読んでいる。
2つ目のブロックでは、ボタンが押されたときの処理を記述しており、numberボックスから値を読み込み、それに基づいて個体生成の指令を出している。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | jQuery ($) ->   # Boids0.5のControlerを作成し、canvasオブジェクトを渡す   canvas = $("#boids05_canvas")[0]   controler = new Boids05.Controler(canvas)   controler.setVMax(50)   # Generateボタンが押されたとき、指定された個体数で群をつくる   $("#boids05_generate").click ->     pop = $("#boids05_population").val()     if pop < 1       pop = 1       $("#boids05_population").val(pop)     controler.generate(pop) | 
Controlerクラス
ブラウザ側からの指令と、スクリプト内の各クラスとの仲立ちを一手に引き受けるクラスで、この段階では以下の機能を提供する。
- constructor
- canvasオブジェクトを渡してControlerオブジェクトを生成する。
- constructor(canvas)
- canvasオブジェクトを渡してConstructorオブジェクトを生成する。
- setVMax(vMax)
- ランダムに生成する速さの最大値をConstructorオブジェクトにセットする。
- createCreature()
- 位置と速度(速さと方向)をランダムに与えて個体を生成する。
- generate(population)
- 指定した数の個体を生成し、Clusterオブジェクトに格納する。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |   class Controler     constructor: (canvas) ->       @vMax = 0       @field = new Field(canvas)       @cluster = new Cluster(canvas)       @population = 0 # number of creatures     # 個体の速度を発生させるときの最大値     setVMax: (@vMax) ->     # 一つの個体を発生させるメソッド     # 位置はcanvasに収まるよう、速度はvMax/2~vMaxの範囲でランダム     createCreature: ->       cr = new Creature(@field)       x = Math.floor(Math.random() * @field.xMax)       y = Math.floor(Math.random() * @field.yMax)       v = (Math.random() + 1) * @vMax / 2       a = Math.random() * Math.PI * 2       cr.setPosition(x, y)       cr.setVelocity(v * Math.cos(a), v * Math.sin(a))       return cr     # 指定した数の個体を発生させ、Clusterオブジェクトに登録する     generate: (@population) ->       @cluster.clearCreatures()       for i in [1..@population]         cr = @createCreature()         @cluster.addCreature(cr)       @cluster.draw() | 
Fieldクラス
将来の拡張も考慮して、一つのクラスとした。現時点では単なる矩形で、上下左右の座標値をプロパティに持つ。
| 1 2 3 4 5 6 |   class Field     constructor: (canvas) ->       @xMin = 0       @yMin = 0       @xMax = canvas.width       @yMax = canvas.height | 
Clusterクラス
Creatureオブジェクトを1~複数保持する「群」のクラス。提供する機能は以下の通り。
- constructor(canvas)
- 個体を描画するcanvasを渡してClusterオブジェクトを生成。
- clearCreatures()
- 群の個体を空にする。
- addCreature(creature)
- Creatureオブジェクトを渡し、群に追加する。
- draw()
- 群の全ての個体を描画する。実際には、保持している個体のdraw()メソッドを呼び出しているだけ。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |   class Cluster     constructor: (canvas) ->       @creatures = []       @canvas = canvas       @context = @canvas.getContext("2d") if @canvas.getContext       return     # 群の個体をすべてクリアする     clearCreatures: ->       @creatures = []     # 群に与えられた個体を加える     addCreature: (creature) ->       @creatures.push(creature)       return     # 群の善個体を描画する     draw: ->       @context.fillStyle = "#e0e0e0"       @context.fillRect(0, 0, @canvas.width, @canvas.height)       for creature in @creatures         creature.draw(@context)       return | 
Creatureクラス
個々のクラスを表現するクラス。このバージョンでは運動はさせないが、速度関係のプロパティや初期化は行っている。
- constructor(canvas)
- Fieldオブジェクトを指定してCreatureオブジェクトを生成。
- setPosition(x, y)
- 個体が存在する座標を指定。
- setVelocity(vx, vy)
- 速度の成分をセット。このバージョンでは必要ないが実装。
- draw(context)
- 描画コンテキストを指定して、個体を描画する。このバージョンでは単純な円を描いている。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |   class Creature     # 描画の基本となるサイズ     # private staticなクラス・プロパティ     _drawSize = 4     constructor: (field) ->       @x = 0       @y = 0       @vx = 0       @vy = 0       @field = field     # 個体の位置をセットするメソッド     setPosition: (@x, @y) ->     # 個体の速度をセットするメソッド     setVelocity: (@vx, @vy) ->     # 個体を描画するメソッド     # canvasのコンテキストを引数で受け取る     draw: (ctx) ->       ctx.fillStyle = "black"       ctx.beginPath()       ctx.arc(@x, @y, _drawSize, 0, Math.PI*2, true)       ctx.fill()       return | 
Boids 1.0
HTML
Boids 1.0用のボックスやボタンを用意し、外部スクリプトファイルを読み込んでいる。
このバージョンから個体の運動をさせるので、Start/Stopボタンを追加している。
| 1 2 3 4 5 6 7 8 9 10 11 | <input type="number" id="boids10_population" value="1" min="1" /><br /> <input type="button" id="boids10_generate" value="Generate" /> <input type="button" id="boids10_start_and_stop" value="Start/Stop" /> <canvas id="boids10_canvas" width="400" height="300" style="background-color: #e0e0e0"> <!-- テキストモードの最後尾 --> ... <script src="../coffee/boids/boids_1_0.js" type="text/javascript">// <![CDATA[ // ]]></script> | 
パッケージとクラスの変更
パッケージ構成
パッケージについては、パッケージ名やエイリアスを変更。
また、個体の運動を追加するため、以下のメソッドを追加。
- Creature.move(interval_sec)
- Cluster.move()
- Controler.setIntervalSec(interva._sec)
- Controler.startAndStop()
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | Boids10 = {} do ->   class Field     constructor: (canvas) ->   class Creature     constructor: (field) ->     setPosition: (@x, @y) ->     setVelocity: (@vx, @vy) ->     draw: (ctx) ->     move: (interval_sec) ->   class Cluster     constructor: (canvas) ->     clearCreatures: ->     draw: ->     move: (interval_sec) ->   class Controler     constructor: (canvas) ->     setVMax: (@vMax) ->     setIntervalSec: (@interval_sec) ->     createCreature: ->     generate: (@population) ->     startAndStop: () ->   Boids10.Controler = Controler jQuery ($) -> | 
Creature.move()
秒単位のフレームタイムを指定して呼び出される。
- 各個体の速度で等速度運動
- 壁に当たった場合は全反射
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |   class Field   ...     # Boids 1.0で追加     # interval_msはアニメーションのフレームタイム     # 秒単位で与えられることを想定     move: (interval_sec) ->       @x += @vx * interval_sec       @y += @vy * interval_sec       # 壁にぶつかった場合は全反射       if @x <= @field.xMin or @x >= @field.xMax then @vx = -@vx       if @y <= @field.yMin or @y >= @field.yMax then @vy = -@vy       return | 
Cluster.move()
秒単位のフレームタイムを指定し、群の個体の数の分だけCreature.move()メソッドを呼び出す。
| 1 2 3 4 5 6 7 8 |   class Cluster   ...     # Boids 1.0で追加     # フレームタイムを秒単位で受け取り、すべての個体を移動させる     move: (interval_sec) ->       for creature in @creatures         creature.move(interval_sec)       return | 
Controlerクラス
変更内容は以下の通り。
- プロパティ追加
- アニメーションをコントロールするプロパティとして以下を追加。
- 運動中かどうかを保持するisRunningフラグ
- 作動中のintervalタイマを保持するtimer
- 秒単位のフレームタイムを保持するinterval_sec
 
- 運動中かどうかを保持する
- setIntervalSec(interval_sec)
- アニメーションのフレームタイムをセット。
- startAndStop()
- Start/Stopボタンを押すごとに、作動状態と停止状態を切り替え。特にリスナにコールバック関数を無名関数で登録するときに、thisをバインドするためのファットアローを使っていることと、無名関数で引数を表示する記法に留意。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |   class Controler     constructor: (canvas) ->       ...       # Boids 1.0で追加/アニメーション用       @isRunning = false       @timer = undefined       @interval_sec = 1 # animation frame interval in seconds     ...     # Boids 1.0で追加     # フレームタイムのセット     setIntervalSec: (@interval_sec) ->     ...     # Boids 1.0で追加     # この関数を呼び出すたびに、アニメーションの開始と停止が切り替わる     # アニメーションにはsetInterval()に以下の引数を渡している     # ・アニメーション1フレームの操作     # ・ミリ秒単位の時間間隔     startAndStop: () ->       if @isRunning         clearInterval(@timer)         @isRunning = false       else         @timer = setInterval =>           @cluster.move(@interval_sec)           @cluster.draw()           return         , @interval_sec * 1000         @isRunning = true       return | 
Boids 1.1
このバージョンでは、個体を壁にぶつかってから全反射させるのではなく、壁が近づくとともに斥力を感じるように壁を避けようとする動作を導入する。
HTML
Boids 1.0用のボックスやボタンを用意し、外部スクリプトファイルを読み込んでいる。
| 1 2 3 4 5 6 7 8 9 10 11 12 | <input type="number" id="boids11_population" value="1" min="1" /><br /> <input type="button" id="boids11_generate" value="Generate" /> <input type="button" id="boids11_start_and_stop" value="Start/Stop" /> <canvas id="boids11_canvas" width="400" height="300" style="background-color: #e0e0e0"> </canvas> <!-- テキストモードの最後尾 --> ... <script src="../coffee/boids/boids_1_1.js" type="text/javascript">// <![CDATA[ // ]]></script> | 
パッケージとクラスの変更
パッケージ構成
クラス構成は特に変わらず、パッケージ名とエイリアスを本バージョンにあったものとする。以下のバージョンでも同じ。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | Boids11 = {} do ->   class Field   class Creature   class Cluster   class Controler   Boids11.Controler = Controler jQuery ($) -> | 
Creatureのクラスプロパティ
このバージョンから、速度の最大値をControlerからCreatureのクラスプロパティに変更(6行目)。
また、壁の接近を認識する距離(_detectionLength)と回避加速度計算時のパラメータ(_repulsionParam)を定義。
| 1 2 3 4 5 6 7 8 9 10 11 12 |   class Creature     # private staticなクラス・プロパティ     # 最大速度     # Boids1.0ではControlerクラスに置いていたが、     # Boids1.1からCreatureクラスのクラスプロパティとした     _vMax = 0     # 描画の基本となるサイズ     _drawSize = 4     # 壁の衝突回避を認識する距離     _detectionLength =  100     # 反発力パラメータ     _repulsionParam = 4 | 
Creature.move
認識距離以内に壁に近づき始めると、壁からの斥力を想定した加速度を計算し、速度を変更。
加速度は重力加速度をイメージし、距離の2乗に反比例させた。

そもそもピクセル単位の計算では最小でも距離の値が”1″となるため、重力モデルでは大きな加速度が出ない。ここでは_detectionLengthを長さの基準としたが、壁との距離に応じて自然に避けるような運動をさせるためにパラメータ(_repulsionParam)を導入しなければならなかった。
なお、速度ベクトルの値のキャップを判定する際に速度成分の符号を用いているが、Math.sign()はほとんどのブラウザで使えないため、「値/絶対値」で符号を得ている。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |     move: (interval_sec) ->       # Boids 1.1から追加       # 壁からの距離に応じた斥力を想定し、x/y方向の加速度を計算       if @x <= _detectionLength         ax =  (_detectionLength * _repulsionParam / @x) ** 2       else if @x >= @field.xMax - _detectionLength         ax = -(_detectionLength * _repulsionParam / (@field.xMax - @x)) ** 2       else         ax = 0       if @y <= _detectionLength         ay = (_detectionLength * _repulsionParam / @y) ** 2       else if @y >= @field.yMax - _detectionLength         ay = -(_detectionLength * _repulsionParam / (@field.yMax - @y)) ** 2       else         ay = 0       # Boids 1.1から追加       # 加速度を考慮した速度の変化       # 速度の絶対値が増え続けないようにキャップで抑える       # 速度成分の符号を得るのに、Math.signがサポートされていないブラウザが多いため、       # 値/絶対値で符号を得ている       @vx += ax * interval_sec       @vx = @vx / Math.abs(@vx) * Math.min(Math.abs(@vx), Creature._vMax)       @vy += ay * interval_sec       @vy = @vy / Math.abs(@vy) * Math.min(Math.abs(@vy), Creature._vMax)       # インターバルの間の移動量       @x += @vx * interval_sec       @y += @vy * interval_sec       # 壁にぶつかった場合は全反射       if @x <= @field.xMin or @x >= @field.xMax then @vx = -@vx       if @y <= @field.yMin or @y >= @field.yMax then @vy = -@vy       return | 
Controlerクラス
vMaxの変更のみ。
| 1 2 3 4 5 6 7 8 9 10 |   class Controler     constructor: (canvas) ->       # @vMax = 0 は削除       @field = new Field(canvas)       @cluster = new Cluster(canvas)       ...     # 実際にはCreatureクラスのクラスプロパティにセットしている     setVMax: (vMax) -> Creature._vMax = vMax     ... | 
Boids 1.2
このバージョンで、以下の点を変更している。
- 座標単位のプロパティ定義・計算を、独自クラスgeom2d.Vectorで書き換え
-  描画サイズなど各種パラメータをHTMLで設定できるようにする
- 各種パラメータをstaticなクラス変数とする
- HTMLでグローバルな変数としてパラメータ群を設定
- 実行時にControlerオブジェクトのセッターでパラメータ群を設定
 
- Creatureオブジェクトの形状を自由に設定可能にする
HTML
独自クラスパッケージファイルの読み込み
本体のスクリプトファイルに先立って、独自クラスのパッケージファイル(taustation_geom2d.js)を読み込ませている。
パラメータ群の設定
HTMLのscript要素でパラメータ用のグローバル変数を定義する。これらはその後に読み込まれたスクリプトで利用される。
script要素内の変数定義はJavascriptで書くため、行末にコロン(;)をつけている。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <input type="number" id="boids12_population" value="1" min="1" /><br /> <input type="button" id="boids12_generate" value="Generate" /> <input type="button" id="boids12_start_and_stop" value="Start/Stop" /> <canvas id="boids12_canvas" width="400" height="300" style="background-color: #e0e0e0"> </canvas> <!-- テキストモードの最後尾 --> <!-- Boids 1.2用のパラメータ --> <script type="text/javascript">// <![CDATA[ V_MAX = 100; CREATURE_SIZE = 8; WALL_DETECTION_LENGTH = 100; WALL_REPULSION_PARAM = 16; INTERVAL_SEC = 0.05; // ]]></script> <script src="../lib/taustation_geom2d.js" type="text/javascript">// <![CDATA[ // ]]></script>  ... <script src="../coffee/boids/boids_1_2.js" type="text/javascript">// <![CDATA[ // ]]></script> | 
script要素をWordPressのテキストモードで書くと、ビジュアルモードを経由したときに//<![CDATA[~改行~//]]>が挿入される。
また、Javascriptをscript要素に直接書くと、改行が除かれて一行になってしまう。
パッケージの準備とクラスの変更
Vectorクラスの利用
独自クラスgeom2d.Vectorを使って、位置・速度・加速度のコーディングを見やすくした。
各オブジェクトの生成と計算時にVectorオブジェクトを生成するnew演算子が介在するが、400個体程度の計算でもパフォーマンスの問題は見られなかった。
個体の形
これまではdraw()メソッドの中で直接円を描いていたが、今回はヘルパーメソッドdrawShape()を実装。
パラメータ設定
HTML内のスクリプト要素で定義されたグローバル変数を参照し、パラメータとしてクラス変数に格納。
この操作はControlerクラスに集約した。
変更に関係する箇所
Creatureクラスのクラス変数
@var: valの形式でクラス変数として定義。
| 1 2 3 4 5 6 7 8 9 |   class Creature     # 最大速度     @_vMax: 100     # 描画の基本となるサイズ     @_drawSize: 8     # 壁の衝突回避を認識する距離     @_wallDetectionLength:  100     # 反発力パラメータ     @_wallRepulsionParam: 4 | 
Creatureの基本メソッド
これまでx, y, vx, vyのように個別の座標値で扱っていたプロパティを、Vectorクラスで置き換える。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |     # 位置、速度、加速度をプロパティとして持つ     constructor: (field) ->       @pos = new Vector(0, 0)       @v = new Vector(0, 0)       @a = new Vector(0, 0)       @field = field     # 個体の位置をセットするメソッド     setPosition: (x, y) ->       @pos.x = x       @pos.y = y       return     # 個体の速度をセットするメソッド     setVelocity: (vx, vy) ->       @v.x = vx       @v.y = vy       return | 
Creature.draw()
単純な円ではなく、方向を持った細長い三角形を描くように変更。
下図のように、基準点(x, y)から速度ベクトルの方向に頂点を、速度ベクトルと直角な報告に底辺を描く。ここで で、これによって三角形の細長さが決まる。
で、これによって三角形の細長さが決まる。

ここで と置くと下図のようになる。
と置くと下図のようになる。

コードは以下の通り。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |     # 個体を描画するメソッド     # canvasのコンテキストを引数で受け取る     draw: (ctx) ->       v = @v.abs()       sx = Creature._drawSize * @v.x / v       sy = Creature._drawSize * @v.y / v       p = 0.25       ctx.fillStyle = "black"       ctx.beginPath()       ctx.moveTo(@pos.x + (1 - p) * sx, @pos.y + (1 - p) * sy)       ctx.lineTo(@pos.x + (-sx - sy) * p, @pos.y + (sx - sy) * p)       ctx.lineTo(@pos.x + (-sx + sy) * p, @pos.y + (-sx - sy) * p)       ctx.closePath()       ctx.fill()       return | 
Creature.move()
Vectorオブジェクトの導入に対応して書き直した。
斥力加速度計算のパラメータ(Creature._wallRepulsionParam)は()の外に出した。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |     move: (interval_sec) ->       # Boids 1.1から追加       # 壁からの距離に応じた斥力を想定し、x/y方向の加速度を計算       if @pos.x <= Creature._wallDetectionLength         @a.x =           Creature._wallRepulsionParam *           (Creature._wallDetectionLength / @pos.x) ** 2       else if @pos.x >= @field.xMax - Creature._wallDetectionLength         @a.x =           -Creature._wallRepulsionParam *           (Creature._wallDetectionLength / (@field.xMax - @pos.x)) ** 2       else         @a.x = 0       if @pos.y <= Creature._wallDetectionLength         @a.y =           Creature._wallRepulsionParam *           (Creature._wallDetectionLength / @pos.y) ** 2       else if @pos.y >= @field.yMax - Creature._wallDetectionLength         @a.y =           -Creature._wallRepulsionParam *           (Creature._wallDetectionLength / (@field.yMax - @pos.y)) ** 2       else         @a.y = 0       # Boids 1.1から追加       # 加速度を考慮した速度の変化       # 速度の絶対値が増え続けないようにキャップで抑える       @v.plusEq(@a.times interval_sec)       @v.x = Math.sign(@v.x) * Math.min(Math.abs(@v.x), Creature._vMax)       @v.y = Math.sign(@v.y) * Math.min(Math.abs(@v.y), Creature._vMax)       # インターバルの間の移動量       @pos.plusEq(@v.times interval_sec)       # 壁にぶつかった場合は全反射       if @pos.x <= @field.xMin or @pos.x >= @field.xMax then @v.x = -@v.x       if @pos.y <= @field.yMin or @pos.y >= @field.yMax then @v.y = -@v.y       return | 
Clusterクラス
変更箇所はない。
Controlerクラスのセッター
以下のメソッド群で整理。Creatureのクラス変数をセットしている。
| 1 2 3 4 |     setVMax: (vMax) -> Creature._vMax = vMax     setCreatureSize: (size) -> Creature._drawSize = size     setWallDetectionLength: (pix) -> Creature._wallDetectionLength =  pix     setWallRepulsionParam: (param) -> Creature._wallRepulsionParam = param | 
実行部分
Controlerオブジェクトのセッター群を呼び出している。
| 1 2 3 4 5 6 7 8 9 | jQuery ($) ->   canvas = $("#boids12_canvas")[0]   controler = new Boids12.Controler(canvas)   controler.setVMax(V_MAX)   controler.setCreatureSize(CREATURE_SIZE)   controler.setWallDetectionLength(WALL_DETECTION_LENGTH)   controler.setWallRepulsionParam(WALL_REPULSION_PARAM)   controler.setIntervalSec(INTERVAL_SEC) |