p5.js入門


# はじめに

この記事は[福岡明太子クラブ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/fukuoka-mentaiko-club)の１日目の記事です。

# やること

本当はprocessingを使用して、mac上で動くグラフィカルなアプリを作成したかったのですが、
processingが上手く動作しなかったので、慣れる意味も込めてp5.jsを触ってみました。

とりあえず作ってみたものがこちらです。

![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68616/7a21e8ca-b551-b087-4bc5-46c3f99e48b0.gif "sample.gif")

* ピンクの円をクリックすると選択状態になり、緑色になる
* 適当な場所をダブルクリックすると、そこに新たな円を作成して、選択した円と作成した円を線で結ぶ

# 環境

* macOS 10.15.1
* p5.js version 0.9.0

# 準備

* 適当なディレクトリに`index.html`と`sketch.js`ファイルを作成する
* `index.html`の中身は下記の通り
	* CDNは[ここ](https://cdnjs.com/libraries/p5.js/)

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>p5.js test</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
  <script src="./sketch.js"></script>
</head>
<body>
</body>
</html>
```

# 作成

ここからは`sketch.js`に記載する内容

## 準備

まず`setup`と`draw`というファンクションを用意します。

* `setup`: 開いた際に最初に１度だけ実行される処理
* `draw`: setup後に何度も繰り返し実行される処理
	* 1フレームで1回実行されるので、1秒間に60回実行される
	* 動きをつけるような処理はここに実装する


```js
// 最初に１回だけ実行される処理
function setup() {
}

// setup後に繰り返し実行される処理（フレーム単位）
function draw() {
}
```

## キャンバスの作成

`setup`内にキャンバスを作成する処理を書きます。このキャンバスのエリアが図形などを描画するエリアとなります。

```js
const canvasX = 1000;
const canvasY = 1000;

const canvasColor = 'skyblue';

function setup() {
  // キャンバスの作成
  createCanvas(canvasX, canvasY);
  // 背景色の設定
  background(canvasColor);
}
```

`index.html`をブラウザで開くと、1000px × 1000pxの水色のキャンバスが描画されます。

![sample1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68616/d817ae18-bee1-9f85-c2ca-575b09f6a7c4.png "sample1.png")

## 図形の描画

試しにいくつか図形を描画してみます。


|関数|内容|
| :-- | :-- |
|circle(x, y, d)|x, y座標を中心に直径dpxの円を描画する|
|aquare(x, y, s)|x, y座標を正方形の左上点の基準として1辺spxの正方形を描画する（他に引数あり）|

```js

function setup() {
  // キャンバスの作成
  createCanvas(canvasX, canvasY);
  // 背景色の設定
  background(canvasColor);
  
  // 円の描画
  circle(100, 100, 100);
  // 正方形の描画
  square(250, 100, 200);
}
```

するとこの様になります。

![sample2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68616/ee35a43e-06f3-329c-af3b-fe05c3188d93.png "sample2.png")


また、塗りつぶしや線は下記のように設定できます。

```js
function setup() {
  // キャンバスの作成
  createCanvas(canvasX, canvasY);
  // 背景色の設定
  background(canvasColor);

  // 図形をピンクで塗りつぶす
  fill('pink');
  // 線の色を赤にする
  stroke('red');
  
  // 円の描画
  circle(100, 100, 100);

  // 塗りつぶさない（透明になる）
  noFill();

  // 正方形の描画
  square(250, 100, 200);
}
```

![sample3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68616/0814be1b-f4fc-792f-c5ee-3f7b61e2985e.png "sample3.png")

`fill`や`stroke`などは、それ以降に描画される図形に適応されるので、それぞれ別々の設定をしたい場合、しっかりと設定する必要があります。

（この場合、`stroke('red')`が正方形にも適応されている）

詳しくは[公式のリファレンス](https://p5js.org/reference/)に載っているので、そちらを参照

## drawでの図形の描画

`draw`ファンクションではアニメーションを付けるような描画を書くことができます。

試しに円が斜めに動くような実装をしてみます。

```js
let circleX = 100;
let circleY = 100;

function setup() {
  // キャンバスの作成
  createCanvas(canvasX, canvasY);
}

function draw() {
  background(canvasColor);
  fill('pink');
  noStroke();
  
  circle(circleX, circleY, 100);
  
  circleX++;
  circleY++;
}

```

![sample4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68616/e9eea0b8-3579-549a-ece5-e37a766c579b.gif "sample4.gif")

※ gif画像なのでカクカクしていますが、実際はなめらかに移動しています。

circleX, circleYを単純に+1しているだけなので、画面外に出て消えていきます。

## イベントのハンドリング

`p5.js`にはマウス操作等のイベントのコールバックが用意されています。

```js
function setup() {
  // 省略
}

function draw() {
  // 省略
  
  // mouseIsPressedはクリックされている間trueを返す
  if (mouseIsPressed) {
    console.log("クリックされ続けている");
  }  
}

// クリックされた際に実行される
function mousePressed() {
  console.log("クリックされた！");
  
  // mouseButtonでクリックの種類がわかる
  // draw内などでも使用可能
  console.log(mouseButton);
  
  if (mouseButton === LEFT) {
    console.log('左クリック');
  }

  if (mouseButton === RIGHT) {
    console.log('右クリック');
  }
  
  // マウスの座標を取得
  console.log(mouseX);
  console.log(mouseY);  
}

// ダブルクリックされた際に実行される
function doubleClicked() {
  console.log('ダブルクリック');
}
```

# 最後に

今回は簡単に`p5.js`に触れるだけの内容となります。

次回は円をクリックしたときの色の変更や、ダブルクリックして円を追加する処理など、最初の画像になるまでの実装を行います。