p5.jsでシンセサイザーを作る 第3話 ノブ制作 当たり判定編
Javascriptとp5.jsを使って、オリジナルなシンセサイザーを作るプログラミングの記事です。とりあえず何を作るのかを手っ取り早くお伝えしたいので、第0話で公開している完成品もチェックしてみてください。
ノブの作成
シンセサイザーには欠かせないノブ(ツマミ)を作ります。
ノブの描画
circleを使ってこのパーツを作ります。構造としては、影、ノブのベース、赤色のマーカー、ノブのトップという感じで、分割して描画します。
一箇所に描画します
let knobX = 100;
let knobY = 100;
let knobSize = 50;
let strokeValue = 2;
function setup() {
createCanvas(500, 400);
}
function draw() {
background(250); //背景の色
noStroke(); // 枠線を消す
fill(100, 100, 100); //
circle(knobX - 3, knobY + 3 ,knobSize); //影の描画
stroke(150, 100, 100); //
strokeWeight(strokeValue); // 枠線の太さ
fill(200, 200, 200); //
circle(knobX, knobY ,knobSize); // ノブのベース
fill(250, 250, 250); //
circle(knobX, knobY, knobSize / 2); // ノブのトップ
fill(250, 0, 0); //
circle(knobX, knobY, 10); // ノブのマーカー
}
このコードを実行するとこのようにノブが表示されます。
p5.jsのcircle()は引数によって指定された座標を中心として円を描画します。影のところだけ座標の引数をknobX - 3, knobY + 3としているのは微妙に陰影をつけたいからです。目分量で左下に描画位置をずらしています。
ノブのトップ部分である白いところは3番目の引数である直径をknobSizeの2分の1にしています。
赤いマーカーが中心に来ているのは?
赤色のマーカーについてですが、このあと実際にマウスクリックによってノブの回転を表現するのですが、少し複雑な処理をして位置を決めますので、仮置きで中心に置いています。このあと、動的な処理を記述して正しい位置に描画させていきます。
マウスクリックに反応させる
プログラム制作においてユーザー操作への視覚的レスポンスは重要だと思います。ノブは回転するパーツなのでその辺りはあとで詳しく記事にしますが、マウスクリックにプログラムが反応するようにしていきます。
var knobStat = false;
setup()の前にknobStatという変数を作ります。これはマウスがクリックされていればtrueマウスがクリックされていなければfalseとなるように取り扱います。
if (knobStat == true){ // マウスクリックでオレンジ色でノブトップを塗り替える
fill(255, 125, 0);
circle(knobX, knobY, knobSize / 2);
}
draw()の中にはknobStatがtrueの時にオレンジ色でノブトップを塗り替える記述を追加します。
function touchStarted() {
if (
mouseX > knobX - knobSize / 2 &&
mouseX < knobX + knobSize / 2 &&
mouseY > knobY - knobSize / 2 &&
mouseY < knobY + knobSize / 2
) {
knobStat = true;
}
}
function touchEnded() {
knobStat = false;
}
touchStarted()とtouchEnded()という関数をdraw()の下に追加します。この二つの関数はp5.jsで標準で定義されているもので、マウスクリック(スマホの画面タッチ)を常時監視しています。
mouseXとmouseYも、同様にp5.jsで最初から定義されているもので、マウスやタッチの座標を監視しています。自分で変数を宣言する必要はありません。
クリックされた範囲を特定する(当たり判定)
マウスクリックのイベントが発生した時に、ノブをクリックしたのか、何もない領域をクリックしたのかを判定します。いわゆる当たり判定をif文で記述しています。
function touchStarted() {
if (
mouseX > knobX - knobSize / 2 &&
mouseX < knobX + knobSize / 2 &&
mouseY > knobY - knobSize / 2 &&
mouseY < knobY + knobSize / 2
) {
knobStat = true;
}
}
基本的にはノブの左上から右下までの座標にマウスのポイントがはまった場合にknobStatをtrueにしたい。というだけです。
なのですが、このノブはcircle()という、中心を基準にした描画をしているので、このようなコードの記述になります。このため、図形の四隅を指定するために、中心からknobSizeの右半分、左半分、上半分、下半分という風に範囲を指定しています。
この4点の範囲がクリックされた場合knobStatがtrueになります。
本来は円形の中に当たり判定をつけるのかもしれませんがこのように矩形の範囲を設定するだけでユーザービリティの面では全く問題ありません。
function touchEnded() { knobStat = false; }
マウスが離されたら
function touchEnded() {
knobStat = false;
}
この部分は至極単純で、マウスが離されたらknobStatがfalseになるだけです。
draw()の中で反応を可視化する
if (knobStat == true){ // マウスクリックでオレンジ色でノブトップを塗り替える
fill(255, 125, 0);
circle(knobX, knobY, knobSize / 2);
}
draw()関数の中に追加したこのコードによってknobStatがtrueの時だけ、ノブトップがオレンジ色に光るようになりました。
この記事のコード全文
let knobX = 100;
let knobY = 100;
let knobSize = 50;
let strokeValue = 2;
var knobStat = false;
function setup() {
createCanvas(500, 400);
}
function draw() {
background(250); //背景の色
noStroke(); // 枠線を消す
fill(100, 100, 100); //
circle(knobX - 3, knobY + 3 ,knobSize); //影の描画
stroke(150, 100, 100); //
strokeWeight(strokeValue); // 枠線の太さ
fill(200, 200, 200); //
circle(knobX, knobY ,knobSize); // ノブのベース
fill(250, 250, 250); //
circle(knobX, knobY, knobSize / 2); // ノブのトップ
fill(250, 0, 0); //
circle(knobX, knobY, 10); // ノブのマーカー
if (knobStat == true){ // マウスクリックでオレンジ色でノブトップを塗り替える
fill(255, 125, 0);
circle(knobX, knobY, knobSize / 2);
}
}
function touchStarted() {
if (
mouseX > knobX - knobSize / 2 &&
mouseX < knobX + knobSize / 2 &&
mouseY > knobY - knobSize / 2 &&
mouseY < knobY + knobSize / 2
) {
knobStat = true;
}
}
function touchEnded() {
knobStat = false;
}
実際にp5.jsのエディターにコピペして、試してみてください。
次はノブを実際に動かしていくためのプログラムに移ります。