マウスに反応させる

2019-04-09

本章のあらすじ

  • マウスに反応させる
  • 計算式を扱う
  • 自分だけのペンツールを作ってみる

マウスに反応させる

前回は、Processingで簡単な図形を描く方法を学びました。描きっぱなしなので静止画でしたが、本来プログラムは、さまざまな情報を入力としてインタラクティブに表情を変えることができます。

今回は簡単なインタラクションの導入として、マウスに反応させる方法を学んでいきましょう。

マウスボタンを押したとき: mousePressed()

Processingでは、マウスに反応するブロックが複数用意されています。例えば mousePressed() は、マウスボタンを押したときに実行されるブロックです。

// 最初に1回だけ実行されるブロック
void setup() {
  size(600, 600);
  background(255, 255, 255);
}

// マウスボタンを押したときに実行されるブロック
void mousePressed() {
}

// (もうひとつ別のブロックも一緒に追加するが、理由は後ほど)
void draw() {
}

なぜか一緒に draw() という名前の空のブロックが追加されていますね。理由は後ほど説明しますが、Processingではこれがないとマウスに反応できないのです。現時点では「マウスに反応させるためには draw() ブロックも必要なんだ」程度の理解でOKです。

さて、 mousePressed() ブロック内に文を追加して、マウスボタンが押されたときに円を描いてみましょう。

void mousePressed() {
  ellipse(300, 300, 200, 200);
}

うまく実行できたでしょうか?

カーソル位置を利用する

中央に円が表示されるだけではつまらないので、クリックした位置に円を描画するように改良してみましょう。

円を描く位置は ellipse() 内の数値で指定できましたが、どうやってカーソルの位置を円の中心にするのでしょうか?

Processingでは mouseX, mouseY という特別なキーワードが用意されていて、それぞれカーソルのX/Y座標として数値のように使うことができます。

void mousePressed() {
  // カーソル位置を中心に円を描く
  ellipse(mouseX, mouseY, 200, 200);
}

このように書けば、クリックしたときにカーソル位置を中心に円が描かれます。 mouseX, mouseY と書かれた場所は、そのときどきのカーソル位置に置き換わるイメージです。

マウスボタンを押すたびに mousePressed() ブロックが実行されるので、何度もクリックすれば円がたくさん描かれます。

マウスを動かしたとき: mouseMoved()

mouseMoved() ブロックは、マウスカーソルが動いたときに実行されるブロックです。先ほどのコードの mousePressedmouseMoved に書き換えて実行してみましょう。どのような変化があるでしょうか?

void setup() {
  size(600, 600);
  background(255, 255, 255);
}

void mouseMoved() {
  ellipse(mouseX, mouseY, 200, 200);
}

void draw() {
}

マウスカーソルが少し動くごとに頻繁にブロックが実行され、たくさんの円が連なって描かれるようになりました。もう一息でお絵かきツールのペンにも使えそうな気がしてきます。

マウスを離したとき: mouseReleased()

ここでは詳しく解説しませんが、 mousePressed() がマウスのボタンを押したとき、 mouseReleased() は離したときに実行されるブロックです。

マウスをドラッグしているとき: mouseDragged()

mouseDragged() ブロックはマウスをドラッグしているときに実行されるブロックです。先ほどのコードの mouseMoved() ブロックをさらに mouseDragged() に書き換えてみましょう。どんな変化がありましたか?

マウスのボタンを押してドラッグしたときだけ円が描かれるようになりました。

マウスで線を引く

このまま塗り色とサイズを調整すれば、ペンツールとして不便なく使えるでしょうか?やってみましょう。

void setup() {
  size(600, 600);
  background(255, 255, 255);
}

// マウスがドラッグされたときに実行されるブロック
void mouseDragged() {
  // 図形を描く前に塗りと線を設定
  noStroke();
  fill(0);
  // カーソル位置に円を描く
  ellipse(mouseX, mouseY, 5, 5);
}

void draw() {
}

