By Greg Benedis-Grab, Layla Quiñones
このチュートリアルでは、スケッチにユーザーインタラクションを追加する新しい方法と、コードの実行順序を制御する方法を学びます。
インタラクティブな太陽のスケッチと日の出アニメーションを作成することで、以下の基本的なプログラミングの概念を学びます:
- 条件文(if、if-else、else-if)
- ブール変数、比較演算子、式
- 加算/減算代入演算子
- インクリメントとデクリメント
- マウスボタンの押下とマウスポインタの位置によるインタラクティビティ
プログラムの流れを制御することは、コンピューティングの力の中心であり、p5.jsで魅力的なアニメーションやゲームを作成することを可能にします。通常、コードの行は順番に実行されます。以前のチュートリアルでは、draw()
関数がコードを上から下へ繰り返し実行することを見てきました。これにより、形状の重ね合わせや「フリップブック」アニメーションが可能になります。
前提条件
始める前に、以下のことができるようになっているはずです:
- p5.jsを使用してキャンバス上に図形やテキストを追加してカスタマイズする
circle()
|rect()
|ellipse()
|triangle()
|line()
fill()
,stroke()
,text()
,textSize()
mouseX
やmouseY
などの組み込み変数を使用するlet
と代入演算子を使用してカスタム変数を宣言、初期化、使用、更新するrandom()
、frameRate()
、frameCount
を使用して線形動作とランダムな動作の両方を組み込む- コードにコメントを付け、エラーメッセージに対処する - エラーメッセージとデバッグについてさらに学ぶには、デバッグのフィールドガイドリファレンスをお読みください。
パート1:インタラクティブな太陽
インタラクティブな太陽のスケッチを作成することは、条件文とユーザーインタラクションの使用方法を学ぶ素晴らしい方法です。
IF文(条件文)
条件文は、特定のコード行がいつ実行されるかを制御します。例えば、日の出前は空が暗いです。太陽が昇ると昼間になり、空はより明るい色になります。太陽の位置に基づいて空の色を変更する条件文(if文としても知られています)を書くことができます。太陽が高ければ空は明るい色になるべきで、そうでなければ空は暗いままです。if文は太陽の位置をチェックし、空の中での位置に応じて実行されるコードを制御できます。
太陽の位置をチェックする条件文を使用する前に、マウスポインタがキャンバス上を動くにつれて太陽の位置を更新するのに役立つカスタム変数を追加できます。
ステップ1:カスタム変数を定義し初期化する
新しいp5.jsプロジェクトを開き、“Interactive Sun”と名付けてスケッチを保存します。
太陽のy座標用のカスタム変数
sunHeight
と、地平線のy座標用のカスタム変数horizon
を宣言します。地平線の変数を200で初期化します。以下のコード行をスケッチの
setup()
の前に追加します://太陽と地平線のy座標用のカスタム変数 let sunHeight; let horizon = 200;
sunHeight
をマウスポインタのy座標であるmouseY
に更新します。以下のコードを
draw()
内に追加します://太陽がマウスのy座標に従う sunHeight = mouseY;
あなたのコードは以下のようになるはずです:
//太陽と地平線のy座標用のカスタム変数
let sunHeight;
let horizon = 200;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
//太陽がマウスのy座標に従う
sunHeight = mouseY;
}
太陽の高さが変化しているので、マウスのy座標mouseY
を変数sunHeight
に格納します。これをdraw()
内で行うことで、draw()
が実行されるたびにsunHeight
が継続的に更新されます。地平線は変化していませんが、カスタム変数horizon
は参照ポイントとして使用され、コードをより読みやすくします。
mouseY
とlet
についての詳細は、p5.jsリファレンスをご覧ください。
ステップ2:図形を描画しキャンバスに色を付ける
カスタム変数
sunHeight
をy座標として使用する太陽を描画します。以下のコードを
draw()
内に追加します://太陽 fill("yellow"); circle(200, sunHeight, 160);
地平線を示す線を描画します。
以下のコードを
draw()
内に追加します:// 地平線の線を描画 stroke("green"); line(0,horizon,400,horizon);
あなたのコードは以下のようになるはずです:
//太陽と地平線のy座標用のカスタム変数
let sunHeight;
let horizon = 200;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
//太陽がマウスのy座標に従う
sunHeight = mouseY;
//太陽
fill("yellow");
circle(200, sunHeight, 100);
// 地平線の線を描画
stroke('green');
line(0,horizon,400,horizon);
}
太陽は、circle(200, sunHeight, 100)
の円のy座標の引数としてsunHeight
が使用されているため、マウスポインタが垂直に動くにつれてそれに従います。キャンバス上に線が描画され、各端点のy座標の引数としてhorizon
が使用されています:y1, y2
。これはキャンバス上に地平線をマークし、背景色を変更するために使用されます。
形状と変数についてさらに学ぶには、p5.jsリファレンスページの2D形状、色、基礎、マウスイベントをご覧ください。一般的なバグについてのヘルプは、デバッグのフィールドガイド(例1&2)をお読みください。
ステップ3:ブール式を持つ条件文を使用して背景色を変更する
- 太陽が地平線より上にある場合、背景色を薄い青に設定します。
以下のコード行をスケッチの
draw()
内のsunHeight = mouseY;
の行の後に追加します://太陽が地平線より上にある場合、背景を薄い青に if(sunHeight < horizon){ background("lightblue"); }
あなたのコードは以下のようになるはずです:
//太陽と地平線のy座標用のカスタム変数
let sunHeight;
let horizon = 200;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
//太陽がマウスのy座標に従う
sunHeight = mouseY;
//太陽が地平線より上にある場合、背景を薄い青に
if(sunHeight < horizon){ //昼間かどうかをチェック
background("lightblue");
}
//太陽
fill("yellow");
circle(200, sunHeight, 100);
// 地平線の線を描画
stroke('green');
line(0,horizon,400,horizon);
}
コードを実行し、マウスを使って太陽を動かしてみてください!
上記のコードでは、draw()
で最初に読み取られる文がbackground(0)
であるため、デフォルトで背景は黒です。太陽が地平線より下にある場合、if文は中括弧内のコードブロックをスキップします:background("lightblue")
。太陽が地平線より上にある場合、中括弧内のコードブロックが実行されます。これにより、デフォルトの黒色から薄い青色に色がリセットされます。
ここでは、background(0)
とbackground("lightblue")
がいつ実行されるかを制御しています。条件文(またはif文)は、特定のコード行がいつ実行されるかを制御する方法であり、スケッチで何が起こるかを変更します。
IF文の構文
if文はif
キーワードで始まり、その後に括弧内の条件が続き、中括弧内のコードブロックと呼ばれる行が続きます。条件がtrue
の場合、コードブロックが実行されます。if文の構文は以下のように定義されます:
if (条件) {
// 条件がtrueの場合に実行されるコード
}
ブール式と値
if
キーワードの後の括弧内のコードは、ブール値またはブール式になります。以下の例では、ブール式を使用してsunHeight
変数の値がhorizon
変数の値より小さいかどうかをチェックしています:
|
|
|
ブール式 |
|
|
|
コードブロック |
|
ブール式はブール値を結果として返す文です。ブール値はtrue
またはfalse
のいずれかになります。数値や文字列とは異なり、ブール値は2つしかありません。ブール式は条件がtrue
かfalse
かをチェックするのに役立ちます。したがって、比較演算子と呼ばれる特殊な記号を使用します。比較演算子は2つの値を比較する特殊な記号です(以下の表を参照)。
ブール式を作成するために使用できる比較演算子記号には以下のものがあります:
記号 | 意味(p5.jsリファレンスリンク) | 例 |
---|---|---|
|
| |
|
| |
|
| |
|
| |
| 厳密等価(異なる型の値は等しくないと見なされる) |
|
| 等しくない |
|
式と演算子についてさらに学ぶには、MDNリファレンスをご覧ください。
ブール式をコンピューターが質問をしているものと考えることができます。ステップ3で追加したコードでは、ブール式はsunHeight < horizon
です。これは変数sunHeight
の値が変数horizon
の値より小さいかどうかを尋ねています。質問の答えがはい、つまりsunHeight < horizon
がtrue
の値を返す場合、コードブロックが実行されます。答えがいいえの場合、コードブロックはスキップされます。
sunHeight < horizon
の値をコンソールで確認するには、draw()
内のsunHeight = mouseY;
の後にconsole.log(sunHeight < horizon)
を追加します。キャンバス上でマウスを動かすと、コンソールに表示される値がtrue
からfalse
に変わるのを観察してください:太陽が地平線より下にあるときはfalse
、地平線より上にあるときはtrue
になります。このスケッチで例を見ることができます。
if文とブール値についてさらに学ぶには、p5.jsリファレンスページの基礎をご覧ください。
IF-ELSE文
もう一つの重要な条件文はif-else文で、2つのコードブロックを制御できます。if-else文の構文は以下のように定義されます:
if (条件) {
// 条件がtrueの場合に実行されるコード
} else {
// 条件がfalseの場合に実行されるコード
}
条件がtrue
の場合、最初のコードブロックが実行されます。false
の場合、else
キーワードの後に続くコードブロックが実行されます。コードが1つの条件に基づいて2つの変更を必要とする場合、if-else文はコードをより適切に構造化する方法です。if文をバブルマップとして視覚化すると役立ちます。以下のマップは、条件が真の場合に1番目のコードブロックが実行され、偽の場合に2番目のコードブロックが実行されることを示しています。
例えば、日の出アニメーションのif文を修正して、background()
関数を削除し、以下のif-else文を追加することができます:
元のコード:
//...function draw
background(0); // 夜空
//太陽がマウスのy座標に従う
sunHeight = mouseY;
//太陽が地平線より上にある場合、背景を薄い青に
if (sunHeight < horizon) {
background("lightblue"); // 青空
}
修正後のコード:
//...function draw
//太陽がマウスのy座標に従う
sunHeight = mouseY;
//太陽が地平線より上にある場合、背景を薄い青に
// if-else文を使用
if (sunHeight < horizon) {
background("lightblue"); // 地平線より上の場合は青空
} else {
background(0); // それ以外の場合は夜空
}
上記のコードでは、太陽が地平線より上にある場合、sunHeight < horizon
がtrue
を返し、background("lightblue")
のコードが実行されます。sunHeight
が地平線以上の場合、else
キーワードの後のコードブロック、background(0)
が実行されます。両方の書き方が同じ視覚効果を持っていますが、時にはif-elseを使用する方が明確で効率的な場合があります。特に2つの異なるコードブロックを制御できる場合です。
さらに学ぶには、p5.jsリファレンスページのif
とBoolean
をご覧ください。
ステップ4:太陽を隠す草を追加する
太陽が地平線より下にあるときに見えなくなるように、スケッチに草原の風景を追加します。
- 太陽の後に緑の長方形を描画して、太陽が地平線より下にあるときに隠れるようにします。この長方形のy座標の引数は
horizon
線の位置です。以下のコードを地平線の線の後の
draw()
内に追加します://草 fill("green"); rect(0, horizon, 400, 400);
あなたのコードは以下のようになるはずです:
//太陽と地平線のy座標用のカスタム変数
let sunHeight;
let horizon = 200;
function setup() {
createCanvas(400, 400);
}
function draw() {
//太陽がマウスのy座標に従う
sunHeight = mouseY;
//太陽が地平線より上にある場合、背景を薄い青に
//if-else文を使用
if (sunHeight < horizon) {
background("lightblue"); // 地平線より上の場合は青空
} else {
background(0); // それ以外の場合は夜空
}
//太陽
fill("yellow");
circle(200, sunHeight, 100);
// 地平線の線を描画
stroke('green');
line(0,horizon,400,horizon);
//草
fill("green");
rect(0, horizon, 400, 400);
}
スケッチを実行し、太陽を地平線より下に動かしてみてください。太陽が消えるにつれて空がどのように変化するか見てください。日の出アニメーションのサンプルスケッチへのリンク。
パート2:日の出アニメーション
次に、太陽が自動的に動き、空の色が徐々に変化する日の出アニメーションを作成します。
ステップ1:太陽の位置と背景色の変数を宣言し初期化する
新しいp5.jsプロジェクトを開き、“Sunrise Animation”と名付けて保存します。
太陽のy座標用のカスタム変数を宣言し、600で初期化します。
以下の行を
setup()
の前のスケッチに追加します://初期の太陽の位置用の変数 //地平線より下の点 let sunHeight = 600;
空の色の赤と緑の成分の値用のカスタム変数を宣言し、0で初期化します。
以下の行を
setup()
の前のスケッチに追加します://色変更用の変数 let redVal = 0; let greenVal = 0;
色コードについて思い出すには、fill()
のp5.jsリファレンスまたはRGBのMDNリファレンスを確認してください。
あなたのコードは以下のようになるはずです:
//初期の太陽の位置用の変数
let sunHeight = 600; //地平線より下の点
//色変更用の変数
let redVal = 0;
let greenVal = 0;
function setup() {
createCanvas(600, 400);
}
function draw() {
}
このステップでは、プログラムで使用される値を格納するための変数redVal
、greenVal
、sunHeight
を作成しました。sunHeight
の初期値は地平線より下の点で、redVal
とgreenVal
の初期値は黒色を示しています。これらはアニメーションが始まるときの太陽の位置と空の色を設定します。これらは、アニメーションの初期条件と呼ばれます。これで、これらの変数を使用してキャンバス上で変更を加えることができます。
ステップ2:カスタム変数を使用して風景を描画する
赤と緑のカスタム変数に基づいて背景を描画します。
以下のコードを
draw()
内に追加します://カスタム変数に基づいて背景を塗りつぶす //青の値は0に設定され、変更されません background(redVal, greenVal, 0);
カスタム変数
sunHeight
をy座標として使用する太陽を描画します。背景を塗りつぶした後に以下のコードを追加します:
//太陽 fill(255, 135, 5, 60); circle(300, sunHeight, 180); fill(255, 100, 0, 100); circle(300, sunHeight, 140);
風景に三角形の山を追加します。
太陽を描画した後に以下のコードを追加します:
//山 fill(110, 50, 18); triangle(200, 400, 520, 253, 800, 400); fill(110,95,20); triangle(200,400,520,253,350,400); fill(150, 75, 0); triangle(-100, 400, 150, 200, 400, 400); fill(100, 50, 12); triangle(-100, 400, 150, 200, 0, 400); fill(150, 100, 0); triangle(200, 400, 450, 250, 800, 400); fill(120, 80, 50); triangle(200, 400, 450, 250, 300, 400);
あなたのコードは以下のようになるはずです:
//初期の太陽の位置用の変数
let sunHeight = 600; //地平線より下の点
//色変更用の変数
let redVal = 0;
let greenVal = 0;
function setup() {
createCanvas(600, 400);
}
function draw() {
//カスタム変数に基づいて背景を塗りつぶす
background(redVal, greenVal, 0);
//太陽
fill(255, 135, 5, 60);
circle(300, sunHeight, 180);
fill(255, 100, 0, 100);
circle(300, sunHeight, 140);
//山
fill(110, 50, 18);
triangle(200, 400, 520, 253, 800, 400);
fill(110,95,20);
triangle(200,400,520,253,350,400);
fill(150, 75, 0);
triangle(-100, 400, 150, 200, 400, 400);
fill(100, 50, 12);
triangle(-100, 400, 150, 200, 0, 400);
fill(150, 100, 0);
triangle(200, 400, 450, 250, 800, 400);
fill(120, 80, 50);
triangle(200, 400, 450, 250, 300, 400);
}
このステップでは、background()
とcircle()
関数でカスタム変数を使用してアニメーションの風景をカスタマイズしました。太陽は最初に描画されたため、山の後ろに隠れていることを覚えておいてください!
試してみよう!
風景をユニークで興味深いものにするために、好きなだけ形を追加してください!
ステップ3:条件文を使用してカスタム変数を更新する
sunHeight
が130未満である限り、sunHeight
変数を変更して太陽を動かします。以下のコードを
draw()
内に追加します:// sunHeightが130に達するまで2ずつ減少させる if (sunHeight > 130) { sunHeight -=2; }
sunHeight
変数が480未満の間、redVal
とgreenVal
変数の値を変更して、空の色を徐々に変化させます。以下のコードを
draw()
内に追加します:// 日の出の間、色変数を4または1ずつ増加させる if (sunHeight < 480) { redVal += 4; greenVal += 1; }
あなたのコードは以下のようになるはずです:
//初期の太陽の位置用の変数
let sunHeight = 600; //地平線より下の点
//色変更用の変数
let redVal = 0;
let greenVal = 0;
function setup() {
createCanvas(600, 400);
}
function draw() {
//カスタム変数に基づいて背景を塗りつぶす
background(redVal, greenVal, 0);
//太陽
fill(255, 135, 5, 60);
circle(300, sunHeight, 180);
fill(255, 100, 0, 100);
circle(300, sunHeight, 140);
//山
fill(110, 50, 18);
triangle(200, 400, 520, 253, 800, 400);
fill(110,95,20);
triangle(200,400,520,253,350,400);
fill(150, 75, 0);
triangle(-100, 400, 150, 200, 400, 400);
fill(100, 50, 12);
triangle(-100, 400, 150, 200, 0, 400);
fill(150, 100, 0);
triangle(200, 400, 450, 250, 800, 400);
fill(120, 80, 50);
triangle(200, 400, 450, 250, 300, 400);
// sunHeightが130に達するまで2ずつ減少させる
if (sunHeight > 130) {
sunHeight -= 2;
}
// 日の出の間、色変数を4または1ずつ増加させる
if (sunHeight < 480) {
redVal += 4;
greenVal += 1;
}
}
スケッチが実行されると、太陽が自動的に動きます!この動きはsunHeight -= 2
という文によって引き起こされ、draw()
が実行されるたびにsunHeight
の値を2
ずつ減少させます。if文のブール式sunHeight > 130
がfalse
になると、sunHeight
の値は変化しなくなります。これはsunHeight
が130以下の値になったときに起こります。
変数の値が減少するとき、これはデクリメントと呼ばれ、減算代入-=
記号が使用されます。変数の値が増加するとき、これはインクリメントと呼ばれ、加算代入+=
演算子が使用されます。変数がインクリメントまたはデクリメントされるたびに、その変数に格納されている値が変更され、新しい値が同じ変数に格納されます。
以下の演算子についてさらに学ぶには、MDNリファレンスをご覧ください:=
| +=
| -=
空の色が変化するのは、redVal
とgreenVal
が徐々に変化するためです。2番目の条件文のブール式によると、sunHeight
が480未満のとき、色変更の変数が変化します:redVal
は4ずつ増加し、greenVal
は1ずつ増加します。draw()
が実行されるたびに、redVal
とgreenVal
が増加し、次回の実行時に背景色を変更するために使用されます。これによりアニメーションの日の出効果が作成されます。
文greenVal +=1
はgreenVal++
とも書くことができます。++
はインクリメント演算子と呼ばれ、--
はデクリメント演算子と呼ばれます。
以下の文は同じ効果があります:
// 1ずつインクリメント
grow++;
grow += 1;
// 1ずつデクリメント
shrink--;
shrink -= 1;
++と—についてさらに学ぶには、MDNリファレンスをご覧ください。
draw()
が最初に実行されるとき、背景は黒でsunHeight
が減少します。太陽がy座標480に達すると、redVal
とgreenVal
の値が増加するにつれて空の色が変化し始めます。太陽はsunHeight
が130に達すると動きを止めます。これは最初の条件文によるものです:
if (sunHeight > 130) {
sunHeight -= 2;
}
ここでは、draw()
が実行されるたびにsunHeight
が130より大きい限り、sunHeight
は2ずつ減少します。130以下になると、括弧内のブール式がfalse
になり、中括弧内のコードはもう実行されません。これにより、太陽のy座標が130以下になると動きが止まります。
ネストされた条件文
複数の条件を同時にテストする場合、以下のように一つの条件を別の条件の中に「ネスト」することができます:
//sunHeightが常に130より大きい場合にのみ変数が変化する
if (sunHeight > 130) {
sunHeight -=2;
//ネストされた条件
if (sunHeight < 480) {
redVal +=4;
greenVal +=1;
}
}
if文を別のif文の中に置くとき、これをネストされた条件文と呼びます。これにより、コードブロックが実行されるためには両方のブール式がtrue
である必要があります。この例では、ネストされた条件の前のコードと比較して、太陽がy値130に達すると空の色も変化を止めるという違いがあります。
上記のコードでは、sunHeight
が130より大きい場合、中括弧内のコードブロックが実行されます:
sunHeight
が2ずつ減少しますsunHeight > 130
とsunHeight < 480
の両方がtrue
である限り、redVal
とgreenVal
の値を変更するコードブロックが実行されます。
最初のif文のブール式がfalse
の場合、2番目の条件はチェックされないことに注意してください。これは、sunHeight
が130と480の間にある限り、redVal
とgreenVal
が変化することを意味します。sunHeight
が130以下になると、すべての変数が変化を止めます。この場合、sunHeight > 130
がtrue
で、かつsunHeight < 480
がtrue
でなければ、ネストされた条件文のブロックは実行されません。完成したプロジェクトの例へのリンクです。形状の輪郭を削除するためにsetup
でnoStroke()
を使用しています。
論理演算子:&&
と||
複数の条件を持つ条件文を書く別の方法は、論理演算子を使用することです。AND演算子(&&
)は、コードブロックを実行するために両方の条件がtrue
でなければならない場合に使用されます。OR演算子(||
)は、コードブロックを実行するためにいずれかの条件が真でなければならない場合に使用されます。
アニメーションの日の出スケッチのネストされた条件文を、AND(&&
)論理演算子を使用して書き直すことができます。sunHeight
が130未満かつ480より大きいことを要求するためです。以下のコードサンプルでは、演算子の両側のブール式がtrue
でなければ、そのコードブロック内のコードは実行されません:
if (sunHeight < 130 && sunHeight > 480) {
//両方の条件が真の場合に実行されるコードブロック
}
論理演算子についてさらに学ぶには、MDNリファレンスの論理AND(&&
)と論理OR(||
)をご覧ください。
試してみよう!
論理演算子を練習するために、以下のコードをdraw()
内に追加してみてください:
if (mouseIsPressed == true && sunHeight === 130) {
background(0);
}
ブール変数: mouseIsPressed
と keyIsPressed
mouseIsPressed
と keyIsPressed
は p5.js に組み込まれた特別な変数で、ブール値を含んでいます。mouseIsPressed
はキャンバス上でマウスボタンが押されているときに true
になり、そうでない場合は false
になります。keyIsPressed
はキーボードの任意のキーが押されているときに true
になり、そうでない場合は false
になります。
この例を探索して、マウスボタンが押されたときにコンソールで mouseIsPressed
に格納されている値が変化するのを確認してください。
「Try this!」チャレンジでは、sunHeight
が 130 に等しく かつ マウスボタンが押されているとき、空が暗くなります。おそらく日食を表現しているのでしょう!
mouseIsPressed
を if 文で単独で使用することもできます:
if (mouseIsPressed && sunHeight === 130) {
background(0);
}
mouseIsPressed
はすでに true
または false
の値を格納しているため、ブール式を作成するために比較演算子を使用する必要はありません。ブール式はブール値に評価され、ブール変数はブール値を格納します。条件文はコードを実行するためにブール値が true
であることだけを必要とします。mouseIsPressed
が true
であれば、条件文のコードブロックが実行されます。
mouseIsPressed
と keyIsPressed
を使用した以下の例を探索してください:
- Mouse and keys: 論理演算子を使用せずに
mouseIsPressed
とkeyIsPressed
を条件文で使用する方法を探索します。 - Clickable button: mouseIsPressed、mouseX、mouseYを使用してクリック可能なボタンを作成する例を探索します!
- Multiple keys: 複数のキーを使用してキャンバス上で変更を加える例を探索します。
詳細については、p5.js リファレンスページの mouseIsPressed
、keyIsPressed
、key
、keyCode
をご覧ください。
まとめ
これで時間制御された日の出アニメーションができました。形や色を変更してスケッチを修正してみましょう。新しい機能やインタラクションを追加してみてください。おそらく新しい条件文も追加できるでしょう。キー押下やマウス押下でアニメーションを開始するのも試してみてください。