p5.playでテキストがオーバーフローしない角丸吹き出しを作る

[Canvasでテキストがオーバーフローしない角丸吹き出しを作る](https://qiita.com/horikeso/items/95595f379a8dfa63c34a) の記事に触発されて、p5.playのスプライトが「しゃべる（フキダシ）」を作ってみようと思いました。

# この記事を読むには

下記のQiita記事を目通ししておいてください。
[p5.play のSpriteクラスを継承させたい](https://qiita.com/harhid/items/350ac45192d2204dc247)

# 目標

- p5.Play のSprite が「フキダシ」を出せるようにしたい。
- Scratch3 風のフキダシを目指したい。

# 元記事でのコードを参考に作りなおし

context.arc() / context.lineTo()を駆使して フキダシの形を作っています。
せっかく p5.js を使うのですから p5.js の機能だけで フキダシを書いてみようと思いました。

## 元記事コードとの主な相違点

元記事では 吹き出しは上方向に向いていますが、Scratch3 のフキダシ風にしたかったので、下に伸びるように変更しています。

また、元記事コードでは フキダシエリアの周囲に枠線が見えないので、Scratch3風に 灰色の枠線をつけました。

## さらに改良したこと

吹き出しの中に絵文字を表示しようとすると、絵文字の文字カウントが狂うため、ちゃんと文字数を数えられるようにしています。

参考： [JavaScript: 文字数を正確にカウントするには？](https://qiita.com/suin/items/3da4fb016728c024eaca)


# 吹き出しの作り方

## STEP 1

テキスト部の形を作ります。
- 枠線無し
- 白色で塗ります。
```
      p.stroke(255,255,255);
      p.fill(255,255,255);
      p.arc(_x, _y, radius, radius, 180, 270, p.PIE); // 左上
      p.arc(_x+rectW, _y, radius, radius, 270, 0, p.PIE); // 右上
      p.arc(_x+rectW, _y+d, radius, radius, 0, 90, p.PIE); // 右下
      p.arc(_x, _y+d, radius, radius, 90, 180, p.PIE); // 左下
      p.rect(_x,_y-radius/2,rectW,rectH);
      p.rect(_x-radius/2,_y,rectW+radius,d);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/714ba12a-e357-9500-3187-7daa1b5922e5.png)

## STEP 2

吹き出し部を作ります。（下に伸びる三角形のことです）
- 枠線無し
- 白色で塗ります。

```
      p.triangle(_x, _y+d+radius/2, _x+30, _y+d+radius/2, _x-radius/2, _y+d+radius/2+20)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/f82d0e78-2120-3e53-c4ee-93056ddae3cd.png)

## STEP 3

テキスト部の上に枠線を書き込みます。
- 枠線の色は灰色で。

```
      p.strokeWeight(2)
      p.stroke(100);
      p.noFill();
      
      p.arc(_x, _y, radius, radius, 180, 270, p.OPEN); // 左上
      p.arc(_x+rectW, _y, radius, radius, 270, 0, p.OPEN); // 右上
      p.arc(_x+rectW, _y+d, radius, radius, 0, 90, p.OPEN); // 右下
      p.arc(_x, _y+d, radius, radius, 90, 180, p.OPEN); // 左下
      
      p.line(_x-radius/2, _y, _x-radius/2, _y+d);  // 左辺
      p.line(_x, _y-radius/2, _x+rectW, _y-radius/2);  // 上辺
      p.line(_x+rectW+radius/2, _y, _x+rectW+radius/2, _y+d);  // 右辺
      p.line(_x+30, _y+d+radius/2, _x+rectW, _y+d+radius/2); // 底辺
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/072f59c5-343a-8ab8-8910-955d90f6b20b.png)

枠線を見やすくするために、背景を 薄い灰色にしています。

## STEP 4

吹き出し部の上に枠線を書き込みます。

- 枠線の色は灰色で。

```
      const pointVertex = p.createVector(_x-radius/2, _y+d+radius/2+20);// 三角形の頂点
      const pointLeft = p.createVector(_x, _y+d+radius/2);// 三角形の底辺左
      const pointRight = p.createVector(_x+30, _y+d+radius/2);// 三角形の底辺右
      p.line(pointLeft.x, pointLeft.y, pointVertex.x, pointVertex.y); 
      p.line(pointRight.x, pointRight.y, pointVertex.x, pointVertex.y);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/92e6d3eb-f081-4972-7f87-599273a6b0a9.png)

枠線を見やすくするために、背景を 薄い灰色にしています。

## STEP 5

ふきだしエリアの中に、よい感じで文字を書き込む

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/e7214d91-534a-f7e4-9ab2-02cc8dd99afd.png)

# コード

GitHub をみてください。(js/p5PlaySpriteFukidashi.js)
[amami-harhid/p5playFukidashi](https://github.com/amami-harhid/p5playFukidashi)

# サンプル公開

動くサンプルを公開します( p5Editor )
[フキダシのサンプル](https://editor.p5js.org/amami-harhid/full/1qOCEC-Js)

` p.world.gravity.y ` を 1 としていますので、ゆっくりと落ちていきます。
キャンバスの下には「床」を作っていて「床」にふれたらフキダシを変化させています。


絵文字をちゃんと表示していることも見てくださいね。

```
        let _fukidashi = [
          "💛💛💛💛💛💛💛💛💛💛💛💛\n",
          "💚💚💚着地したよ!💚💚💚\n",
          "💻👨🏻‍💻👨👨🏻👨🏻‍💻👨🏻‍🏫👨🏻‍🎓👩🏻‍🎓👩🏽‍🎓👩‍🎓👩‍👧💛",
        ];

```

![p5play_pico37.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/0e945b1d-747c-58b5-9618-f648bd762c6e.gif)