canvas上で炎を表現

# 前置き

プログラミング初心者のため、見苦しいコードが多いです。プログラムを組んで何か作るの好きです！

# Chill(チル)を知っていますか？
![cc3f5f3587512930a1c86ad70d3d6611be20d1eb1346760024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454421/47b7b22d-1fa2-57ad-8162-46d8cf16c905.jpeg)

最近、SNSなどを見ているとチルという言葉をよく見かけます。自分は流行に疎いのでそれが何を指すのかは分かっていませんでしたが、Youtubeのチル動画にはまったので意味を調べてみました。
> 「チル」は英語の「chill out」(チルアウト)から由来した言葉で「くつろぐ」や「まったりする」「落ち着く」といった意味の俗語で、「チルってる」「チルしてる」「チルする」「チルる」といった表現がある。

chillだけだと冷やすという意味だけどoutがつくと、穏やかな感じのイディオムになるんですね。勉強になりました。

# 身の回りに溢れるチル

![20687068_1725731127720397_2823729766333415424_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454421/264a9b5f-6c3f-d8bc-a7e3-2658fd3b437e.jpeg)

少し回りに目を向けるとチルがたくさん見つかります。

- 六畳一間の窓から見る夕焼け
- 満月が昇っている夜空
- 大晦日の焚き火

自分は自然が好きなので、自然系のチル中心ですね。今回はチルを目指してチルっぽい炎を作っていきたいと思います。リアルなのは無理なのでドット絵で。

# 炎の制作過程
canvasに描画していきます。
ドット絵なので昔のゲームとかに出てくるような炎を目標に作っていきます。

## １．炎クラスを作る

![fire1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454421/6b8d3ea7-7b8c-794b-e843-fe12b29f9643.gif)

まずはともあれ、炎を作りたいので、炎クラスを作ります。
炎クラスには以下の2つのメソッドを作ります。

- 炎の形データを元に色データを作るメソッド

```js
createData() {
    for (var x = 0; x <= 9; x++) {
        for (var y = 0; y <= 9; y++) {
            if (this.mask[x][y] == 0) // maskの値が0だったら透明のピクセル配置
            else if (this.mask[x][y] == 1) // maskの値が1だったら炎の赤い部分のピクセル配置
            else // maskの値が0,1以外だったら炎の黄色部分のピクセル配置
        }
    }
}
```

this.maskは炎の形データです。予めコンストラクタで設定しておきます。このマスクを通して、炎の色(RGBA)を設定しています。

---

- 炎の形データを元に描画するメソッド

このメソッドはsetIntervalで毎フレーム毎に呼び出されるメソッドです。canvasに炎を描画させて、アニメーションさせるメソッドですね。このメソッド内で前述のcreateDataメソッドも呼び出しているため、炎の色データも毎フレーム毎にリセットされます。

## ２．炎に揺らぎを加える

![fire2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454421/51a27fa3-3c12-49d5-8003-e6e49baf1489.gif)

風などで炎は揺らいでいます。これはどのように実装するか迷いました。物理は勉強しましたが、炎の揺らぎ方なんて数式化するのは自分じゃまだまだ無理そうです。ということで今回は一定確率でドットが透明になるようにRGBAのAlphaを設定しました。カラーコードだけで透明率を設定出来るのは便利ですね。結構それっぽくなったので満足です。

## ３．煙クラスを作る

![fire3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454421/11c95bd1-8119-5bcc-0ce2-2b3b3f6a9faf.gif)

炎があるところには必ず煙があるなと思ったので、煙が上がるようにしました。煙の色は今回は黒～灰色にしましたが、そういえば煙の色って色々ありますよね。調べてみると、水分が関係しているらしいです。水分量が少ないと黒い煙が出て、多いと白い煙が出てきます。消火作業が進むと白い煙が出てくることから分かりますね。ちなみに黒煙に成る前の黄色い状態の煙は毒性が強いそうなので覚えておくといいかもしれないですね。

## ４．草クラスを作る

![fire4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454421/76a2dd82-3f91-1d9d-7549-ba3c41978f2b.gif)

背景がないと寂しいなと思ったので、草っぽい背景を作りました。画像は使わずcanvasのメソッドだけで制作したいので、草というよりはただのボーダーですが。
これは、createPatternというメソッドを使っています。メインの物を描画しているcanvasとは別のcanvasを生成し、そこでパターンの一部となる背景を描画し、それをcreatePatternでパターン化します。出来上がったパターンはメインのcanvas上にあらかじめ設置した長方形のfillStyleに設定すると別のcanvasで描画したもので長方形を塗り潰せます。

```js
this.ctx.createPattern(result, "repeat");
```

第一引数のresultはメインとは別のcanvasです。第二引数はパターンの繰り返し方法です。repeat・repeat-x・repeat-y・no-repeatなどがあります。

## ５．光クラスを作る

![fire5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454421/d3366dc6-8317-0365-0399-31709d8d5e42.gif)

arcメソッドで円を作って、createRadialGradientでグラデーション操作をしています。毎秒ごとに外側の黄色のグラデーションの範囲と透明度をリセットしているため、きらめいている感じにしました。

# 炎の完成

<p class="codepen" data-height="430" data-theme-id="dark" data-default-tab="js,result" data-user="lizard_nest" data-slug-hash="qBBaodR" style="height: 430px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="MoveFire">
  <span>See the Pen <a href="https://codepen.io/lizard_nest/pen/qBBaodR">
  MoveFire</a> by hoihoi (<a href="https://codepen.io/lizard_nest">@lizard_nest</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

背景の草や炎の揺らぎなど色々改善点は残りましたが、とりあえず完成です。これに炎の効果音など乗っけたりしても良いかもしれません。
今回の目標は「チルっぽい炎」でした。これはどうでしょうか。
チルというより、チープな感じだ。

# 最後に

朝の電車に乗っている時間が長い。しかも、本を広げて読める程空いていない。となるとスマホしか触ることがない。ゲームは夢中になってしまうから、CodePenを触ってる。1日の隙間時間にCodePen、オススメです。ただ、凄いやりにくいです。