ゼロからEntityComponentSystemを書いてみる 6

前回は、こんなコードを書きました
```Rust:main.rs
use rand;

#[derive(Debug)]
struct Position {
    x: i32,
    y: i32,
}

#[derive(Debug)]
struct Velocity {
    x: i32,
    y: i32,
}

fn main() {
    
    // idは配列の要素数を表す
    let mut id = 0;

    // 配列をやめて、ベクタで宣言する
    // Position構造体のベクタ
    let mut pos_ary: Vec<Position> = vec![];  

    // Velocity構造体のベクタ
    let mut vel_ary: Vec<Velocity> = vec![];
    
    // 効果を確かめるために、10回 create_entity を呼び出す
    for i in 0..10 {
        // ランダムな値を取得する
        let (x, y) = rand::random();
        generic_create_entity(&mut id, &mut pos_ary, Position { x, y });
        generic_create_entity(&mut id, &mut vel_ary, Velocity { x, y });
    }


    // ベクタの要素を出力する
    for i in 0..id  {
        println!("{}: {:?}", i, pos_ary[i]);
        println!("{}: {:?}", i, vel_ary[i]);
    }
}

// ジェネリックなデータ型を引数に取る create_entity 関数
fn generic_create_entity <T> (id: &mut usize, v: &mut Vec<T>, data: T) {
    v.push(data);
    *id += 1;
}

// ジェネリックなデータ型を引数に取る set_data 関数
fn generic_set_data <T> (id: &usize, v: &mut Vec<T>, data: T) {
    v[*id] = data;
}

```

このコードは、ベクタの範囲外にアクセスしてしまう実行時エラーが発生します。

原因は、forでループするごとに２回 generic_create_entity 関数を呼び出しているからです。

generic_create_entity 関数は内部で id を +1 するようになっています。
そうすることで、id とベクタの要素数が一致するようにしていました。
しかし、２つコンポーネントを持つときに前提が崩れます。

さて、解決策は２つ考えられます。

generic_create_entity 関数の外で id を +1する。
generic_create_entiry 関数でベクタにコンポーネントを追加するのをやめる。この場合はコンポーネントを追加する関数を別に定義する。

後者を選択します。

```rust:main.rs
// ベクタにコンポーネントを追加するのをやめて、id に +1 するだけにした
fn create_entity (id: &mut usize) {
    *id += 1;
}

// ベクタにコンポーネントを追加する
fn add_component <T> (v: &mut Vec<T>, data: T) {
    v.push(data)
}
```

呼び出し側も変更します。
```rust:main.rs
    // 効果を確かめるために、10回 create_entity を呼び出す
    // ひとつのエンティティにつきコンポーネントを２つ追加する
    for i in 0..10 {
        // ランダムな値を取得する
        let (x, y) = rand::random();
        create_entity(&mut id);
        add_component(&mut pos_ary, Position { x, y });
        add_component(&mut vel_ary, Velocity { x, y });
     }

```

Cargo runをして、動くか確認します。

```terminal
0: Position { x: -660079295, y: 1825477436 }
3: Velocity { x: 1925488918, y: 867039476 }
4: Position { x: -580269154, y: 2063526753 }
4: Velocity { x: -580269154, y: 2063526753 }
5: Position { x: 814984666, y: 1106294742 }
5: Velocity { x: 814984666, y: 1106294742 }
6: Position { x: 1538517374, y: 1132620795 }
6: Velocity { x: 1538517374, y: 1132620795 }
7: Position { x: 497063939, y: -126158228 }
7: Velocity { x: 497063939, y: -126158228 }
8: Position { x: -853418764, y: 743967430 }
8: Velocity { x: -853418764, y: 743967430 }
9: Position { x: 1599348111, y: 563693441 }
9: Velocity { x: 1599348111, y: 563693441 }
```

エラーは、発生しませんでした。
めでたしめでたし、とはなりません。
というのも、Positionコンポーネントのみを持つエンティティと、Velocityコンポーネントをのみをもつエンティティの混在ができません。

例えば、こんなコードはエラーになります。

```rust:main.rs
    // ひとつのエンティティにつきコンポーネントを１つ追加する
    for i in 0..10 {
        let (x, y) = rand::random();
        create_entity(&mut id);
        add_component(&mut pos_ary, Position { x, y });
     }

     for i in 0..10 {
        let (x, y) = rand::random();
        create_entity(&mut id);
        add_component(&mut vel_ary, Velocity{ x, y });
     }
```

エラー内容は、ベクタの範囲外にアクセスするといったものです。

```terminal
0: Position { x: -140031214, y: 1932431071 }
0: Velocity { x: -1797666031, y: -1399117212 }
1: Position { x: 1807449926, y: 385782984 }
1: Velocity { x: 1789379074, y: 228539768 }
2: Position { x: 1036897023, y: 724644213 }
2: Velocity { x: 1996904484, y: -975977116 }
3: Position { x: -1873213305, y: 1334489366 }
3: Velocity { x: 1436019688, y: -270224867 }
4: Position { x: -543927070, y: -495643909 }
4: Velocity { x: 165570458, y: -1878530085 }
5: Position { x: 672617972, y: -55078610 }
5: Velocity { x: 1498926927, y: -1492524075 }
6: Position { x: -938536916, y: 482969888 }
6: Velocity { x: -733716627, y: -1553570199 }
7: Position { x: 2018722633, y: -923909018 }
7: Velocity { x: -1317984055, y: -1380790659 }
8: Position { x: 791429712, y: 58472768 }
8: Velocity { x: -1858233802, y: 10838087 }
9: Position { x: 1906118180, y: 1435231638 }
9: Velocity { x: 222468546, y: -430294130 }
thread 'main' panicked at 'index out of bounds: the len is 10 but the index is 10', src\main.rs:45:33
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\EntitiyCompornentSystem-Rust.exe` (exit code: 101)
```

次回は、これを解決します。

最後に、コードの全体を記載して終わります。
※このコードは、前述のエラーを出力します。
```rust:main.rs
use rand;

#[derive(Debug)]
struct Position {
    x: i32,
    y: i32,
}

#[derive(Debug)]
struct Velocity {
    x: i32,
    y: i32,
}

fn main() {
    
    // idは配列の要素数を表す
    let mut id = 0;

    // 配列をやめて、ベクタで宣言する
    // Position構造体のベクタ
    let mut pos_ary: Vec<Position> = vec![];  

    // Velocity構造体のベクタ
    let mut vel_ary: Vec<Velocity> = vec![];
    
    // 効果を確かめるために、10回 create_entity を呼び出す
    // ひとつのエンティティにつきコンポーネントを１つ追加する
    for i in 0..10 {
        // ランダムな値を取得する
        let (x, y) = rand::random();
        create_entity(&mut id);
        add_component(&mut pos_ary, Position { x, y });
    }

    for i in 0..10 {
        let (x, y) = rand::random();
        create_entity(&mut id);
        add_component(&mut vel_ary, Velocity{ x, y });
    }


    // ベクタの要素を出力する
    for i in 0..id  {
        println!("{}: {:?}", i, pos_ary[i]);
        println!("{}: {:?}", i, vel_ary[i]);
    }
}

// ベクタにコンポーネントを追加するのをやめて、id に +1 するだけにした
fn create_entity (id: &mut usize) {
    *id += 1;
}

// ベクタにコンポーネントを追加する
fn add_component <T> (v: &mut Vec<T>, data: T) {
    v.push(data)
}

// ジェネリックなデータ型を引数に取る set_data 関数
fn generic_set_data <T> (id: &usize, v: &mut Vec<T>, data: T) {
    v[*id] = data;
}
```