コンテンツにスキップ

変数と図形を描く関数で絵を作る

この章では、p5.js に用意されている様々な関数を使って図形を描きます。 まず私たちが用いる座標系について説明し、次にいろいろな図形のパラメータがどのように指定されるかを紹介します。 また、変数と計算について学び規則的な図形の配置を簡単に作れるようになります。

座標系

私たちがふだん使っているコンピュータのモニタには、画素(ピクセル)と呼ばれる小さな点が格子状に並んでいて、それぞれの色を変化させることで絵を表示しています。 物理的なモニタの構造だけでなく、p5.js の画面(キャンバス)も同様の構成を持っていて、 createCanvas(横の画素数, 縦の画素数) で好きな大きさのキャンバスを作ることができます。

キャンバス上の位置を表示する座標は、画素の位置そのものです。 x 座標と y 座標はモニタの左上隅の画素が原点 (0, 0) であり、x軸が右方向に、y軸が下方向へ伸びています。 y軸の方向が数学でよく使う座標系と異なるのではじめは慣れないかもしれません。 これから図形を描くときにはたくさんの座標をコンピュータに指示する必要があるので、使いながら慣れていきましょう。

図形を描く関数

図形を描く関数をたくさん紹介します。 いま全部覚えるのは厳しいので、自分の使いそうなものだけよく見てください。 また、分からなくなったらいつでもこの章に戻ってきてください。 全部を覚えるよりも、それぞれのサンプルコードで入力している数値を書き換えて変化を観察してみましょう。 私たちが使う座標への理解につながります。

point で点を描く

画素一個分の点を打ちます。 みなさんの使っている画面によっては見えにくいかもしれないので、その場合はブラウザを拡大してみてください。

function setup() {
    createCanvas(300, 300);
    background(200);
}

function draw() {
    point(150, 150);
}

line で直線を描く

一本の直線を引きます。 始点と終点それぞれのx座標とy座標を指定します。

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    line(50, 50, 450, 250);
}

rect で長方形を描く

長方形を描きます。 デフォルトでの引数は、rect(左上のx座標, 左上のy座標, 横幅, 縦幅) です。

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    rect(100, 100, 300, 200);
}

rect の前にrectMode を呼ぶことで座標の指定方法を変えられます。 デフォルトの指定方法は、rectMode(CORNER)です。

中心&大きさで長方形を描く

rectMode(CENTER) を指定することで、長方形の中心と縦横の大きさを指定した描画ができます。

rect(中心のx座標, 中心のy座標, 横幅, 縦幅)

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    rectMode(CENTER);
    rect(250, 250, 300, 200);
}

両端の位置で長方形を描く

rectMode(CORNERS) を指定することで、左上角の座標と右下角の座標を指定した長方形を描くことができます。

rect(左上のx座標, 左上のy座標, 右下のx座標, 右下のy座標)

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    rectMode(CORNERS);
    rect(100, 100, 300, 200);
}

ellipse で楕円を描く

中心位置と縦横の直径を指定して楕円を描きます。

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    ellipse(250, 250, 150, 100);
}

ellipse より前に ellipseMode(RADIUS) を書くことで楕円の大きさを半径で指定できるようになります。

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    ellipseMode(RADIUS);
    ellipse(250, 250, 150, 100);
}

円の場合は circle を使いましょう。 こちらもellipse と同じでデフォルトでは中心位置と直径を指定します。 また、ellipseMode(RADIUS)で半径の指定に変更できます。

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    circle(250, 250, 100);
}

triangle で三角形を描く

3つの頂点座標を与えて三角形を描きます。

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    triangle(50, 450, 250, 50, 450, 450 );
}

変数と計算

プログラムを使って絵を描くことの利点は、変数を使った計算結果をもとに関数を呼び出せることです。 変数は数学で使う変数と同じ意味にとらえてかまいません。 座標を求める計算式さえ書いてしまえば、こまごまとした座標を与えなくても図形を画面に表示することができます。 以下に図形を決めるための座標を計算で求める例として、右へ150ずつずらしながら3つの円を描くプログラムを示します。

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    let x;
    let y = 250;
    let width = 100;

    x = 100;
    circle(x, y, width);

    x = x + 150;
    circle(x, y, width);

    x = x + 150;
    circle(x, y, width);
}

例2-2-1 には x, y, width という3つの変数が登場しています。 プログラミングにおいては、変数の名前を数学のように1文字にする必要はなく、自分の好きな名前を付けることができます。 width のように意味のある単語などを使うと読みやすく分かりやすい良いプログラムを書くことができます。 重要なのはその変数がなにを意味するかが分かることなので、自分なりに読みやすいように変数名を考えるようにしてください。

変数の使い方について詳しく説明する前に、実際に計算しているところを見ましょう。 以下は、a = 7, b = 4 として計算をするだけのプログラムです。 変数や数値に対して、四則演算などをコンピュータの一般的な書き方で計算させることができます。 % は余りの計算です。

