[Webゲーム開発入門日記③] Javascriptの主なイベント

今回はJavascriptの主なイベントを紹介&それを利用してWASDで動かせる簡易的なキャラコンを実装したいと思います。※キャラじゃなくて画像です笑
# Javascriptの主なイベント
Javascriptのイベントと言ってもありすぎて紹介しきれないので、その中のいくつかよく使うものを紹介します。
ちなみにイベントが呼ばれることを`発火`と呼ぶ
***①key関係***
`keydown`キーが押されたら発火
`keyup`キーが離されたら発火
`keypress`キーが押されたら発火(入力可能な文字だけ、shiftとかf5とかは×)
***➁click関係***
`click`クリックで発火
`dblclick`ダブルクリックで発火
***③mouse関係***
`mousedown`マウスが押されたら発火
`mouseup`マウスが離されたら発火
***④入力関係***
`input`ユーザーがテキストボックスに文字を打ち込むと発火
`change`input(テキストボックスなど)の値が変化すると発火
***⑤load関係***
`load`ページのロードが完了したら発火。ロードが完了する前に動作が行われるのを防げる。
`unload`ページが閉じられるorリロードされたとき発火
`beforeunload`ページを閉じるorリロードしようとしたときに発火。
`error`ページの読み込みでエラーが起こると発火する。
動作に対し、警告(アラート)を出すことができる。

とりあえず主要なイベントはこのぐらいですかね。
# 実践
とりあえず使ってみましょう。最初は`keydown`を使用して入力された文字を`html`の`<div>`で管理しようと思います。
新しいhtmlファイルを作成し、このコードを打ち込みましょう、
```
<html>
    <head>
        <title>
            日記③
        </title>
    </head>
    <body>
        <div id="container"></div>
            <script>
            document.addEventListener('keydown', function(e) {
                const container = document.getElementById('container');
                container.appendChild(document.createTextNode(e.key));
            });
            </script>
    </body>
</html>
```
このコードを書いたhtmlファイルを開くと押したキーが文字として表示されるサイトが表示されるはずです。できていたら成功です。
# 解説
`<div>`などは前に紹介しているので`<script>`内のみ解説します。
```
document.addEventListener('keydown', function(e)
```
この部分でeというキーが押されたら(eは変数で押したキーが入るということ)というイベントです。
```
                const container = document.getElementById('container');
                container.appendChild(document.createTextNode(e.key));
```
ここで`<div>`を指定して受け取った文字を要素として`<div>`に追加します。
if文を使用すれば押されたキーが〇〇なら...のような処理もできます。

# 簡易的なキャラコンを実装してみよう
今回作ろうとしているのはwasdで画像を自由に動かすことができる仕組みです。
***まずは仕組みを理解しよう***
当たり前ですが、キーが押されたことを検知するので`keydown`イベントを使います。
ですが、`keydown`イベントだけだと不便な点があるんです。
さっき作ったサイトでやってみればわかりますがaを長押ししながらwを長押しするとどちらか一方しか長押しされなくなってしまうんですね。
つまりwaを同時に押せない→斜めに移動できないということです。
さすがに不便すぎるのでどうにかして解決しないといけません。
ここで登場するのが`keyup`イベントです。先ほども解説した通り`keyup`イベントはキーが離されたことを検知するイベントです。
なのでkeyupが発火したらtrueに、keydownが発火したらfalseという風に管理することで、この問題を回避することができます。とにかく実践してみましょう!!
以下のコードをhtmlファイルに貼り付けます。
```
<html>
    <head>
        <title>
            日記③
        </title>
        <style>
        .img {
            position: absolute;
            width: 100px;
            height: 100px;
        }
        </style>
    </head>
    <body>
        <img src="https://rakugaki-biyori.com/images/1123/shape-simple-square-lightcoral-800x800.webp" class="img" id="img">
            <script>
                const img = document.getElementById('img');
                let w,a,s,d;
                let X = 0;
                let Y = 0;

                document.addEventListener('keydown', function(event) {
                    switch (event.key) {
                        case 'w':
                        w = true;
                        break;
                        case 'a':
                        a = true;
                        break;
                        case 's':
                        s = true;
                        break;
                        case 'd':
                        d = true;
                        break;
                        }
                });

                document.addEventListener('keyup', function(event) {
                    switch (event.key) {
                        case 'w':
                        w = false;
                        break;
                        case 'a':
                        a = false;
                        break;
                        case 's':
                        s = false;
                        break;
                        case 'd':
                        d = false;
                        break;
                        }
                });

                function updatePosition() {
                    if (w) {
                    Y = Y - 5;
                    }
                    if (a) {
                    X = X - 5;
                    }
                    if (s) {
                    Y = Y + 5;
                    }
                    if (d) {
                    X = X + 5;
                    }
                }

                setInterval(function() {
                updatePosition();
                img.style.left = `${X}px`;
                img.style.top = `${Y}px`;
                }, 10);
            </script>
    </body>
</html>
```
これでhtmlファイルを開いてみるとピンク色の正方形がwasdで動かせると思います。
このままだとどこまででも行けてしまいますが、改良すればステージの端を決めたり、移動スピードなんかも変更できたりします。

