By Layla Quiñones, Joanne Amarisa
このチュートリアルに従って、p5.jsでの変数の基本と動きの作成を学びながら、アニメーションのある風景を作成しましょう。
このチュートリアルでは以下のことを学びます:
- p5.jsのスケッチで変数を宣言、初期化、更新する
- p5.jsの図形関数で変数、演算子、random()を使用してキャンバス上に動きを作成する
- p5.jsのプロジェクトに線形およびランダムな動きを追加する
前提条件:
- 環境のセットアップ
- はじめに
- (オプション) デバッグのフィールドガイド
始める前に、以下のことができるようになっているはずです:
- p5.js Web Editorにログインし、新しいプロジェクトを保存する
- キャンバスのサイズと背景色を変更する
- 図形とテキストを追加してカスタマイズする
mouseX
とmouseY
を使用して簡単なインタラクティブ性を追加する- コードにコメントを追加する
- エラーメッセージを読んで対処する
ステップ1:開始点を選ぶ
p5.js Web Editorにログインし、以下のオプションから1つ選んでください:
- 前回のはじめてのチュートリアルを完了している場合:
- インタラクティブな風景を複製し、新しい名前を付けます。
- インタラクティブな風景を開き、Fileをクリックし、Duplicateを選択します。
- 名前を「Animated Landscape」などに変更します。
- ステップ3に進みます。
- インタラクティブな風景を複製し、新しい名前を付けます。
- 最初から始める場合:
- キャンバス上に図形やテキストを配置するのに役立つコードが含まれているこのテンプレートを使用します:
- テンプレートを複製し、新しい名前を付けます。
- このテンプレートリンクを開き、Fileをクリックし、Duplicateを選択します。
- 名前を「Animated Landscape」などに変更します。
- テンプレートを使用せずに新しいp5.jsプロジェクトを開き、「Animated Landscape」という名前を付けて保存することもできます。
ヘルパーコードを使用したい場合は、以下の行を
draw()
関数にコピーしてください://マウスのx座標とy座標をキャンバス上に表示します fill(255) //白いテキスト text(`${mouseX}, ${mouseY}`, 20, 20);
ヒント
p5.js Web EditorでPlayをクリックし、「Auto-refresh」の横にあるチェックボックスをオンにすると、プロジェクトにコードを追加するたびにキャンバスが継続的に更新されます。このボックスをチェックすると、スケッチに変更を加えるたびにPlayボタンを押す必要がなくなります。
テンプレートを複製した場合、コードは以下のようになるはずです:
text(`${mouseX}, ${mouseY}`, 20, 20);
というコード行は、マウスポインタのx座標とy座標を座標ペアx, yとして表示します。最初の数字、変数mouseXの値は、マウスポインタがキャンバス上を移動する際のx座標を表します。2番目の数字、変数mouseYの値は、マウスポインタのy座標を表します。
ヒント
このテキストを表示し続けるには、このコードがdraw()
の最後の行に表示されていることを確認してください。背景とブレンドする場合は、fill()
の値を変更してテキストの色を変更する必要があるかもしれません。座標が不要になったら、fill()
とtext()
関数の前に//
を入力します。これにより、それらの行をコメントとして隠すことで、プログラムにそれらの行をスキップするよう指示します!
忘れずに: プログラムの最後の行は}
(閉じ中括弧)であるべきです。これはdraw()
関数のブロックを閉じます。
コメントについて詳しく学ぶには、このリファレンスを参照するか、このビデオをご覧ください。
変数
変数は、スケッチで使用できる値を格納します。変数は、時間とともに変化する要素をスケッチに追加する際に非常に役立ちます。 変数は計算、メッセージ、関数の引数など、さまざまな用途に使用できます!
mouseX
とmouseY
は、p5.jsライブラリに組み込まれている変数です。これらは、マウスポインタがキャンバス上をドラッグされる際のx座標とy座標を格納します。はじめにチュートリアルでは、mouseX
とmouseY
をてんとう虫や他の絵文字のx座標とy座標として使用したインタラクティブな風景を作成しました。これにより、絵文字がキャンバス上でマウスポインタをドラッグすると追従し、アートワークをインタラクティブにすることができました!
上記のテンプレートでは、mouseX
とmouseY
を使用して、text()
関数を使ってマウスのx座標とy座標をキャンバス上に表示しています。変数はtext()
関数と文字列補間(例2)を使用してテキストと一緒にキャンバス上に表示できます。
文字列補間
はじめにでは、文字列が常に引用符(""
)で囲まれたデータ型であることを学びました。変数と文字列を一緒に使用するために、テンプレートリテラルを使用できます!テンプレートリテラルは引用符(""
)の代わりにバッククォート(“)で始まり終わります。この例のように、バッククォートの間に任意の文字を入力して文字列を生成できます。${}
プレースホルダーを使用し、中括弧内に変数名を配置することで、この例のように文字列に変数を含めることができます。
詳しくは文字列補間(例2)、テンプレートリテラル、またはp5.jsのstringリファレンスページをご覧ください!
注意
数値を含む変数は、数値が必要な場所で引数として使用できます。文字列を格納する変数を数値が必要な場所で使用すると、コンソールに"...was expecting Number for the first parameter, received string instead."
のようなエラーメッセージが表示されます。一般的なエラーとその修正方法については、デバッグのフィールドガイドのエラーメッセージセクションをご覧ください!
ステップ2:背景の風景を作成する
- 背景に色を付けます。
- 風景の形(太陽や月、山、建物、家、木など)を追加し、色を付けます。
- コードの各セクションを説明するコメントを追加します。
キャンバス上で色と形を使用する方法の詳細については、はじめにのステップ4〜6を参照してください。
コードは次のようになります:
上記のコードでは、circle()
とtriangle()
の形を使用して風景内のオブジェクトを作成し、fill()
とstroke()
を使用して形と輪郭に色を付けています。
background()
はキャンバスの背景色を変更するために使用されます。draw()
は繰り返しコードを実行します。これにより、draw()
の最後に表示される形が、近くに配置されている場合、最初に来る形と重なることができます。- 三日月は2つの
circle()
形を重ねることで作成されました。- この例では、重なる2つの円を使用して三日月を作成しています。
- 山は2つの重なる
triangle()
形を使用して作成されました(以下の図を参照)。- この例は、重なる三角形を使用してより詳細な山を作成する方法を示しています。
- 三日月は2つの
triangle()
は、キャンバス上に表示するために3つの点の位置が必要です。各点にはx座標とy座標の値があります。最初の2つの数字は最初の点のx座標とy座標(x1, y1)、次の2つの数字は次の点の座標(x2, y2)、最後の2つは最後の点の座標(x3, y3)です。
あなたの風景は上記のコードサンプルとは大きく異なる可能性があります。以下の形をスケッチで自由に使用してください(リンクをクリックして詳細を学びましょう):rect()
| triangle()
| ellipse()
| circle()
| line()
| square()
| quad()
| point()
| arc()
プロジェクトで形と色を使用する方法についてさらに学ぶには、以下のリソースをご覧ください:fill()
| stroke()
| background()
| draw()
デバッグのフィールドガイドとThe Coding Trainのこのビデオで強調されている一般的なエラーを避けるようにしてください。
ステップ3:カスタム変数を使用して形を描く
ellipse()
メソッドを使用して、キャンバスの空に白い雲を配置します。以下のテキスト行を草のコードの直下に追加します:
//雲 fill(255); ellipse(50, 50, 80, 40);
cloudOneX
という名前のカスタム変数を作成し、その中に数字50を格納します – この変数はプログラム全体を通して白い雲のx座標の値を格納します。以下のテキスト行を
setup()
の前に追加します://雲のx座標のためのカスタム変数 let cloudOneX = 50;
ellipse(50, 50, 80, 40);
のx座標をcloudOneX
変数に置き換えます。このコード行は以下のようになるはずです:
ellipse(cloudOneX, 50, 80, 40);
コードは次のようになります:
ellipse()
はキャンバス上に表示するために4つの数値が必要です。最初の2つの数字(x, y)は中心点のx座標とy座標です。最後の2つの数字は楕円のピクセル幅と高さを表します。
上記のコードでは、雲はellipse()
を使用して描かれており、cloudOneX
(数値50を格納)をx座標として、50をy座標として、幅80ピクセル、高さ40ピクセルで描画されています。
カスタム変数
カスタム変数は、後で変更可能な数値や文字列などの値を格納します。カスタム変数は変更可能な値を格納するため、キャンバス上の形のx座標やy座標、サイズを変更するのに使用できます。形のx座標やy座標が変更されると、それは動いているように見えます。このステップでは:
ellipse()
を使用して、x座標として数値50を使用して白い雲をキャンバス上に配置しました;setup();
の前にcloudOneX
という名前のカスタム変数を宣言しました- プログラムで使用するカスタム変数を作成する場合、名前を付け、キーワード
let
を使用して宣言する必要があります。 - 変数は任意の名前で宣言できますが、変数の用途を思い出すのに役立つ名前を使用するのが最適です!
- プログラムで使用するカスタム変数を作成する場合、名前を付け、キーワード
cloudOneX
に数値50を割り当てて初期化しました。- 代入演算子(
=
)を使用して変数に値を格納できます – これは特定の変数に値を割り当てます。 - カスタム変数に初めて値が格納されるとき、それを変数の初期化と呼びます。
- 代入演算子(
最後に、変数名cloudOneX
をellipse()
のx座標の引数として使用できます。cloudOneX
変数には数値50が格納されているため、数値が必要な任意の関数でcloudOneX
を引数として使用できます。ここでは、白い雲のx座標として数値50をcloudOneX
変数名に置き換えて使用しました:ellipse(cloudOneX, 50, 80, 40);
。
変数のスコープ
変数のスコープは、プログラム内でその変数を使用できる場所を説明します。カスタム変数をsetup()
とdraw()
の外部で宣言することがしばしば有用です。なぜなら、これにより変数がグローバルスコープを持つことができるからです。グローバルスコープを持つ変数は、プログラムのどこでも使用できます。グローバル変数は多くの場合、コードの最初の行で宣言されます。これはプログラマーが何が変更されているかを理解するのに役立ち、コードの保守を容易にし、コードの後半での混乱を避けるのに役立ちます。mouseX
、mouseY
、width
、height
などの組み込み変数は、p5.jsライブラリに組み込まれているため宣言する必要がなく、グローバルスコープを持っているためコードのどこでも使用できます!
他の関数(draw()
やsetup()
など)内で宣言された変数はローカルスコープを持ちます – つまり、それらが宣言されたブロックまたは関数内でのみ使用できます。setup()
で宣言された変数はdraw()
や他の関数で使用できず、draw()
で定義された変数はsetup()
で使用できません。グローバルとローカル変数のスコープのこの例をご覧ください。
カスタム変数の宣言、初期化、使用についてさらに学ぶには、これらのp5.jsリファレンスページをご覧ください:let
、numbers、strings。
アニメーションのための変数の使用
キャンバス上の形のx座標やy座標が変化すると、その形が動いているように見えます。キャンバス上に表示される任意のものの x座標やy座標の代わりに変数を使用できます。例:
cloudOneX
に格納されている値を、初期化されている値を置き換えることで変更し、キャンバス上の白い雲の変化を観察します。cloudOneX
の値が増加すると、白い雲は右に移動しているように見えます。cloudOneX
の値が減少すると、白い雲は左に移動しているように見えます。
次のステップでは、cloudOneX
の値を変更して、雲がキャンバス上で水平に移動しているように見えるようにします。
ステップ4:水平方向の動きを追加する
白い雲の下の行に、以下のコードを追加します:
//x座標をフレームカウントに設定します //左端でリセットします cloudOneX = frameCount % width
コードは次のようになります:
上記のステップでは、cloudOneX
をframeCount % width
の値に設定しました。draw()
が繰り返し実行されることを思い出してください:
frameCount
は、draw()
が実行された回数を保存する組み込み変数です。この値は、プログラムが実行されている限り増加し続けます。frameCount
に格納される値を表示するこの例をご覧ください。
width
は、createCanvas()
で定義されたキャンバスの幅を格納する組み込み変数です。この例では、width
が400でheight
が400であることがわかります。%
は剰余演算子(モジュロとも呼ばれます)です - 左側の数(frameCount
)を右側の数(400)で割り、その余りを返します。以下の表は、プログラムの実行中にframeCount
とframeCount % width
がどのように変化するかを示しています(width
が400の場合):
|
|
---|---|
0 | 0 |
100 | 100 |
300 | 300 |
400 | 0 |
500 | 100 |
700 | 300 |
800 | 0 |
cloudOneX = frameCount % width
の場合:frameCount
が400未満の場合、frameCount % width
はframeCount
の値を返します。- 例:
frameCount
が40の場合、frameCount % width
は40を返し、cloudOneX
に格納します。これにより、白い雲がx座標40に移動します。
- 例:
frameCount
が増加するにつれて、新しい値がcloudOneX
に格納され、白い雲は右に移動しているように見えます(より高いx座標)。frameCount
がwidth
と等しくなると、frameCount % width
は0を返します。これにより、雲の位置がx座標0(キャンバスの左端)にリセットされます。frameCount
がwidth
より大きくなると、frameCount % width
は再びframeCount
の値を返し始めます。- 例:
frameCount
が440の場合、frameCount % width
は40を返し、cloudOneX
に格納します。
- 例:
frameCount
がwidth
の倍数に達するたびに、frameCount % width
は0になり、雲がキャンバスの左端(x座標が0の位置)にリセットされたように見えます。
プログラムが実行されると:
cloudOneX
が宣言され、50の値で初期化されます。setup()
が実行され、幅400ピクセルのキャンバスを作成します。draw()
が最初に実行されるとき:- 背景と風景のすべての形がキャンバス上に描画されます;
- 雲がx座標
cloudOneX
(数値50を格納)で描画されます; cloudOneX
にframeCount % width
の余りが格納されます。
draw()
が2回目に実行されるとき:- 背景と風景が再び描画されると、すべての形が覆われます;
- 新しい雲が
cloudOneX
の新しい値で上に描画され、x座標0から400まで移動し、その後リセットしたように見える錯覚を作り出します; - このパターンは
draw()
が停止するまで続きます。
キャンバス上を形が移動する際のframeCount
とframeCount % width
の値を表示するこの例をご覧ください。詳細については、MDNの剰余リファレンスをご覧ください!
アニメーションとdraw()
draw()
関数は繰り返しコードを実行し、一連の静止画をアニメーション化するフリップブックのように動作します。
draw()
が背景と風景の形のコードを読み取るたびに、前回draw()
が実行されたときにキャンバス上に描画されたものを覆います。これにより、draw()
が実行されるたびにキャンバス上のものが変化すると、フリップブックの次のページをめくったかのように見えます。
- この例は、円がキャンバス上を水平に移動する際のx座標の変化を示しています。
- この例は、円がキャンバス上を垂直に移動する際のy座標の変化を示しています。
- この例は、プログラムの実行中に円のサイズが変化する様子を示しています。
- これらの例は、
draw()
関数が実行されるたびに新しい位置に新しい形が描画される様子を示しています:水平方向の動き | 垂直方向の動き | ランダムな動き- これらの例では、
draw()
が提供する「フリップブック」の錯覚を取り除くためにbackground()
が削除されています。これにより、背景がそれを覆わないため、描画されるすべての新しい形を見ることができます。
- これらの例では、
詳細については、draw()
のp5.jsリファレンスをご覧ください。
frameRate()
、frameCount
、console.log()
draw()
が実行される回数はframeCount
変数に格納され、1秒間にdraw()
が実行される回数はフレームレートとして知られています。デフォルトでは、フレームレートはコンピュータによって設定され、ほとんどのコンピュータでは約60です。これは、draw()
に表示されるコードが1秒間に約60回実行されることを示しています。
frameRate()
関数を使用して、draw()
のフレームレートを設定および表示できます。console.log()
を使用して、フレームレートとframeCount
の値をコンソールに表示できます。
詳細については、以下のp5.jsリファレンスページをご覧ください:frameRate()
| frameCount
| console.log()
ステップ5:より多くの動く雲を追加し、フレームレートを変更する
- フレームレートを15に設定してアニメーションを遅くします:
background()
の下の行にこれを追加します:frameRate(15); //フレームレートを15に設定
- ステップ4を繰り返して、異なるxとy値で風景にさらに雲を追加します。
最初の雲の下にこのテキストを追加できます:
ellipse(cloudOneX - 40, 100, 60, 20); ellipse(cloudOneX + 20, 150, 40, 10);
コードは次のようになります:
上記のステップでは、以下を追加しました:
- x座標
cloudOneX - 40
、y座標100
の2番目の雲- これにより、2番目の雲が最初の雲の40ピクセル左、20ピクセル下に描画されます。
- x座標
cloudOneX + 20
、y座標150
の3番目の雲- これにより、3番目の雲が最初の雲の20ピクセル右、70ピクセル下に描画されます。
ここでは、cloudOneX
を参照点として使用しました - キャンバス上で一緒に動く形を配置する際のガイドとして使用される点です。
- この例は、参照点(x, y)を使用して複数の形の位置を一度に変更する方法を示しています。
ステップ6:垂直方向の動きを追加する
風景に垂直方向(上下)に動く木(または他のオブジェクト)を追加します。
キャンバスに木を描きます。
雲が描かれるコードと変数が増加するコードの間にこのテキストを追加します:
//成長する木 //幹 fill("rgb(118,80,72)"); rect(40, 270, 15, 50); //葉 fill("green"); triangle(25, 270, 45, 240, 70, 270);
葉を描く三角形の頂点(240)から
frameCount % 290
を引きます -cloudOneX
に格納される値:上記の三角形のy2の値を
frameCount % 290
を引くように修正します://葉 fill("green"); triangle(25, 270, 45, 240 - frameCount % 290, 70, 270);
同じように成長する木をさらに追加します。
最初の木の下にこのテキスト行を追加します:
//幹 fill("rgb(118,80,72)"); rect(340, 330, 15, 50); //葉 fill("green"); triangle(325, 330, 345, 240 - frameCount % 290, 370, 330);
コードは次のようになります:
このステップでは、以下を行いました:
- 長方形(木の幹)と三角形(葉)で構成される木を追加しました;
- 三角形の頂点のy座標(
y2
)の値をframeCount % 290
を引くように修正しました(y2
の位置を思い出すにはtriangle()の図を参照してください):- 木の葉を成長させたいので、三角形の頂点は
draw()
が実行されるたびにキャンバス上で上に移動する必要があります。この例で見られるように、キャンバス上で上に移動する点のy座標(y2
)は減少します。 - この動きを実現するために、
y2
の値を240 - frameCount % 290
を引くように修正しました。これにより、frameCount
を290で割った余りだけy2
が減少します。 - ステップ5で見たように、
draw()
関数が実行されるたびに、frameCount % 290
が返す値は1
ずつ増加するので、y2
も変化します。
- 木の葉を成長させたいので、三角形の頂点は
詳細については、以下のp5.jsリファレンスページをご覧ください:frameRate()
| frameCount
| triangle()
ステップ7:ランダムな動きを追加する
空にランダムな位置に現れる流れ星を追加します。
lineXone
とlineYone
という2つの変数を宣言し、0
で初期化します。これらのテキスト行をsetup()
の前に追加します://流れ星のためのカスタム変数 let lineXone = 0; let lineYone = 0;
流れ星を表す線を描きます。このテキストを
frameRate(15)
の下に追加します://流れ星 stroke("yellow"); line(lineXone, lineYone, lineXone + 30, lineYone - 30);
lineXone
とlineYone
をランダムな値に設定します。このテキストをcloudOneX
がframeCount % width
に割り当てられるコード行の後に追加します://流れ星をランダムな位置に設定 lineXone = random(0, width); lineYone = random(0, height/2);
マウスポインタのx座標とy座標を表示するコード行を
draw()
の最後から削除して、最終プロジェクトを表示します。友達とシェアしましょう!
コードは以下のようになるはずです:
上記のステップでは、空の流れ星を表す線を描くために使用される2つの新しい変数、lineXone
とlineYone
を作成しました。線はline()
関数を使用して描かれます(以下の図を参照)。
line()
がキャンバス上に表示されるには4つの数値が必要です。最初の2つの数値は最初の点の座標(x1,y1)です - x1はx座標、y1はy座標です。最後の2つの数値は2番目の点の座標(x2,y2)です。x2はx座標、y2はy座標です。
詳細については、line()
のp5.jsリファレンスページをご覧ください。
このプロジェクトでは、(lineXone
, lineYone
)の点から始まる線を描きました。x1はlineXone
に格納された値、y1はlineYone
に格納された値です。線は(30
, lineXone + 30
)の点で終わります。x2はx1から30ピクセル右、y2はy1から30ピクセル上です。
x1,y1を使用してx2,y2の値を修正することで、線の両端が同じように動くことができます。これにより、lineXone
とlineYone
が変化しても、線の形を変えずにキャンバス上を移動させることができます。
random()
は最小値と最大値の間のランダムな数を生成するために使用されます。これを使用してlineXone
とlineYone
にランダムな数を再割り当てし、風景の空の中にランダムな位置に配置しました。
random()
を使用した例:
ランダムな数がどのように生成されるかについて詳しく学ぶには、random()
のp5.jsリファレンスページをご覧ください。
draw()
が実行されるとき:
- 背景が設定されます。
- 流れ星が他の風景と共にキャンバス上に配置され、
cloudOneX
が変更されます。 lineXone
が0
とwidth
の間のランダムな数に変更されます(常にキャンバス上に表示されるようにするため)。lineYone
が0
とheight
/2
の間のランダムな数に変更されます。height
/2
は、流れ星がキャンバスの上半分にのみ表示されることを示しています。
draw()
が再び実行されると、同じプロセスが発生し、流れ星はキャンバスの上半分の新しいランダムな位置に配置されます。これはdraw()
が停止するまで続きます。
エラーメッセージ
p5.jsは、理解できないコード行についてプログラマーとコミュニケーションを取るためにコンソールを使用します。これらはエラーメッセージと呼ばれます。プログラマーはこれを使用してコード内の「バグ」を見つけて修正します。詳しく学ぶには、デバッグのフィールドガイドを読むか、このビデオをご覧ください!