p5.js のセットアップ
p5.js (または q5.js)の setup
関数内のコードは、プログラムが開始するときに実行されます。new Canvas()
コンストラクタは、プログラムが描画できる画面のセクションを作成します。
p5.js の draw
関数はデフォルトで 1 秒間に 60 回実行されます。background
関数は、キャンバスが描画されるたびにそれを色で塗りつぶすために使用できます。
キャンバスの幅と高さを変更してみてください(Canvas
コンストラクタ内の数字)、それから例のプログラムを再起動してみてください!
スプライトとは何ですか?
スプライトは幽霊です!
ビデオゲーム開発者は、キャラクター、アイテム、または背景の上を移動する他のものを指すために "スプライト"という単語を使用します。
new Sprite()
コンストラクタは、スプライトの位置、サイズ、および外観を定義する変数を含むスプライトオブジェクトを作成します。
下のミニ例でボックスと円のスプライトのプロパティを編集してみてください!
試してみてください!
スプライト名 ball
を直径 30 の青い円に変えて、キャンバスの右上の角に配置してみてください。
スプライトの物理
スプライトの衝突判定器は、他のスプライトとの衝突を検出するために使用されます。デフォルトでは、スプライトには 'dynamic'
の物理衝突判定器があり、スプライトが自由に移動し、重力に影響を受けることができます。
'static'
の衝突判定器は移動できません。'kinematic'
の衝突判定器はプログラム的に移動することができますが、他のスプライトによっては移動できません。また、他のキネマティック衝突判定器と衝突しません。スプライトの衝突判定器タイプを
'none'
に設定すると、物理シミュレーションからそれが削除されます。
衝突判定器のタイプは、衝突判定器のタイプ名の最初の文字を使用して設定することもできます:'d'
、's'
、'k'
、または
'n'
。
ミニ例を再生するには、右上のリロードアイコンをクリックしてください!
試してみてください!
静的な衝突判定器と円形の形状を持つスプライト名 peg
を作成してみてください。動的な衝突判定器とボックス形状のスプライト block
を作成します。ブロックを配置して、それがペグに当たって右に落ちるようにします。
p5.js の draw
関数が終了するたびに、スプライトは自動的に描画され更新されます。world
は p5play
がロードされるときに作成されますが、デフォルトでは重力はありません。world.gravity.y
を正の数に設定してみてください。
さらなるチャレンジとして、ブロックが落ちた後に元の位置にリセットしてみてください。
スプライトの移動
スプライトを直接編集して(x、y)座標を変更すると、中間の位置を移動せずに新しい位置にテレポートします。
このミニ例をクリックしてみてください。
スプライトが移動中に他のスプライトと実際に相互作用するようにしたい場合は、テレポートしないでください!
この悪い例は、p5.js の描画関数がフレームをレンダリングするたびにスプライトがテレポートされる場合の問題を示しています。
このページの他のすべての移動方法は、スプライトの x 軸と y 軸の速度を変更することで動作します。velocity
別名 vel
は p5.js の
Vector で、それには任意の Vector 関数が使用できます。
この例を見るためには、スプライトを動かすために再起動する必要があるかもしれません。
スプライトのdirection
とspeed
を設定することで、スプライトを無限に移動させます。
また、スプライトの方向を 'up', 'down', 'left', 'right', 'upLeft', 'upRight', 'downLeft', 'downRight' などの方向名を使って設定することもできます。
p5play はこれらの方向名を対応する角度値に変換することに注意してください。
move
関数は、スプライトを固定距離移動させます。移動の方向と速度は、関数のパラメータとして指定することも、別々に設定することもできます。
moveTowards
関数は、スプライトをある位置に向かって、その位置までの距離のパーセンテージだけ移動させます。
この例では、プレイヤーは p5.js の draw 呼び出し毎に、マウスまでの距離の 10%を移動します。そのスピードと、ブロックに対する力は、移動する距離に比例します。
moveTo
関数は、スプライトを一定の速度である位置に移動させるためのインパルスを生成します。
しかし、スプライトが重力のような力に作用されたり、他のスプライトにぶつかったりすると、その速度と方向が影響を受けて目的地に到達しない可能性があることに注意してください。
x と y のプロパティを持つオブジェクトを受け入れる任意の移動関数は、代わりに(x, y)の位置数値を使用して呼び出すことができます。
このページの例示が、p5play で利用可能な移動オプションの一部を理解するのに役立つことを願っています。
ただし、move
、moveTo
、および moveTowards
関数は、スプライトの現在の動きを上書きし、新たな方向に動かすことを強制します。これが必ずしも望む結果であるとは限りません!重力など、それに作用する他の力を考慮に入れてスプライトを移動させる方法を学ぶには、高度なスプライト移動に関するページを読んでください。
スプライトの画像
sprite.image
または sprite.img
は、p5.Image または画像ファイルへの URL パスに設定できます。
プログラムが開始する前に画像をロードする必要がある場合は、p5.js の preload
関数内で loadImage
を使用するのが最善です。
sprite.scale
は、スプライトの衝突判定器と視覚的な外観の両方のサイズを変更します。スケール値 2 はスプライトのサイズを 2 倍にします。
左マウスボタンを押してみてください。 sprite.debug
プロパティが true
に設定されると、スプライトの物理ボディの衝突判定器が見えます。衝突判定器のサイズを画像のサイズとは異なるサイズにすることができます!
ピクセルアート
spriteArt
関数を使用して、スプライト用のピクセルアート画像を作成できます。この関数は文字列を入力として受け取り、画像を返します。文字列内の各文字は、画像内のピクセルの色の値を表します。
spriteArt
関数への第二入力パラメータは、画像のスケールです。
試してみよう!
自分のピクセルアートを作ってみましょう!以下のアルファベットを見て、各文字がデフォルトで表す色を確認してください。
カスタムカラー
カラーパレットを作成し、spriteArt
関数への第三パラメータとして渡すことで、カスタムカラーを使ったピクセルアートを作成することもできます。
p5play のカラーパレットはJavaScript
オブジェクト形式で提供する必要があります。シンプルな JS
オブジェクトは辞書のようなものです。ピクセルアートで使用する各文字に対して色を定義することができます。色を作成するには、p5.js のcolor
関数を使用します。この関数は RGB(赤、緑、青)値または
HEX カラーコードを受け付けます。
色を見つける最も簡単な方法は、カラーピッカーを使用することです。
スプライトの作成を高速化
Sprite コンストラクタ、new Sprite()
の内部では、スプライトの位置、サイズ、衝突判定器のタイプを指定できます。
前のスプライト参照ページで見たように、スプライトを作成するために Sprite コンストラクタに何も入力を追加する必要はありません。しかし、コンストラクタでスプライトのサイズを設定したい場合は、最初にその位置を指定する必要があります。
デフォルトでは、Sprite コンストラクタに入力が与えられない場合、新しいスプライトはキャンバスの中央に位置し、幅と高さが 50 ピクセル、動的な衝突判定器が付いています。
試してみてください!
スプライトコンストラクタを使用して 2 つのスプライトを作成してみてください。
衝突
スプライトが別のスプライトと衝突する最初のフレームでは、collides
関数が true を返します。
スプライトが別のスプライトと衝突している間、colliding
関数は衝突が発生しているフレーム数を返します。
2 つのスプライトが衝突した後の最初のフレームでは、collided
関数が true を返します。
オーバーラップ
スプライトはデフォルトで衝突しますが、重なることもできます!
レイヤー
デフォルトでは、スプライトは作成された順番に描画されます。描画の順序を変更するには、スプライトの .layer
プロパティを編集します。レイヤー値が最も高いスプライトが最初に描画されます。
スプライトが別のスプライトと重なる最初のフレームでは、overlaps
関数が true を返します。
スプライトが別のスプライトと重なっている間、overlapping
関数は重なりが発生しているフレーム数を返します。
2 つのスプライトが重なった後の最初のフレームでは、overlapped
関数が true を返します。
スプライトがテレポートされたり、その位置が直接変更されたりした場合、スプライト間の物理的な相互作用、衝突や重なりを適切に検出することはできません!
試してみてください!
青いスプライトが赤いスプライトと重なっている場合に限り、赤に変わるようにしてみてください。
overlaps と collides を切り替える
デフォルトでは、2 つのスプライト間の重なりをチェックすると、それらはもはや衝突しません。スプライト間の衝突をチェックすることで、これを上書きすることができます。
この例では、スペースキーを押すと、プレイヤーは一時的に壁をすり抜けることができます。
スプライトの回転
スプライトのrotation
プロパティを直接変更すると、指定された回転角度にテレポートします。
スプライトが回転している間に他のスプライトと物理的に相互作用することを望むなら、スプライトをテレポートさせないでください!
このページの他のすべての回転方法は、スプライトのrotationSpeed
を変更することによって動作します。
rotate
関数を使用して、スプライトを指定した量だけ回転させます。
オプションの 2 つ目のパラメータは、スプライトがフレームごとに回転する速度です。
rotateTo
関数を使用して、スプライトを角度に回転させます。回転速度はオプションの 2 つ目のパラメータとして与えることができます。
また、この関数に x, y 座標を持つオブジェクトが与えられた場合、スプライトはその位置に向かって回転します。"facing"角度は、スプライトが目標位置に対面する際の角度です。これを 0 から 90 に変更してみてください。クリックすると、スプライトの長辺がマウスに向かって回転します。
rotateTowards
関数を使用して、スプライトを角度に向けて回転させるか、位置に対面するように回転させます。
オプションの 2 つ目のパラメータは、追跡速度であり、これはスプライトが各フレームで目標の回転角度に移動する距離のパーセントです。デフォルトでは 0.1(10%)です。
offset
プロパティを使用して、スプライトの物理ボディをその中心に対して移動させます。
sprite.debug
が true のとき、スプライトの中心は小さな緑色の十字線で表示されます。中心点は、スプライトの x および y
座標がある場所です。また、これは回転の中心でもあります。
移動のシーケンス化
これらの例では、ただの通常のスプライトであるTurtle
スプライトを使用しています。
それは緑色で、三角形になっていて、古典的なタートルプログラミングの見た目を持っています。
async
関数内でawait
キーワードを使用すると、次の移動を続ける前に移動が終了するのを待つことができます。これは、スプライトを順番に動かすのに便利です。
move
、moveTo
、rotate
、およびrotateTo
関数はすべて、移動が終了したときに
true に解決するPromise
を返します。
しかし、スプライトの移動が新しい移動またはスプライトの軌道を大幅に変更する衝突によって中断されると、promise は false に解決します。
スプライトを別のスプライトに追従させたい場合、moveTo
を何度も使用し、スプライトが目的地に到達するのを待たないで使うことが考えられます。しかし、パフォーマンスを向上させるためには、angleTo
関数を試してみてください。これは、スプライトと位置との間の角度を取得します。この角度は、スプライトが移動する方向を変更するために使用できます。
この例では、p5.js dist関数が使用されて、プレイヤーとその味方との間の距離を計算しています。
物理的属性
スプライトには、世界との相互作用に影響を与える物理的属性があります。これらの属性がどのように作用するかを見るために、ミニ例をご覧ください。
質量
デフォルトでは、mass
はスプライトのサイズに基づいて割り当てられます。スプライトが大きいほど、質量は多くなります。質量は手動で設定することもできます。
試してみてください!
このミニ例の一つのスプライトの質量を変更してみてください。
planck のバグ
p5play は planck 物理エンジンを使用していますが、通常は現実的に見える物理的相互作用を出力しますが、それは完全ではありません。
このミニ例では、ボールはbounciness
が 1 なので、ボールがバウンドするたびに、それはその開始位置に戻るはずです。しかし、planck
のバグにより、ボールは地面に当たるたびに増加的に高く跳ねます。
planck か p5play の将来のバージョンでバグが修正されることを願っていますが、それまではここに一つの回避策を提供します。
bounciness
のバグは、衝突体がフラットな面からバウンドするときに最も目立ちます。これは地面と衝突した後にボールの y 速度を上書きする回避策です。
この例では、ブロックが動くプラットフォームと衝突しているとき、その色は赤です。プラットフォームによって持ち上げられている間、ブロックが赤色のままであることを期待するかもしれませんが、赤と青の間で点滅します。
現実世界では、人がエレベーターに乗って上昇すると、その人がエレベーターの床と一緒に衝突すると言うでしょう。
しかし、planck では、衝突体が他の衝突体によって移動させられたとき、それらは互いに衝突し、解除されます。
もしプラットフォーマーゲームを作ろうとしているなら、衝突はスプライトがプラットフォームに立っているかどうかを確認するための信頼できる方法ではありません。私のプラットフォーマーデモをチェックしてみてください。
チェインコライダー
3 つの異なるチェインモードがあります:vertex、distance、および line。
vertex モードを使用するには、Sprite コンストラクタに頂点配列の配列を提供します。各頂点配列は[x, y]座標を含むべきです。これらのミニ例では、スプライトの(x, y)位置は小さな黒い四角で強調表示されています。
ミニ例のチェインスプライトの頂点を変更して、ボールが床に留まるようにしてみてください!
distance モードを使用するには、Sprite コンストラクタに(x, y)位置と distance 配列の配列を提供します。これらの配列は、前の頂点に対する[x, y]距離を含むべきです。(x, y)位置はチェインの最初の頂点になります。
distance モードは、超長いチェインを作成するのに最適です。
5 つの距離を追加して、地面が起伏する岩地チェイン上で転がるようにしてみてください。
line モードを使用するには、Sprite コンストラクタに(x,y)位置と線の長さと角度のリストを提供します。各角度は前の線の角度に対する相対値です。
line モードは、小さなおよび/または対称的なチェインに最適です。
line モードのチェインの(x, y)位置は、全ての頂点の平均に位置しますが、これはチェイン上の点ではないかもしれません。
これらの線の長さと角度を変更してみてください!
ポリゴンコライダー
通常のポリゴンは、スプライトコンストラクタに辺の長さとポリゴンの名前を提供することで作成できます。
使用できる名前は以下の通りです: 三角形、四角形、五角形、六角形、七角形、八角形、九角形、十角形、十一角形、十二角形。
チェーンの始点と終点が同じ点にある場合、かつ、結果として得られる形状が凸形状であれば、それは自動的にポリゴンになります!
スプライトがポリゴンであるかチェーンであるかに関わらず、始点と終点が同じ点にあるすべての物理ボディは、その(x, y)位置が形状の中心に位置することに注意してください、最初の頂点ではありません。この位置は、形状のすべての頂点を平均して計算されます。
sprite.shape = 'chain'
と設定することで、凸形状のポリゴンを強制的にチェーンにすることができます。
通常のポリゴンは、線の長さ、角度、リピートをリストにして作成することができます。
正規ポリゴンの角度の公式は 360 / n です。ここで、n は辺の数です。この角度を負にすると、ポリゴンがその辺の一つを上に向けて配置されます。
四角形のチェーンを作ってみてください!
ここには、五角星を作るコードがあります。
星が凹形状であるため、ポリゴンコライダを持つことはできないことに注意してください。
ポイントの数を変更してみてください!
これで p5play のロゴの作り方がわかります!
このような閉じたチェーンでさえ、内部は空で、線で作られています。p5play のホームページの例では、チェーンコライダが他の多くのスプライトを内包することができることがわかります!
閉じたチェーンコライダは、ダイナミックコライダとしてあまり良くないことに注意してください。これは p5play が使用している Box2D 物理エンジンの制約です。
カスタム描画
スプライトの動きに対して求める視覚効果を得るために、事前に描かれたアニメーションを使用できない場合があります。
幸いなことに、スプライトのdraw
関数をカスタマイズして、任意の表示を行うことができます!
スプライトの draw 関数内部では、スプライトの中心が位置(0, 0)に移動されることに注意してください。
このミニ例では、スプライトの楕円を移動方向に回転させ、その方向に比例して楕円を伸ばします。これはちょっと複雑です!
カスタムアップデート
また、描画ループの終わりまたは update
が呼ばれたときに実行されるスプライトのカスタムアップデート関数を定義することもできます。そこには、任意のスプライト固有の振る舞いを入れることができます。
スケール
sprite.scale
を変更すると、指定された量でスプライトのコライダーと視覚的な外観がスケーリングされます。
数字キーを押すと、スプライトがその量だけ均一にスケールします。
"d"キーを押すと、スプライトのスケールが倍になります。
"x"キーまたは"y"キーを押すと、スプライトがその方向にランダムな量だけスケールします。ただし、スプライトが不均等にスケーリングされた場合、画像は歪んでしまい、再度均一にスケーリングされてもそのままになります。
コンボコライダー
addCollider
関数を使用すると、スプライトに複数のコライダーを追加することができます。
しかし、この機能は、ゲームプレイに本当に必要なときだけ使用してください!通常、迷路の壁のように多くのコライダーを必要とするものは、それぞれが独自のコライダーを持つ複数のスプライトを作成するべきです。また、スプライトの画像が複雑でも、通常はボックスや円で物理的な相互作用には十分で、特に小さなスプライトにはそれが適しています。
しかし、時には、本当に複数のコライダーを持つスプライトを作成する必要があります。例えば、ピンボールのフリッパーをモデル化したい場合などです!
コンボセンサー
オーバーラップセンサーはスプライトが別のスプライトと重なっているかを判定します。
オーバーラップチェックのメソッドが使用されると、スプライトにセンサーがない場合、addDefaultSensors
関数が背後で使用され、スプライトの各コライダーのためにセンサーが作成されます。
addSensor
関数を使用して、スプライトに追加のセンサーを追加することができます。
高度な動作
move
関数は命令的で、スプライトの速度を上書きします。しかし、スプライトが重力などの他の力を尊重する必要がある場合はどうすれば良いでしょうか?
ベアリングとは、目的地に到達するために従う必要がある方向です。スプライトの bearing
を変更しても、その移動方向が命令的に変更されるわけではありません。
applyForce
を使い、入力パラメータとして力の量を一つ受け取ることで、力をスプライトの bearing
角で適用することができます。
この例では、ドローンは重力の力を克服して飛ばなければなりません。ドローンを飛ばし、それから落としてみてください。ドローンに再び上向きの力が加わると、落下が徐々に止まり、飛び始めます!
applyForceScaled
関数は、スプライトに適用される力をその質量で乗算します。位置は、x および y
プロパティを持つオブジェクトとして与えることもできますし、個別の x と y パラメータとして与えることもできます。
この関数を使用して、スプライトに独自の重力を与えることができます!
両方の力関数は、力を個々の x および y 成分として受け入れるか、スプライトの bearing
を設定することで量として受け入れることができます。
デフォルトでは、力はスプライトの重心に適用されます。ただし、applyForce
および applyForceScaled
関数は、最後の入力パラメータとして、x と y プロパティを持つ位置オブジェクトも受け入れることができます。この位置オブジェクトは、どこに力をスプライトに適用するかの相対位置を指定します。
attractTo
関数を使用して、位置に引き寄せる力を適用してスプライトを引き寄せることができます。
この例では、電子が原子核の周りを軌道を描いている様子をシミュレーションしています。
なお、このページで示されている高度な動作関数は、スリーピングスプライト を起こすことはありません。
トルクは回転を引き起こす力です。applyTorque
を使用してスプライトの回転に影響を与えることができます。
この例では、地面が急斜面の場所ではロボットの転がる速度が遅くなります。