描けないことはないのですが、マウスを素早く動かすと途切れてしまいますね。これを防ぐためには、円で表現するのではなく、少し前のカーソル位置から現在のカーソル位置まで線を引いてあげるのがよいでしょう。

Processingには pmouseX, pmouseY という便利なキーワードが用意されていて、それぞれ少し前のカーソルのX/Y座標として使うことができます。 p は「Previous=以前の」の頭文字です。

線を引くのは line() でした。 pmouseX, pmouseY, mouseX, mouseY を組み合わせると…。

void setup() {
  size(600, 600);
  background(255, 255, 255);
}

// マウスがドラッグされたときに実行されるブロック
void mouseDragged() {
  // 少し前のカーソル位置から現在のカーソル位置まで線を引く
  line(pmouseX, pmouseY, mouseX, mouseY);
}

void draw() {
}

途切れず描けています。ペンツールが完成しました!

計算式

ほとんどのプログラミング言語ではコード中に計算式を書くことができまして、この講義で扱うProcessingでも可能です。コンピューターは式を解釈したうえで結果を計算してくれます。

よく使う演算記号計算結果
足し算+10 + 212
引き算-10 - 28
掛け算*10 * 220
割り算/10 / 25
割り算の余り%10 % 73

計算の優先順序を変える括弧 () も使えます。これまで出てきた特別なキーワード mouseX, mouseY なども、数値と同様に扱えるので計算式に含めることができます。

// これ自体はまったく意味のないコードですが、
// このような込み入った計算式も問題なく使えるという例です
rect(
  (mouseX + 10) * 2,
  mouseY / 7,
  100 + (2 * (100 - mouseX)) % 3,
  (mouseX + 20) / mouseY * 0.1
);

もう少し実用的な例として、カーソル位置と少しずらしたところにもう1本線を引くスケッチを作成してみましょう。

void mouseDragged() {
  // メインの線を引く
  stroke(0, 0, 0);
  line(pmouseX, pmouseY, mouseX, mouseY);

  // Y軸方向に少しずらして、薄い線(影)を引く
  stroke(0, 0, 0, 20);
  line(pmouseX, pmouseY + 10, mouseX, mouseY + 10);
}

mouseY + 10 でカーソル位置のY座標に10を足すことで、Y軸方向に少しずれた位置に線を描くことができています。

文法さえ外さなければ、計算式は自由に書き換えられます。例えば掛け算に変えると、結果はどのように変化するでしょうか?

  line(pmouseX, pmouseY * 1.2, mouseX, mouseY * 1.2);

余裕がある人は、いろいろ書き換えて試しながら、どうしてそのような結果が得られるのか考えてみてください。トライアル&エラーの繰り返しが上達への近道です。

練習:自分だけのペンツールを作ってみる

これまで習得した知識を駆使して、自分だけのペンツールを作ってみましょう。とはいえ、何を作ればよいかいきなりはわからない人も多いと思いますので、アイディアのタネとなる例をいくつか紹介しておきます。

XとYを入れ替えてみる

line()ellipse() に指定しているXとYを入れ替えてみると、どんな模様ができるでしょうか?(→yx_pen

XとYを入れ替えた場所にも描いてみた例

発展

  • 上下や左右の鏡写しペンは作れる?

固定の位置と線を引いてみる

カーソル位置と、固定の位置(例えば画面端や画面中央)で線を引いてみるとどうなるでしょうか?(→fixed_pen

線の片側を画面中央に固定してみた例

発展

  • 上下左右端と結ぶと?
  • 同時に複数の点と結ぶと?

カーソル位置を色に反映する

色を変える fill()stroke() にも、カーソル位置 mouseX, mouseY を指定することができます。工夫して綺麗な色が出せないでしょうか?(→gradient_pen

X軸方向の位置を色に反映して見た例

発展

  • XとYを同時に色に反映すると?

本章のまとめ

  • マウスに反応するブロックがたくさんある( mousePressed(), mouseDragged(), … )
  • カーソルの位置は特別なキーワード mouseX, mouseY で使える
  • コード中には計算式を書くことができる