チュートリアル 変数と変化

変数と変化

By Layla Quiñones, Joanne Amarisa

このチュートリアルに従って、p5.jsでの変数の基本と動きの作成を学びながら、アニメーションのある風景を作成しましょう。

このチュートリアルでは以下のことを学びます:

  • p5.jsのスケッチで変数を宣言、初期化、更新する
  • p5.jsの図形関数で変数、演算子、random()を使用してキャンバス上に動きを作成する
  • p5.jsのプロジェクトに線形およびランダムな動きを追加する

前提条件:

始める前に、以下のことができるようになっているはずです:

ステップ1:開始点を選ぶ

p5.js Web Editorにログインし、以下のオプションから1つ選んでください:

  • 前回のはじめてのチュートリアルを完了している場合:
  • 最初から始める場合:
    • キャンバス上に図形やテキストを配置するのに役立つコードが含まれているこのテンプレートを使用します:
    • テンプレートを複製し、新しい名前を付けます。
      • このテンプレートリンクを開き、Fileをクリックし、Duplicateを選択します。
      • 名前を「Animated Landscape」などに変更します。
    • テンプレートを使用せずに新しいp5.jsプロジェクトを開き、「Animated Landscape」という名前を付けて保存することもできます。
      • ヘルパーコードを使用したい場合は、以下の行をdraw()関数にコピーしてください:

        //マウスのx座標とy座標をキャンバス上に表示します
        fill(255) //白いテキスト
        text(`${mouseX}, ${mouseY}`, 20, 20);
ヒント

p5.js Web EditorPlayをクリックし、「Auto-refresh」の横にあるチェックボックスをオンにすると、プロジェクトにコードを追加するたびにキャンバスが継続的に更新されます。このボックスをチェックすると、スケッチに変更を加えるたびにPlayボタンを押す必要がなくなります。

テンプレートを複製した場合、コードは以下のようになるはずです:

text(`${mouseX}, ${mouseY}`, 20, 20);というコード行は、マウスポインタのx座標とy座標を座標ペアx, yとして表示します。最初の数字、変数mouseXの値は、マウスポインタがキャンバス上を移動する際のx座標を表します。2番目の数字、変数mouseYの値は、マウスポインタのy座標を表します。

ヒント

このテキストを表示し続けるには、このコードがdraw()の最後の行に表示されていることを確認してください。背景とブレンドする場合は、fill()の値を変更してテキストの色を変更する必要があるかもしれません。座標が不要になったら、fill()text()関数の前に//を入力します。これにより、それらの行をコメントとして隠すことで、プログラムにそれらの行をスキップするよう指示します!

忘れずに: プログラムの最後の行は}(閉じ中括弧)であるべきです。これはdraw()関数のブロックを閉じます。

コメントについて詳しく学ぶには、このリファレンスを参照するか、このビデオをご覧ください。

変数

変数は、スケッチで使用できる値を格納します。変数は、時間とともに変化する要素をスケッチに追加する際に非常に役立ちます。 変数は計算、メッセージ、関数の引数など、さまざまな用途に使用できます!

mouseXmouseYは、p5.jsライブラリに組み込まれている変数です。これらは、マウスポインタがキャンバス上をドラッグされる際のx座標とy座標を格納します。はじめにチュートリアルでは、mouseXmouseYをてんとう虫や他の絵文字のx座標とy座標として使用したインタラクティブな風景を作成しました。これにより、絵文字がキャンバス上でマウスポインタをドラッグすると追従し、アートワークをインタラクティブにすることができました!

上記のテンプレートでは、mouseXmouseYを使用して、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()形を使用して作成されました(以下の図を参照)。
      • この例は、重なる三角形を使用してより詳細な山を作成する方法を示しています。
  • triangle()は、キャンバス上に表示するために3つの点の位置が必要です。各点にはx座標とy座標の値があります。最初の2つの数字は最初の点のx座標とy座標(x1, y1)、次の2つの数字は次の点の座標(x2, y2)、最後の2つは最後の点の座標(x3, y3)です。

3つの角の座標がラベル付けされた三角形を描いた図:(x1, y1)、(x2, y2)、(x3, y3)。図の上には三角形関数の構文が "triangle(x1, y1, x2, y2, x3, y3);" と表示されています。

