本稿では、フクロウの描画を通して、関数の作成に必要な手順を見ていきます。
目次
フクロウの描画
フクロウを描画するコードの例です。
function setup() {
createCanvas(480, 120);
}
function draw() {
background(204);
translate(110, 110);
stroke(0);
strokeWeight(70);
// 胴体
line(0, -35, 0, -65);
noStroke();
fill(255);
// 左目用の円
ellipse(-17.5, -65, 35, 35);
// 右目用の円
ellipse(17.5, -65, 35, 35);
// あご
arc(0, -65, 70, 70, 0, PI);
fill(0);
// 左目
ellipse(-14, -65, 8, 8);
// 右目
ellipse(14, -65, 8, 8);
// くちばし
quad(0, -58, 4, -51, 0, -44, -4, -51);
}
ただしここでは(後々関数として使用しやすいように)、translate()を使って原点(0, 0)を(110, 110)に移動させ、そこを基準にフクロウを描いています。したがって、シェイプの座標は場所によって正や負の値になっています。
仲間を描画
フクロウを描画する前のコードは、フクロウが1羽のときは問題ないのですが、もう1羽描きたいとなると、ほぼ倍になります。
function setup() {
createCanvas(480, 120);
}
function draw() {
background(204);
// 左のフクロウ
translate(110, 110);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65);
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35);
ellipse(17.5, -65, 35, 35);
arc(0, -65, 70, 70, 0, PI);
fill(0);
ellipse(-14, -65, 8, 8);
ellipse(14, -65, 8, 8);
quad(0, -58, 4, -51, 0, -44, -4, -51);
// 右のフクロウ
translate(70, 0);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65);
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35);
ellipse(17.5, -65, 35, 35);
arc(0, -65, 70, 70, 0, PI);
fill(0);
ellipse(-14, -65, 8, 8);
ellipse(14, -65, 8, 8);
quad(0, -58, 4, -51, 0, -44, -4, -51);
}
ここではただ、translate()からquad()までのコードをコピーして下にペーストし、translate(110, 110)をtranslate(70, 0)に変更しているだけです。これは2羽めを描く方法としてははなはだ退屈で非効率的であり、3羽めを追加することなどまったく考慮していない方法です。しかし関数を使うとこの問題は一挙に解決します。
フクロウの関数
次の例では、関数を使って、同じコードでフクロウを2羽描画しています。フクロウを描画するコードを新しい関数にすると、そのコードはプログラム内に1つ記述するだけで済みます。
function setup() {
createCanvas(480, 120);
}
function draw() {
background(204);
owl(110, 110);
owl(180, 110);
}
const owl = (x, y) => {
push();
translate(x, y);
stroke(0);
strokeWeight(70);
line(0, -35, 0, -65);
noStroke();
fill(255);
ellipse(-17.5, -65, 35, 35);
ellipse(17.5, -65, 35, 35);
arc(0, -65, 70, 70, 0, PI);
fill(0);
ellipse(-14, -65, 8, 8);
ellipse(14, -65, 8, 8);
quad(0, -58, 4, -51, 0, -44, -4, -51);
pop();
}
関数を使ったこのサンプルは、前のものと結果は同じですが、フクロウを描画するコードがowl()関数内の1箇所しかないので、かなり短くなっています。owl()関数は、draw()内で2回呼び出されているので、2回実行されます。フクロウは、関数に渡される、xとy座標を設定するパラメータによって、2つの異なる位置に描画されます。
パラメータは、関数に柔軟性を与えるという理由で重要です。前のrollDice()関数では、6面や20面、また面数を問わないサイコロをシミュレーションするnumSidesという名前のパラメータを1つ使っていました。これは、p5.jsのほかの関数でも同じです。たとえば、line()関数のパラメータは、キャンバスのあらゆる点からほかのあらゆる点を結ぶ線の描画を可能にします。関数は、パラメータがないと、ある決められた点からほかの決められた点への線しか描画できないのです。
それぞれのパラメータは、関数が実行されるたびに作成される1つの変数です。このサンプルを実行してowl()関数が初めて呼び出されるとき、xパラメータの値は110、yパラメータの値も110です。次に呼び出されるときのxパラメータの値は180、yパラメータの値は110です。パラメータの各値は関数に渡され、関数内でその変数名が書かれた場所は全部、関数に入ってきたその値に置き換えられます。
もっと増やす
フクロウをキャンバスのどの位置にも描画する基本的な関数が作成できたので、関数をforループ内に置いて、ループが繰り返されるたびに1つめのパラメータ(x)を変更するという方法で、多くのフクロウが効率的に描画できるようになります。
function setup() {
createCanvas(480, 120);
}
function draw() {
background(204);
for (let i = 35; i < width + 70; i += 70) {
owl(i, 110);
}
}
const owl = (x, y) => {
// 前と同じ
}
フクロウの大きさと色をさまざに変える
関数にパラメータをもっと追加して、フクロウの見た目をさまざまに変えることができます。
次の例では、パラメータを2つ加えて、各フクロウのグレー値とサイズを変更しています。
function setup() {
createCanvas(480, 120);
}
function draw() {
background(204);
randomSeed(0);
for (let i = 35; i < width + 40; i += 40) {
const gray = int(random(0, 102));
const scalar = random(0.25, 1);
owl(i, 110, gray, scalar);
}
}
const owl = (x, y, g, s) => {
push();
translate(x, y);
// 縮小
scale(s);
// ストロークの色をg値に設定
stroke(g);
strokeWeight(70);
line(0, -35, 0, -65);
noStroke();
// 塗り色を255-g値に設定
fill(255 - g);
ellipse(-17.5, -65, 35, 35);
ellipse(17.5, -65, 35, 35);
arc(0, -65, 70, 70, 0, PI);
fill(0);
ellipse(-14, -65, 8, 8);
ellipse(14, -65, 8, 8);
quad(0, -58, 4, -51, 0, -44, -4, -51);
pop();
}
randomSeed()
説明
random()関数用のシード値を設定する。
デフォルトでは、random()関数は、プログラムが実行されるたびに異なる結果を生成するが、seedパラメータを定数に設定することで、ソフトウェアが実行されるたびに同じ疑似乱数値を返すようにする。
シンタックス
randomSeed(seed)