Siv3Dにおけるコンテナ(Array)を使ってみる
1つ前の記事に対する補足の記事です。
konkea.hatenablog.com
自分はvector型にオブジェクトを格納し、forで1つずつ回していたのですが、コメントにて「オブジェクトの削除はErase_ifを使うといいよー」とのご指摘を受けました。
リファレンスを参考に見させていただいたところ、Erase_ifだけでなくSiv3Dにて独自に用意されている便利な型・関数がありましたので補足という形で紹介させていただきます!
参考URL
シューティングゲーム · Siv3D/Reference-JP Wiki · GitHub
コード
前回の記事のものと同じ内容ですが、使用する型・関数等を変更しています。
# include <Siv3D.hpp> struct MyCircle { private: int radius; Vec2 place; int color; public: MyCircle(int r, Vec2 p, int c) { radius = r; place = p; color = c; } void setRadius(int r) { radius = r; } void setPlace(Vec2 p) { place = p; } void setColor(int c) { color = c; } int getRadius(void) { return radius; } Vec2 getPlace(void) { return place; } int getColor(void) { return color; } bool deleteCheck(void) { return ((place.x < -20) || (place.x > 660) || (place.y < -20) || (place.y > 500));} }; void Main() { Array<MyCircle> array; int radius = 20; int count = 0; while (System::Update()) { MyCircle cir(radius, Vec2(0, 20 + 40 * (count % 12)), count * 2); array.push_back(cir); //描写および次の位置のセット for (auto& object : array) { Circle(object.getPlace(), object.getRadius()).draw(HSV(object.getColor())); object.setPlace(object.getPlace() + Vec2(6, 0)); } //オブジェクトの削除 Erase_if(array, [](MyCircle& c) { return c.deleteCheck(); }); count++; count = count % 360; } }
解説など
コンテナArrayの使用
前回まではコンテナとして型std::vectorを使っていましたが、今回はSiv3Dにて独自に定義されているArrayに変更しました。コンテナの種類を変えただけなため、動作に変わりはないはずです。対象とする型は変わらずMyCircleです。
拡張for文の利用
一般的なfor文から、拡張for文へと変更しました。これにより、コンテナのサイズを求めることなくすべての要素に対して処理が行えるようになります。拡張for文で気を付けたいのが、コンテナの中身を取ってくる方法です。渡されたコンテナの中身を1つ1つコピーし、それを変数に代入して操作するため、for文内でオブジェクト内の値の変更をする際には参照渡しをする必要があります。これがここにおける&の意味ですね。
また後の関数Erase_ifの都合上、このfor文ではオブジェクトの削除は行わずに、描写と次の位置のセットのみを行っています。
Erase_if ... Siv3D独自の便利な関数の利用
コンテナ内の特定オブジェクトの削除に、それ専用の関数Erase_if()を利用しました。第一引数にコンテナ名を指定し、第二引数に無名関数(?)でbool値を返すものを指定します。trueならば削除、falseならば何もしません。今回は構造体MyCircle内にあらかじめオブジェクト削除判定用の関数を用意してあったので、それをそのまま利用できました。
書き換えた感想
いろいろと書き換えましたが、かなり記述量が減りました!しかも、全体的な記述が無駄なくスマートになっている気がします。どことなく感じるのが、やはりコード書いてて楽しいです。この謎の魅力はなんなんでしょうかね、恐るべしSiv3D。