3つの角の座標がラベル付けされた三角形を描いた図:(x1, y1)、(x2, y2)、(x3, y3)。図の上には三角形関数の構文が "triangle(x1, y1, x2, y2, 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つの数字は楕円のピクセル幅と高さを表します。

楕円の幅、高さ、中心点(x,y)にラベルが付いた図。図の上には楕円関数の構文が "ellipse(x, y, width, height);" と表示されています。

楕円の幅、高さ、中心点(x,y)にラベルが付いた図。図の上には楕円関数の構文が "ellipse(x, y, width, height);" と表示されています。

上記のコードでは、雲はellipse()を使用して描かれており、cloudOneX(数値50を格納)をx座標として、50をy座標として、幅80ピクセル、高さ40ピクセルで描画されています。

カスタム変数

カスタム変数は、後で変更可能な数値文字列などの値を格納します。カスタム変数は変更可能な値を格納するため、キャンバス上の形のx座標やy座標、サイズを変更するのに使用できます。形のx座標やy座標が変更されると、それは動いているように見えます。このステップでは:

  • ellipse()を使用して、x座標として数値50を使用して白い雲をキャンバス上に配置しました;
  • setup();の前にcloudOneXという名前のカスタム変数を宣言しました
    • プログラムで使用するカスタム変数を作成する場合、名前を付け、キーワードletを使用して宣言する必要があります。
    • 変数は任意の名前で宣言できますが、変数の用途を思い出すのに役立つ名前を使用するのが最適です!
  • cloudOneXに数値50を割り当てて初期化しました。
    • 代入演算子=)を使用して変数に値を格納できます – これは特定の変数に値を割り当てます。
    • カスタム変数に初めて値が格納されるとき、それを変数の初期化と呼びます。

変数の初期化と宣言のJavaScript構文の部分にラベルを付けた図:"let"は"カスタム変数を宣言するキーワード"とラベル付けされ、"変数名"は"名前"とラベル付けされ、"="は"変数名に値を割り当てる"代入演算子"とラベル付けされ、"値"は"数値や文字列などの任意のデータ型"とラベル付けされています。

変数の初期化と宣言のJavaScript構文の部分にラベルを付けた図:"let"は"カスタム変数を宣言するキーワード"とラベル付けされ、"変数名"は"名前"とラベル付けされ、"="は"変数名に値を割り当てる"代入演算子"とラベル付けされ、"値"は"数値や文字列などの任意のデータ型"とラベル付けされています。

最後に、変数名cloudOneXellipse()のx座標の引数として使用できます。cloudOneX変数には数値50が格納されているため、数値が必要な任意の関数でcloudOneXを引数として使用できます。ここでは、白い雲のx座標として数値50をcloudOneX変数名に置き換えて使用しました:ellipse(cloudOneX, 50, 80, 40);

変数のスコープ

変数のスコープは、プログラム内でその変数を使用できる場所を説明します。カスタム変数をsetup()draw()の外部で宣言することがしばしば有用です。なぜなら、これにより変数がグローバルスコープを持つことができるからです。グローバルスコープを持つ変数は、プログラムのどこでも使用できます。グローバル変数は多くの場合、コードの最初の行で宣言されます。これはプログラマーが何が変更されているかを理解するのに役立ち、コードの保守を容易にし、コードの後半での混乱を避けるのに役立ちます。mouseXmouseYwidthheightなどの組み込み変数は、p5.jsライブラリに組み込まれているため宣言する必要がなく、グローバルスコープを持っているためコードのどこでも使用できます!

他の関数(draw()setup()など)内で宣言された変数はローカルスコープを持ちます – つまり、それらが宣言されたブロックまたは関数内でのみ使用できます。setup()で宣言された変数はdraw()や他の関数で使用できず、draw()で定義された変数はsetup()で使用できません。グローバルとローカル変数のスコープのこの例をご覧ください。

カスタム変数の宣言、初期化、使用についてさらに学ぶには、これらのp5.jsリファレンスページをご覧ください:letnumbersstrings

アニメーションのための変数の使用

キャンバス上の形のx座標やy座標が変化すると、その形が動いているように見えます。キャンバス上に表示される任意のものの x座標やy座標の代わりに変数を使用できます。例:

  • cloudOneXに格納されている値を、初期化されている値を置き換えることで変更し、キャンバス上の白い雲の変化を観察します。
    • cloudOneXの値が増加すると、白い雲は右に移動しているように見えます。
    • cloudOneXの値が減少すると、白い雲は左に移動しているように見えます。