# 解説
今回はhtml,css,javascriptの3つ解説します。
***①CSS***
```
        .img {
            position: absolute;
            width: 100px;
            height: 100px;
        }
```
今回はこの部分だけでしたね。
`width`と`height`を前回もやった通り、縦と横の長さ
`position`:位置を決める。左から〇pxとかで指定できる。`absolute`にするとjavascriptから　位置の上書きが可能になる。

***➁html***
```
<img src="https://rakugaki-biyori.com/images/1123/shape-simple-square-lightcoral-800x800.webp" class="img" id="img">
```
html解説はこの部分だけですかね。
`<img>`は画像タグ、`src="ファイルパスor画像url"`とすることで画像を指定できます。
今回はwebで公開されていたフリー素材の正方形の画像urlを貼っています。

***③Javascript***
部分ごとに分けて解説していきます。
```
const img = document.getElementById('img');
```
先ほどの`<img>`タグの画像を取得しています。
```
                let w,a,s,d;
                let X = 0;
                let Y = 0;
```
w,a,s,dをグローバル変数とするために文頭で宣言。
座標を表すX,Yの初期値を0に設定。
※グローバル変数とはコード全体で共通した変数。普通変数はif文の中で書いたならif文の中のみ。のように一部でしか読み取り、再代入ができない。グローバル変数とすることでコードのどこからでも読み取りと再代入ができるようになる。グローバル変数の宣言方法はもう一つある。普通は
```
var 〇〇 = xx;
```
のように宣言するが、
```
〇〇 = xx;
```
このようにvarを省略することでグローバル変数として扱われる。しかしこの方法はあまりお勧めはしない。グローバル変数を使用したいなら文頭で宣言するのが最適。
```
                document.addEventListener('keydown', function(event) {
                    switch (event.key) {
                        case 'w':
                        w = true;
                        break;
                        case 'a':
                        a = true;
                        break;
                        case 's':
                        s = true;
                        break;
                        case 'd':
                        d = true;
                        break;
                        }
                });

                document.addEventListener('keyup', function(event) {
                    switch (event.key) {
                        case 'w':
                        w = false;
                        break;
                        case 'a':
                        a = false;
                        break;
                        case 's':
                        s = false;
                        break;
                        case 'd':
                        d = false;
                        break;
                        }
                });
```
`keydown`(押されたら)でwが押されたらwをtrueに
`keyup`(離されたら)でwが離されたらwをfalseに
という処理をしている。つまり押されている間だけtrueになる。
※switchとはif文で使用でき、()内の条件の結果をいくつかのcase(場合)に分けて処理を変更できる。
else if()では()内の条件を再記入しないといけないが、switchだと省くことができる。

```
                function updatePosition() {
                    if (w) {
                    Y = Y - 5;
                    }
                    if (a) {
                    X = X - 5;
                    }
                    if (s) {
                    Y = Y + 5;
                    }
                    if (d) {
                    X = X + 5;
                    }
                }
```
`updatePosition()`という関数を定義。
Xは左端からの距離。Yは上からの距離を表しているので
w(左方向)が押されたらXの値を減らし、左に寄せる。という処理をwasd別で行っている。

```
                setInterval(function() {
                updatePosition();
                img.style.left = `${X}px`;
                img.style.top = `${Y}px`;
                }, 10);
```
今まで紹介していなかったが、setIntervalというのは指定した間隔ごとにコードを実行するイベントである。今回の場合は10ms(0.01秒)に一回の間隔で実行している。
`updatePosition()`さっき定義した関数を呼び出す。
画像のX座標を左からX pxの位置にする(Xは変数)
画像のY座標を上からY pxの位置にする(Yは変数)
という処理をしている。

以上ですべての解説は終わりです。Javascriptの処理を要約すると、
①w,a,s,dがそれぞれ押されたらtrueにする
➁w,a,s,dがそれぞれ離されたらfalseにする。
つまり押されている間のみがtrueになる。
③0.01秒に一回値がtrueかfalseかを調べtrueの場合は座標の値を変動させる。
④0.01秒に一回座標を上の値に更新する。

# 最後に
今回の記事の内容は理解できたでしょうか？
`keydown`,`keyup`やwasdでのキャラコンはゲームを作る上ではかなり大事になってくると思うので、早めに解説しておきました。
次回は自分で作ったサイトを無料で公開する方法を紹介したいと思います。