Rust + Entity Component System で仕様変更に強いゲーム設計 その４−１ 〜 剣を表示

## 目次

[その１ 〜 序文](https://qiita.com/mas-yo/items/e7d1e247e5d4a9f47e92)
[その２ 〜 キャラの移動](https://qiita.com/mas-yo/items/207244f04dd442cb567c)
[その３−１ 〜 コンポーネントの設計](https://qiita.com/mas-yo/items/e1f89bea5f84b7041462)
[その３−２ 〜 システムの設計](https://qiita.com/mas-yo/items/ca97fe6ed961d77be715)
[その３−３ 〜 メイン部分](https://qiita.com/mas-yo/items/9f0459dd942a874c6273)
【イマココ】[その４−１ 〜 剣を表示](https://qiita.com/mas-yo/items/daae411935d138d85c95)
[その４−２ 〜 アニメーションコンポーネント](https://qiita.com/mas-yo/items/678d775e4caf5e14abe7)
[その４－３ 〜 アニメーションを動かす](https://qiita.com/mas-yo/items/3db0a920cb76c75bca51)
[その５－１～ あたり判定](https://qiita.com/mas-yo/items/598ed52f5c08a0375ead)
[その５－２～ やられアニメーション](https://qiita.com/mas-yo/items/cf017ac1ebdd7ce25d86)
[その６ 〜 これまでの振り返り](https://qiita.com/mas-yo/items/22ead1dc226da4df54e2)


## 前回まで

前回、その３まででは、エンティティを管理する仕組みを実装し、プレイヤーキャラと敵キャラを動かすところまでやりました。
その４では、キャラをアニメーションさせる仕組みを実装して、

- 何も操作していないときは待機アニメーション
- スペースキーを押すと、攻撃アニメーション

が動くようにしてみましょう。
その４も長くなりそうなので、何回かに分けて投稿します。

## 今回つくったもの

![game-step4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227302/0a640f22-ce24-30c1-f9fb-d1a2278bc551.gif)


上図の様になりました。
待機アニメーションとしては、円が一定間隔で縮小拡大を繰り返す様ににしました。
円のところから伸びている線は、剣です。
剣は、今のキャラの向きを表すと共に、攻撃すると左右に動きます。（こういうの見た事ある！）

ソースはこちら
https://github.com/mas-yo/rust-ecs-game/tree/step-4


## スケール変化と剣の表示

円のスケール変化と、剣を表示するため、`CharacterView` コンポーネントに以下のメンバを追加します。

- 現在向いている方向を示す `direction`
- 武器の方向を示す `weapon_direction`
- 円の半径に対するスケール値 `radius_scale`


```Rust

pub(crate) struct CharacterView {
    pub position: Vector,
    pub direction: f32,     //追加
    pub radius: f32,
    pub radius_scale: f32,  //追加
    pub color: Color,
    pub weapon_direction: f32,  //追加
}
```

これを表示するための `System` は、


```Rust
impl SystemProcess for System<Window, CContainer<CharacterView>> {
    fn process(window: &mut Self::Update, views: &Self::Refer) {
        views.iter().for_each(|(_, view)| {

            //半径にスケールをかける
            window.draw(
                &Circle::new(
                    (view.position.x, view.position.y),
                    view.radius * view.radius_scale,
                ),
                Col(view.color),
            );

            //現在の向き＋武器の向きの方向に線を引く
            let dir = view.direction + view.weapon_direction;
            let line_end = (
                view.position.x + dir.cos() * view.radius * 1.8f32,
                view.position.y + dir.sin() * view.radius * 1.8f32,
            );
            window.draw(
                &Line::new((view.position.x, view.position.y), line_end),
                Col(view.color),
            );
        });
    }
}
```

これで表示の準備が整いました。

ひとまず、現在の進行方向が`CharacterView::direction`が反映されるようにします。

```Rust
impl SystemProcess
    for System<CContainer<CharacterView>, (&CContainer<Position>, &CContainer<Velocity>)>
{
    fn process(views: &mut Self::Update, pos_vel: &Self::Refer) {
        views
            .iter_mut()
            .zip_entity2(pos_vel.0, pos_vel.1)
            .for_each(|(view, pos, vel)| {
                view.position.x = pos.x;
                view.position.y = pos.y;
                if vel.x != 0f32 || vel.y != 0f32 {
                    view.direction = vel.y.atan2(vel.x);
                }
            });
    }
}
```

`CharacterView`の更新処理は、前回まで`Position`だけに依存する形になっていました。
今回は`direction`の更新のために、`Velocity`も参照するようにしました。


```Rust:変更前
impl SystemProcess for System<CContainer<CharacterView>, CContainer<Position>>
```


```Rust:変更後
impl SystemProcess
    for System<CContainer<CharacterView>, (&CContainer<Position>, &CContainer<Velocity>)>
```



これでひとまず、剣が表示されていて、キャラの進行方向に表示される様になりました。

次回から、アニメーションの実装に入って行きます。