Tonyu System 2であほげーを作ろう - その3  ターゲットと敵と

[前回](https://qiita.com/drafts/1a471a00b38576430f7e/)に引き続き，[Toyu System 2(以下Tonyu2)](https://www.tonyu.jp/)で作る [あほげー](http://ahoge.info)のテンプレートを紹介していきます．

## 記事一覧
[第1回 設定とタイトル](https://qiita.com/hoge1e3/items/388bdb47f3d56ed0789f)
[第2回 メイン画面](https://qiita.com/hoge1e3/items/1a471a00b38576430f7e)
[第3回 ターゲットと敵と](https://qiita.com/hoge1e3/items/c5d8379db1304a2897fd/)
[第4回 スコア・時間など](https://qiita.com/hoge1e3/items/e2ab8fbe03469e933022)
[第5回 ゲームを公開する](https://qiita.com/hoge1e3/items/f7bd844fd9743073190e)
[第6回 Twitterにスコアを投稿](https://qiita.com/hoge1e3/items/821e5dd1f163d3d9f3c3/)
[第7回 サウンド関係](https://qiita.com/hoge1e3/items/a5b1726f6c95bbb4e852)
[第8回 物理エンジンなど](https://qiita.com/hoge1e3/items/b2a0df1d5aaba773310f)


## 今回追加するもの

前回はプレイヤーが動くだけだったので，他の登場人物として`<<第26回のテーマ>>` と`<<テーマに関連する何か>>` を作ります．

今日のファイルはこちらです．改めて，Tonyu2はブラウザで動作しますので，次のリンクからプログラムの閲覧＆編集＆実行が可能です．(すいません，投稿した直後のプログラムはうまく開かなかったので，もう一度開いてみてください）

[今回のプログラムを開く！](https://edit.tonyu.jp/index.html?fromPrjB=ahgtmpl0.04.zip)

メニューの`実行`→`Settingを実行` を選んで， 一応，ストーリー？を見直しておきましょう

<img width="375" alt="スクリーンショット 2018-04-28 11.57.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/127248/a35f7a45-26b2-a17c-f0d6-90aeca0a3947.png">

というなんとも抽象的なストーリーですが，テーマが決まった暁には具体的になる....はずです．
とにかく，今回は`<<第26回のテーマ>>` を集めるのが目的なので，`<<第26回のテーマ>>`  のことを `Target` と名付けました．

## Targetの動作

~~~JS:Target
p=$pat_ahoge26+1;//★1
while(true) {
    x+=vx;//★2
    y+=vy;//★2
    if (screenOut()) die();
    update();
}
~~~

★1の変数`p`は，前回説明した通り，絵柄の設定を行っています．↓の絵の2番目の絵になります．

![ahoge26.png](https://qiita-image-store.s3.amazonaws.com/0/127248/c069454b-582d-d5c7-d29d-158efa0ea8cd.png)

★2では，`x+=vx;`だの，`y+=vy` だの書いてありますが，これらの変数はどこにも初期化されている様子がありません．これらは実際には`Main`クラスで値を設定しています．

~~~JS:Main
new Player{x=100,y=100};
//---今回追加分↓
while(true) {
    if (rnd(50)==0) {
        new Target{x=rnd($screenWidth),y=0,vx=0,vy=1};// ★3
    }
    if (rnd(50)==0) {
        new Enemy{x=rnd($screenWidth),y=$screenHeight,vx=0,vy=-1};
    }
    update();
}
~~~
★3のように，オブジェクトを作るときに，後ろに`{変数=値...}` という形式で変数（フィールド）の内容を初期化しています．ちなみに，ここでは次のように初期化されます．

- x は 0 以上 `$screenWidth` 未満の乱数
  -  `$screenWidth` は画面の幅を表すグローバル変数
- y は 0
- vx は 0
- vy は 1
 
★2の`x+=vx;`，`y+=vy`によって，`x`や`y`の値を`vx`や`vy`の分だけ増やすことになるので，この`Target`は次のように動きます．

- `vx`は0なのでx座標（横）は動かない
- `vy`は1なのでy座標（縦）は増える．画面上端がy=0で，yが増えるほど下に移動するので，下に移動する

`Target`の残りの部分を見ていきます：

~~~JS:Target
p=$pat_ahoge26+1;
while(true) {
    x+=vx;
    y+=vy;
    if (screenOut()) die();//★3
    update();//★4
}
~~~

- ★3は，`screenOut` メソッドにより「オブジェクトが画面外にいるか」という判定を行い，もしそうだったら `die` メソッドによりオブジェクトを消しています．
- ★4の `update`メソッドは，前回も説明した通り，このオブジェクトの1フレーム分の動作を終了させます．

## Targetとの当たり判定

`Player`クラスにて，プレイヤーがTargetに当たったら，そのTargetを取れるようにしています．

~~~JS:Player
pad=new APad;
p=$pat_ahoge26+0;
while(true) {
    x+=pad.vx*5;
    y+=pad.vy*5;
    //---今回追加分↓
    t=crashTo(Target);//★5
    if (t) {//★6
        t.die();//★7
    }
    e=crashTo(Enemy);
    if (e) {
        die();
    }
    //---------
    update();
}
~~~

- ★5 では`crashTo` メソッドを用いて，`Target`クラスのオブジェクト のうちどれかに当たっているかを判定します．
  - 当たっていたらそのオブジェクトを返します
  - 当たっていなかったら`undefined`を返します
- ★6では，★5の結果が `undefined` 以外かどうか，すなわち，当たっているオブジェクトがあったかを判定します．
  - JavaScript同様，値が`false`，`undefined`，`null`，`NaN`，`0`，空文字列の場合は`false`相当，それ以外は`true`相当になります．
- ★7では，当たったオブジェクトに対して`die`メソッドを呼び，当たったオブジェクトにを消します．

## 敵を作る．

ストーリーでは「`<<テーマに関連する何か>>` は集めるなよ！」と言っていたので，これを`Enemy`と呼びます．プレイヤーが当たったらプレイヤーが消えます．

作り方は`Target`とほとんど同じです．

~~~JS:Enemy
p=$pat_ahoge26+2;//Targetとの違いはここの絵柄だけ 
while(true) {
    x+=vx;
    y+=vy;
    if (screenOut()) die();
    update();
}
~~~

出現は`Main`で行います．Targetを出現させる方法と同じです．yは画面下,vyは-1にしているので下から出現します．

~~~JS:Main
new Player{x=100,y=100};
//---今回追加分↓
while(true) {
    if (rnd(50)==0) {
        new Target{x=rnd($screenWidth),y=0,vx=0,vy=1};
    }
    if (rnd(50)==0) {// ここでEnemy出現
        new Enemy{x=rnd($screenWidth),y=$screenHeight,vx=0,vy=-1};
    }
    update();
}
~~~

当たり判定は`Player`で行います．「当たったらプレイヤー自身が消える」という点以外は`Target`と同じです．

~~~JS:Player
pad=new APad;
p=$pat_ahoge26+0;
while(true) {
    x+=pad.vx*5;
    y+=pad.vy*5;
    //---今回追加分↓
    t=crashTo(Target);
    if (t) {
        t.die();
    }
    e=crashTo(Enemy);
    if (e) {
        die();// プレイヤー自身が消える
    }
    //---------
    update();
}
~~~

今回はここまで．[次](https://qiita.com/hoge1e3/items/e2ab8fbe03469e933022)はスコアやら体力やら時間やら，パラメータ系の作成をしていきます．