四則演算以外にも、三角関数などの便利な関数が初めから用意されています。 例では円周率 PI を使って sin, cos を計算しています。 これらの関数では多くの場合、角度として弧度法(ラジアン)での数値を使います。 radians(degree) を使うと度数法(°)から変換することができます。 他の関数は reference/#math から調べられます。

[例2-2-2. 変数を使った計算]

function setup() {
    let a = 7;
    let b = 4;

    let sum = a + b; // 11
    let diff = a - b; // 3
    let prod = a * b; // 28
    let quot = a / b; // 1.75
    let rem = a % b; // 3
    let sine = sin(PI/2); // sin(π/2) == 1
    let cosine = cos(radians(180)); //  cos(180°) = cos(π) = 1

    print(sum);
    print(diff);
    print(prod);
    print(quot);
    print(rem);
    print(sine);
    print(cosine);
}

function draw() {
}

変数の使い方

詳しい文法について説明します。 私たちが使いたい変数をコンピュータに知らせることを変数の宣言といい、let <変数名> のように書きます。 これで宣言した変数は、以降その名前で自由に使うことができます。

注意として、同じ変数名を宣言できる場合があるのですが、値が上書きされてしまいプログラムが思ったように動かなくなる可能性があります。 これに関してはすこし複雑なルールがあるので授業では扱っていません。 とりあえずは同じ変数名を使わないように心がければ大丈夫です。 興味のある人は、付録の 変数の寿命 を読んでみてください。

変数に値を代入するためには、= を使います。 =右辺に書いた数字や変数の値が、左辺に代入されます。 変数の宣言と代入はいっぺんにおこなうことができて、次の2つのコードは同じ意味です。

// 変数の宣言と代入を別々におこなう
let x;
x = 10;

// 変数の宣言と代入をいっぺんにおこなう
let x = 10;

演算や関数の結果を変数に代入することができます。

// 計算結果を変数に代入する
x = 10 + 20;
x = sin(1);

数学の等号と異なり、代入の操作は向きが決まっています。 例えば次のような書き方は許されていません。

// *左辺から右辺への代入はできない
250 = x;

また、プログラムでは次のような書き方ができます。

// x を150増加させる
x = x + 150;
数学ではありえない式ですが、これはxにもともと入っていた値に150を加えて、再びxへ代入するという意味です。 すなわち、この文はxを150増加させるという操作をおこなっています。 例2-2-1 において、円の位置を右へずらしていくような場面でこの書き方をします。

変数を使ってアニメーションを作る

p5.js では draw のブロックを何度も呼び出してアニメーションを実現しています。 (アニメーションのためのしくみ) アニメーション全体を通して使用する変数を用意し、数値を少しずつ変化させることで動きを制御することができます。 次のプログラムは円の座標の角度を表す変数を angle とし、1フレームごとに0.1ラジアンずつ増加させて描くことで円運動を実現しています。

let angle = 0; // はじめ angle = 0 に設定する

function setup() {
    createCanvas(500, 500);
    background(200);
}

function draw() {
    background(200);

    angle = angle + 0.1; // angle を 0.1 増加させる

    let center_x = 250;
    let center_y = 250;

    let r = 100;
    let x = center_x + r*cos(angle);
    let y = center_y + r*sin(angle);

    circle(x, y, 60);
}

この例ようにフレームを超えて使いたい変数はブロックの外で宣言する必要があります。 逆に、ブロックの中で宣言された変数は同じ名前であっても各 draw の実行ごとに新しく作られる別物であり、前フレームの情報を引き継ぐことができません。

// *angle が変化しないので図形は移動しない
function draw(){
    let angle = 0;
    angle = angle + 0.1;
    ...
}

思った絵が出ないときは

プログラムは書いたとおりにしか動きません。 思ったようにプログラムが動かないということは、思っているのと違う数値を使って関数を呼びしているということです。 このようなときはまず、プログラムのいろいろな場所で print(<変数>) を使ってコンソールへ値を表示し、どんな数値が関数に渡っているかを確認しましょう。

練習問題

練習1

図形を描く関数を使って、顔のような絵をかいてみましょう。 だいたい楕円、長方形、直線の組み合わせでいけます。

練習2

下図のような絵を描いてください。 ただし、図形の位置や大きさが変化するように計算式を使って決めてください。 図形の色についてはまだ学んでいないので再現する必要はありません。

練習3

次のプログラムは、変数 x, y の位置に円を描きます。

let x = 100;
let y = 100;

function setup() {
    createCanvas(windowWidth, windowHeight);
    background(200);
}

function draw() {
    circle(x, y, 60);
}

これをもとに、draw の中でx, y を更新していくことで円が徐々に左上から右下に動くようなプログラムを書いてください。 ループする必要はなく、円が画面外に消えてしまうもので良いです。