p5.jsでシンセサイザーを作る 第9話 パーツの配置 p5.jsの基本を復習
Javascriptとp5.jsを使って、オリジナルなシンセサイザーを作るプログラミングの記事です。とりあえず何を作るのかを手っ取り早くお伝えしたいので、第0話で公開している完成品もチェックしてみてください。
p5.jsの繰り返し処理による複数の図形描画
今回は一度、p5.jsの基本記述についておさらいしていきます。まずは円を描画していきます。
円の描画
//円の値
let knobX = 100;
let knobY = 50;
let knobSize = 50;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(200);
fill(250,125,0);
//円の描画
circle(knobX ,knobY ,knobSize);
}
円の描画はcircle()の関数を使います。
引数は中心のX、中心のY、円のサイズ
この三つを指定するだけです。このコードでは一個の円が出るだけなのですが、繰り返しの構文を使って複数の図形を一気に記述したい所です。
For文で円の描画を繰り返す
それでは、前回の記事で使用したFor文で5個の円を一気に描画します。
//円の値
let knobX = 100;
let knobY = 50;
let knobSize = 50;
let knobInterval = 10; //円を描画する間隔。
function setup() {
createCanvas(400, 400);
}
function draw() {
background(200);
fill(250,125,0);
//円を繰り返しで描画
for(let i = 0; i < 5; i++){
circle(knobX + i * knobInterval ,knobY ,knobSize);
}
}
このコードの変更点はknobIntervalという円と円の感覚を指定する変数を追加したこと。
そしてcircle()をfor文を使って5回繰り返して実行している所です。
p5.jsの繰り返し描画のポイント
ここでのポイントは、for文の中で実行しているこの部分です。
circle(knobX + i * knobInterval ,knobY ,knobSize);
+ i * knobInterval
この部分を省いて、circleを記述して見ます
//円の値
let knobX = 100;
let knobY = 50;
let knobSize = 50;
let knobInterval = 10; //円を描画する間隔。
function setup() {
createCanvas(400, 400);
}
function draw() {
background(200);
fill(250,125,0);
//円を繰り返しで描画
for(let i = 0; i < 5; i++){
circle(knobX ,knobY ,knobSize); // ここに注目
}
}
circle(knobX ,knobY ,knobSize);
このように、For文の中で実行されるcircle()を実行すると、5回の繰り返しは実際に行われているのですが、全てが同じ座標に描画されているため、単なる一つの円にしか見えません。
ここで、先ほど記載した+ i * knobIntervalの記述をcircle()の中に記述しています。
コードをもう一度見てみる
for(let i = 0; i < 5; i++){
circle(knobX + i * knobInterval, knobY ,knobSize);
}
このコードはFor文でよく使われる表現です。説明します。
今回の描画ロジックで注目したいのは第一引数の部分です。
起点は常にknobXから始まるのですが、複数の円形を描くために繰り返し回数”i”に応じて、knobIntervalの分だけ開始位置を右にずらしています。
分かりにくいかも。自信がありません。ここまで書いていて申し訳ないですが、色々いじって感覚的に習得するのも大事ではないかと思いました。
もう一回実行
//円の値
let knobX = 100;
let knobY = 50;
let knobSize = 50;
let knobInterval = 10; //円を描画する間隔。
function setup() {
createCanvas(400, 400);
}
function draw() {
background(200);
fill(250,125,0);
//円を繰り返しで描画
for(let i = 0; i < 5; i++){
circle(knobX + i * knobInterval ,knobY ,knobSize);
}
}
位置決め
繰り返しの描画はできていますが、どう考えても円が重なっています。しかし、ここまで来れば簡単です。
円の間隔を指定するknobIntervalを50まで広げて見ましょう
let knobInterval = 50; //円を描画する間隔。
綺麗に並びましたが、もう少し間隔を広げたいです。
knobIntervalを60まで広げてみます。
let knobInterval = 60; //円を描画する間隔。
いい感じです。それぞれの円が等間隔に、適切な間隔で5個並びました。
ここまで円の描画を例にしていますが、矩形(四角形)も描画して見ます。
矩形の描画
//矩形の値
let keyX = 100;
let keyY = 50;
let keySize = 50;
let keyInterval = 60; //円を描画する間隔。
function setup() {
createCanvas(400, 400);
}
function draw() {
background(200);
fill(250,125,0);
//矩形を繰り返しで描画
for(let i = 0; i < 5; i++){
rect(keyX + i * keyInterval ,keyY ,keySize ,keySize);
}
}
うまく描画されています
円の場合はcircle()を使いますが、矩形の場合はrect()を使っています。
rect()の場合引数は四つあります。
左上X、左上Y、矩形の横幅、矩形の縦幅
この四つです。
全部一気に描画します。
//円の値
let knobX = 100;
let knobY = 100;
let knobSize = 50;
let knobInterval = 60; //描画する間隔。
//矩形の値
let keyX = 100;
let keyY = 150;
let keySize = 50;
let keyInterval = 60; //描画する間隔。
function setup() {
createCanvas(400, 400);
}
function draw() {
background(200);
fill(250,125,0);
//円を繰り返しで描画
for(let i = 0; i < 5; i++){
circle(knobX + i * knobInterval ,knobY ,knobSize);
}
//矩形を繰り返しで描画
for(let i = 0; i < 5; i++){
rect(keyX + i * keyInterval ,keyY ,keySize ,keySize);
}
}
これで円と矩形を一気に描画できました。
繰り返しによる処理で図形を並べることができましたので、ここからは、ノブのパーツやキー、ボタンのパーツを必要なだけ、繰り返し配置することができるようになります。第0話で公開しているシンセサイザーのパーツはこの応用によって配置しています。また、当たり判定についても、配置位置を起点としているので、同じくFor文を使って判定することができます。
補足
前に掲載している画像ですが、円と矩形が綺麗に並ばずに、矩形が右下にずれています。
これはcircle()が中心を起点としているのに対して、rect()は左上を起点にしているところが原因です。
色々やり方はあるのですが、簡単に横位置を揃えるのであれば、矩形の位置であるkeyXを左にずらしてしまうというロジックが便利です
let keyX = knobX - knobSize / 2;
円形の中心"knobX"から、円のサイズ"knobSIze"の半分だけ左にずらした位置が矩形の左側起点"keyX"である。
このロジックは万能ではなく、UIのデザイン上目分量によって細かい位置キメをすることもありますので、参考程度のアイデアです。
このような開発においては、計算式によって統一された美しいロジックを組むのも楽しいのですが、そもそもの目的は、シンセサイザーを作ることです(忘れそうになります)。
適時、計算ロジックの”共通化”と目分量による、”勘”によってUIを最適化していくことが大事なのだなと思いました。
この記事のコード全文
//円の値
let knobX = 100;
let knobY = 100;
let knobSize = 50;
let knobInterval = 60; //描画する間隔。
//矩形の値
let keyX = knobX - knobSize / 2;
let keyY = 150;
let keySize = 50;
let keyInterval = 60; //描画する間隔。
function setup() {
createCanvas(400, 400);
}
function draw() {
background(200);
fill(250,125,0);
//円を繰り返しで描画
for(let i = 0; i < 5; i++){
circle(knobX + i * knobInterval ,knobY ,knobSize);
}
//矩形を繰り返しで描画
for(let i = 0; i < 5; i++){
rect(keyX + i * keyInterval ,keyY ,keySize ,keySize);
}
}
実際にp5.jsのエディターにコピペして、試してみてください。
これで、パーツ配置の構文が大体できています。実際にノブやキーを配置する様子を次回から記事にしていきたいと思います。