Spdeでお絵かきプログラミング再入門

SpdeはScala(的文法)でビジュアルプログラミングをするためのツール。
Processingという言語からインスピレーションを得ている。
Scalaの勉強がてら導入したので、yoppa.orgの授業資料を参照しながら簡単なコードを書いていく。

参照:
第3回:変数と繰り返し
第4回:「繰り返し」を繰り返す

インストールの仕方

忘れた。
ここからダウンロードしてごちゃごちゃ。
環境の準備は一番面倒で何やってるかよくわからなくて説明しづらい。

変数

Processingにおいて変数の定義は型を宣言する必要があった。

int foo = 10;
float bar = 12.3;

Spde(Scala)では型を宣言する必要がない。

var foo = 10
val bar = 12.3

これは型推論という機能によるものである。varは再代入可能な変数を、valは再代入不可能な変数を定義する。
また、一度に複数の値を初期化する場合は次のような書き方ができる。

var a,b,c = 0
println(a, b, c) // => (0, 0, 0)
var (x,y,z) = (1, 2, 3) //タプル記法
println(x, y, z) // => (1, 2, 3)

繰り返し

Spdeで指定回数の繰り返しを行うためには次のように記述する。

for( i <- 1 to 10 ){
  //なにかの処理
}

Scalaにおけるfor文はコレクションを処理するための構文のようである。
Scalaインタプリタを起動して1 to 10と入力してみる。

scala> 1 to 10
res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

よって上記for文はその内側でiに1から10まで代入しつつ繰り返し処理を行うもの、と素朴に理解できる。
という説明はまあ回りくどい。
for(初期化式; 継続条件式; 再初期化式)のような書き方より格段にシンプルになっていることはわかるけど…

for文についての詳細はHishidama's Scala for Memoを参照すると分かるかも。

同心円

上記の変数と繰り返し文についての知識から、参考サイトにおける同心円の描画コードを次のように書き換えることができる。
描画系命令はsize,background,noStroke,...などProcessingと同じものが利用できる。

var (x, y, diameter) = (200, 200, 400.0)

override def setup() = {
  size(400, 400)
  background(0)
  noStroke
  smooth
  fill(0, 127, 255, 100)
}
def draw() {
  for(i <- 1 to 3) {
    ellipse(x, y, diameter, diameter)
    diameter /= 1.4
  }
}

「繰り返し」を繰り返す

Processingでは、「繰り返し」を繰り返すような処理をする際for文をネストしていた。

for(int y = 10; y < height; y+=10){
    for(int x = 10; x < width; x+=10){
        ellipse(x, y, 5, 5)
    }
}

Spdeでは二重ループを次のように書き直せる。

for(x <- 10 until width by 10; y <- 10 until height by 10){
  ellipse(x, y, 5, 5)
}

untilはtoよりひとつ少ないRangeを返す(?)。語彙が乏しくて言葉が出てこない。

scala> 1 until 10
res0: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)

byによって変数のステップを定める。

円の重ね合わせのバリエーション

よってfor文をネストすることなしに(しかも分かりやすい書き方で)二次元的に図形を配置することができる。

size(400, 400)
background(0)
noStroke
smooth
colorMode(HSB, 360, 100, 100, 100)
rectMode(CENTER)
noLoop

def draw(){
  for(x <- 40 until width by 80; y <- 40 until height by 80; i <- 0 until 10){
    fill(random(200, 240), 100, 100, 50)
    ellipse(x + random(-20, 20), y + random(-20, 20), random(1, 40), random(1, 40))
  }
}

ランダムな図形を敷き詰める

JARED TABELのNINE.BLOCKを作ろうとしてあきらめた残骸。

size(400, 400)
background(0)
noStroke
noLoop
smooth
colorMode(HSB, 360, 100, 100, 100)
rectMode(CENTER)

def randomFig(x: Int, y:Int){
  val l = List((x:Int, y:Int)=>ellipse(x, y, 10, 10),
               (x:Int, y:Int)=>rect(x, y, 10, 10),
               (x:Int, y:Int)=>triangle(x-5, y-5, x-5, y+5, x+5, y-5),
               (x:Int, y:Int)=>rect(x, y, 5, 10)
               )
  val r = l.apply(floor(random(l.length)))
  val rot = PI*random(4).toInt/2.0
  pushMatrix
  translate(x, y)
  rotate(rot)
  r(0, 0)
  popMatrix
}

def draw() {
  for(x <- 10 until width by 40; y <- 10 until height by 40){
    for(_x <- 0 until 30 by 10; _y <- 0 until 30 by 10){
      randomFig(x + _x, y + _y)
    }
  }
}

あきらめた理由

基本図形を描くのが面倒でやめた。画像で用意したほうがいい。
点対称に図形を配置するのは簡単だと思う。←負け惜しみ

あきらめんなよ!!

というわけでつづく。