次のステップでは、cloudOneXの値を変更して、雲がキャンバス上で水平に移動しているように見えるようにします。

ステップ4:水平方向の動きを追加する

  • 白い雲の下の行に、以下のコードを追加します:

    //x座標をフレームカウントに設定します
    //左端でリセットします
    cloudOneX = frameCount % width

コードは次のようになります:

上記のステップでは、cloudOneXframeCount % widthの値に設定しました。draw()が繰り返し実行されることを思い出してください:

  • frameCountは、draw()が実行された回数を保存する組み込み変数です。この値は、プログラムが実行されている限り増加し続けます。
  • widthは、createCanvas()で定義されたキャンバスの幅を格納する組み込み変数です。この例では、widthが400でheightが400であることがわかります。
  • %は剰余演算子(モジュロとも呼ばれます)です - 左側の数(frameCount)を右側の数(400)で割り、その余りを返します。以下の表は、プログラムの実行中にframeCountframeCount % widthがどのように変化するかを示しています(widthが400の場合):

frameCount

frameCount % width

0

0

100

100

300

300

400

0

500

100

700

300

800

0

  • cloudOneX = frameCount % widthの場合:
    • frameCountが400未満の場合、frameCount % widthframeCountの値を返します。
      • 例:frameCountが40の場合、frameCount % widthは40を返し、cloudOneXに格納します。これにより、白い雲がx座標40に移動します。
    • frameCountが増加するにつれて、新しい値がcloudOneXに格納され、白い雲は右に移動しているように見えます(より高いx座標)。
    • frameCountwidthと等しくなると、frameCount % widthは0を返します。これにより、雲の位置がx座標0(キャンバスの左端)にリセットされます。
    • frameCountwidthより大きくなると、frameCount % widthは再びframeCountの値を返し始めます。
      • 例:frameCountが440の場合、frameCount % widthは40を返し、cloudOneXに格納します。
    • frameCountwidthの倍数に達するたびに、frameCount % widthは0になり、雲がキャンバスの左端(x座標が0の位置)にリセットされたように見えます。

プログラムが実行されると:

  • cloudOneXが宣言され、50の値で初期化されます。
  • setup()が実行され、幅400ピクセルのキャンバスを作成します。
  • draw()が最初に実行されるとき:
    • 背景と風景のすべての形がキャンバス上に描画されます;
    • 雲がx座標cloudOneX(数値50を格納)で描画されます;
    • cloudOneXframeCount % widthの余りが格納されます。
  • draw()が2回目に実行されるとき:
    • 背景と風景が再び描画されると、すべての形が覆われます;
    • 新しい雲がcloudOneXの新しい値で上に描画され、x座標0から400まで移動し、その後リセットしたように見える錯覚を作り出します;
    • このパターンはdraw()が停止するまで続きます。

キャンバス上を形が移動する際のframeCountframeCount % widthの値を表示するこの例をご覧ください。詳細については、MDNの剰余リファレンスをご覧ください!

アニメーションとdraw()

draw()関数は繰り返しコードを実行し、一連の静止画をアニメーション化するフリップブックのように動作します。

draw()が背景と風景の形のコードを読み取るたびに、前回draw()が実行されたときにキャンバス上に描画されたものを覆います。これにより、draw()が実行されるたびにキャンバス上のものが変化すると、フリップブックの次のページをめくったかのように見えます。

  • この例は、円がキャンバス上を水平に移動する際のx座標の変化を示しています。
  • この例は、円がキャンバス上を垂直に移動する際のy座標の変化を示しています。
  • この例は、プログラムの実行中に円のサイズが変化する様子を示しています。
  • これらの例は、draw()関数が実行されるたびに新しい位置に新しい形が描画される様子を示しています:水平方向の動き | 垂直方向の動き | ランダムな動き
    • これらの例では、draw()が提供する「フリップブック」の錯覚を取り除くためにbackground()が削除されています。これにより、背景がそれを覆わないため、描画されるすべての新しい形を見ることができます。

詳細については、draw()のp5.jsリファレンスをご覧ください。

