structとimplを使って跳ね返るボールをいっぱい作る

nannou

跳ね返るボールは、ピンボールやブロック崩しで使えるねって話で、rust nannouで跳ね返るボールの描画についてはこちらの記事で書きました

跳ね返るボールの描画の考え方や求め方はこちらをご覧ください

今回は、この記事を元にさらにプログラムを拡張して、複数の跳ね返るボールの描画に挑戦していきます。

構造体structとimplでメソッドを使ってボールを定義する

複数のボールを制御するためにいくつか方法がありますが、今回はstructとimplを使います。

言語仕様の細かい話は今回はしませんが、他の言語でいうところのclassのような役目をすると思ってください。

ボールのstructを作る

まず、ボールにstructを作りましょう。

跳ね返るボールに必要だったのは、ボールのxy座標とxy方向の速度の情報でしたね。

それを踏まえてball structのソースを書いてみましょう。

struct Ball {
     position: Vector2,
     velocity: Vector2,
 }

positionがボールの座標、velocityがボールの速度です。変数の型はVector2。

Vector2は(x,y)二つの要素を持つ型です。

ボールstructのimplを作る

さて、ボールを構成する要素が決まったので、ボールに機能を持たせましょう。そこで出てくるのがimpl

impl Ball {
     pub fn new(p: Vector2, v: Vector2) -> Self {
         let position = p;
         let velocity = v;
         Ball { position, velocity }
     }
 }

ボールを作るときnewするメソッドを定義してます。

これで、最低限の機能、newという座標(x,y)、速度(vx,vy)の情報を持つボールオブジェクトを作ることができるようになりました。

ボールオブジェクトの生成と描画

ボールについて、構造体とメソッドを作ることができました。

これを使って、座標の更新や跳ね返り処理、描画をやっていきましょう。

ボールのインスタンス化

ボールの構造体を作ったので、それを実体化させましょう。

ボールを複数個描画するためにnannouのModelにボールの情報を保管する場所を定義します。

struct Model {
     balls: Vec<Ball>,
 }

ballsの中にベクタ型で構造体Ballを収納していきます。

次にmodel関数に移ってballを生成していきましょう

ballの作り方は、Ball::new(position,velocity)っていう風にやります。

const N_BALLS: usize = 100;
fn model(app: &App) -> Model {
....
....
    let mut balls = Vec::new();
    for _i in 0..N_BALLS {
         let ball = Ball::new(
             pt2(random::() * 100.0, random::() * 100.0),
             pt2(random_range(-1.1, 1.1), random_range(-1.1, 1.1)),
         );
         balls.push(ball);
    }
    Model { balls }
}

const N_BALLSでボールの数を指定

あとは、ボールの数分だけforを回してballを生成して、ballsの中にballを収納していきます

座標更新と跳ね返り処理

ballが出来上がったら、それぞれのボールの座標更新と跳ね返り処理を計算していきます。

update関数に移動して

fn update(app: &App, model: &mut Model, _update: Update) {
     let speed = 4.0;
     let win = app.window_rect();
   for ball in model.balls.iter_mut() {
         if ball.position.x > win.right() || ball.position.x < win.left() {
             ball.velocity.x *= -1.0;
         }
     if ball.position.y > win.top() || ball.position.y < win.bottom() {
             ball.velocity.y *= -1.0;
         }
         ball.position += ball.velocity * speed ;
     }
}

行ってる処理は一個のボールの移動と跳ね返りの処理と同じです。

それが複数個存在するので、存在する分だけforを使って計算していく感じです。

ballっていう構造体を作ったのでドット”.”で情報を呼び出してこれるようになったぐらいです。

ボールの描画

最後に描画処理です。

これも実際行うことは、1個の時とほぼ一緒です。ただ、個数分だけ情報を取り出して描画するということだけ

fn view(app: &App, model: &Model, frame: Frame) {
     let draw = app.draw();
     let win = app.window_rect();
     draw.rect().wh(win.wh()).rgba(0.0, 0.0, 0.0, 0.2);
     for ball in model.balls.iter() {
         draw.ellipse().xy(ball.position).radius(10.0).color(WHITE);
     }
     draw.to_frame(app, &frame).unwrap();
 }

for文でballsの中に入っているball要素を取り出してきて、それについて描画していく感じです。

これで大量のボールを描画することができました。

まとめ

今回は構造体structと実装implを使って、ボールを定義して、そして、描画するという処理をrust nannouを使って行いました。

メソッドが今回はnewだけでしたが、例えば加速とか減速とかそういうメソッドを実装することも可能です。それについては、また、解説していこうと思います。

ひとまず、最低限のメソッドを持ったボールを定義することそして描画することができました。

他の言語だとclassっていうので行うことをrustでは構造体structと実装implで行うっていうことで、戸惑うこともありますが、こういうケースを使って慣れていくといいかなと思います。

ではまた!

コメント

  1. […] structとimplを使って跳ね返るボールをいっぱい作る跳ね返るボールは、ピン… […]

タイトルとURLをコピーしました