frameRate()frameCountconsole.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も変化します。
      • draw()が実行される前、y2240です。
      • draw()が最初に実行されるとき、frameCount % 290からの値は1で、y2239になります。
      • draw()が2回目に実行されるとき、frameCount % 290からの値は2で、y2238になります。
      • draw()が3回目に実行されるとき、frameCount % 290の値は3で、y2237になります。
      • frameCountが290の倍数になると、frameCount % 290の値は0になり、y2は元の値240に戻ります。
      • このパターンはdraw()が停止するまで続きます。

詳細については、以下のp5.jsリファレンスページをご覧ください:frameRate() | frameCount | triangle()

ステップ7:ランダムな動きを追加する

  • 空にランダムな位置に現れる流れ星を追加します。

    • lineXonelineYoneという2つの変数を宣言し、0で初期化します。これらのテキスト行をsetup()の前に追加します:

      //流れ星のためのカスタム変数
      let lineXone = 0;
      let lineYone = 0;
  • 流れ星を表す線を描きます。このテキストをframeRate(15)の下に追加します:

    //流れ星
    stroke("yellow");
    line(lineXone, lineYone, lineXone + 30, lineYone - 30);
  • lineXonelineYoneをランダムな値に設定します。このテキストをcloudOneXframeCount % widthに割り当てられるコード行の後に追加します:

    //流れ星をランダムな位置に設定
    lineXone = random(0, width);
    lineYone = random(0, height/2);
  • マウスポインタのx座標とy座標を表示するコード行をdraw()の最後から削除して、最終プロジェクトを表示します。

  • 友達とシェアしましょう!

コードは以下のようになるはずです:

上記のステップでは、空の流れ星を表す線を描くために使用される2つの新しい変数、lineXonelineYoneを作成しました。線はline()関数を使用して描かれます(以下の図を参照)。

線の端点(x1,y1)と(x2, y2)を示す図。線関数の構文が図の上に "line(x1, y1, x2, y2);" と表示されています。

線の端点(x1,y1)と(x2, y2)を示す図。線関数の構文が図の上に "line(x1, y1, x2, y2);" と表示されています。

line()がキャンバス上に表示されるには4つの数値が必要です。最初の2つの数値は最初の点の座標(x1,y1)です - x1はx座標、y1はy座標です。最後の2つの数値は2番目の点の座標(x2,y2)です。x2はx座標、y2はy座標です。

詳細については、line()のp5.jsリファレンスページをご覧ください。

このプロジェクトでは、(lineXone, lineYone)の点から始まる線を描きました。x1lineXoneに格納された値、y1lineYoneに格納された値です。線は(30, lineXone + 30)の点で終わります。x2はx1から30ピクセル右、y2はy1から30ピクセル上です。

x1,y1を使用してx2,y2の値を修正することで、線の両端が同じように動くことができます。これにより、lineXonelineYoneが変化しても、線の形を変えずにキャンバス上を移動させることができます。

  • x1,y1が変化するにつれて線がキャンバス上を移動する様子を示すこの例をご覧ください。
  • 点間の距離が変化するにつれて線が変化する様子を示すこの例をご覧ください。

random()は最小値と最大値の間のランダムな数を生成するために使用されます。これを使用してlineXonelineYoneにランダムな数を再割り当てし、風景の空の中にランダムな位置に配置しました。

random()を使用した例:

ランダムな数がどのように生成されるかについて詳しく学ぶには、random()のp5.jsリファレンスページをご覧ください。

draw()が実行されるとき:

  • 背景が設定されます。
  • 流れ星が他の風景と共にキャンバス上に配置され、cloudOneXが変更されます。
  • lineXone0widthの間のランダムな数に変更されます(常にキャンバス上に表示されるようにするため)。
  • lineYone0height/2の間のランダムな数に変更されます。
    • height/2は、流れ星がキャンバスの上半分にのみ表示されることを示しています。

draw()が再び実行されると、同じプロセスが発生し、流れ星はキャンバスの上半分の新しいランダムな位置に配置されます。これはdraw()が停止するまで続きます。

エラーメッセージ

p5.jsは、理解できないコード行についてプログラマーとコミュニケーションを取るためにコンソールを使用します。これらはエラーメッセージと呼ばれます。プログラマーはこれを使用してコード内の「バグ」を見つけて修正します。詳しく学ぶには、デバッグのフィールドガイドを読むか、このビデオをご覧ください!

次のステップ

前のステップ

リソース