円を描く関数に「ellipse」ってのがあります。もちろん標準的な使い方で
ellipse()
.x_y(230.0, 150.0)
.radius(
25.0)
.color(WHITE);
こんな書き方ですよね。
今回はmy_ellipse()という関数を作って
my_ellipse(x座標,y座標,大きさ,.....)
みたいな自分が使う専用の関数を作ってみたいともいます。
これは、円だけではなくて、他のものにも応用できます。
ellipseに設定できるもの
まずは、もともとのellipseがどんなものを引き継げるのか、見てみましょう。
公式ドキュメント見るのが速いですが、よく使う代表的なものをここでご紹介
座標や大きさ系
- x(x座標)
- y(y座標)
- x_y(x座標,y座標)
- xy(Point2)
- radius(円の大きさ)
- stroke(色)
- stroke_weight(線の太さ)
- no_fill()塗りつぶしなし
色
- color(color)
- rgb(red,gree,blue)
- hsl(hue, saturatio, lightness)
- hsv(hue, saturation, value)
という感じでね。色々あるわけです。他にもたくさんあるんですが、よく使うのはここらへんかな?
例えば、「x座標を150.0でy座標-20.0のところに大きさ15.0の赤い円を描きたい」となれば
ellipse().x_y(150.0,-20.0).radius(15.0).color(RED);
という感じになります。
もちろん色の指定は、alphaの要素を持ったhsva(hue, saturation, value, alpha)というのもあるので、半透明の円を描きたいとなると
ellipse().x_y(150.0,-20.0).radius(15.0).hsva(0.8, 1.2, 0.8, 0.5);
こんな感じになります。
円をあっちこっちに色々描きたいな。色をちょっとだけ変えて。。と思うとこれをいちいち全部描くのは面倒ですよね。
もちろんforでグルグル回す手もありますが、種類をそろえればそれなりの見た目の悪さになります。
なので、今回の本題。関数作っていきましょう
自分なりの円を描く関数my_ellipseを作る
今回の目標の関数はこちら
fn my_ellipse(draw: &Draw, x: f32, y: f32, scale: f32) {
draw.ellipse()
.x_y(x, y)
.radius(scale);
}
rustで関数を作る方法
rustの関数を作るのはいたって簡単。他の言語とそう変わりはないです。
fn 関数名(引数:型, 引数:型, …){
処理の内容
}
最低限これだけです。
返り値とか、返り値の型とかいろいろ設定することもできます。
my_ellipseの解説
もう一度自作関数my_ellipseはこのな感じ
fn my_ellipse(draw: &Draw, x: f32, y: f32, scale: f32) {
draw.ellipse()
.x_y(x, y)
.radius(scale);
}
引数
引数を見ていきましょう。
関数内では、もともとnannouにあるellipseを使っています。nannouのellipseはAppのdrawメソッドの中のellipseなので、Appかdrawを持ってないとダメです。
まずはもともとものところからdrawをもらいましょう。&Drawの形で渡してもらいます。これによって自作の関数my_ellipse内で、drawが使えるようになります。
x座標、y座標、大きさこの3つの値を渡してもらいます。これは、元々もellipseに使ってる座標や大きさの指定では、f32で指定するので、ここでもf32で値を渡してもらいます。
実装
引数が決まれば、あとは、実装していきましょう。
関数の作り方は、
fn 関数名(引数:型, 引数:型, …){
処理の内容
}
です。
それぞれ当てはめていくと
fn my_ellipse(draw: &Draw, x: f32, y: f32, scale: f32) {
//TODO
}
こんな感じになります。
TODOのところに、この引数を受けて、nannouの元々の関数ellipseに当てはめていく
draw.ellipse()
.x_y(x, y)
.radius(scale);
これで完了。
fn my_ellipse(draw: &Draw, x: f32, y: f32, scale: f32) {
draw.ellipse()
.x_y(x, y)
.radius(scale);
}
出来上がり!
使い方
例えば、座標(120.0,250.0)のところに20.0の円を描きたい。と思えば
my_ellipse(&draw, 120.0, 250.0, 20.0)
と書けばOKです。
これを普通のやり方で書くと
draw.ellipse().x_y(120.0, 250.0).radius(20.0);
こうなります。
普通に書くのもあんまり変わらなくない?
単純なものだと、あまり変わらないと思います。どっちで書いてもこの段階だと、大差ないですよね。
いくつか事例を考えてみましょう
値のキャストを伴う場合
円を描くときに、「僕は小数点なんて使わない!だから、いちいち”.0”なんて書きたくない!」としましょう。
そうなると、いちいち値をキャストしないとけないんですよね。
draw.ellipse().x_y(120 as f32, 250 as f32).radius(20 as f32);
面倒ですよね。
たくさんコードを書いていくと、型エラーがでてあれーってなっちゃいます。
そこで、自分の関数つくってしまえばいいわけです。
fn my_ellipse(draw: &Draw, x: i32, y: i32, scale: i32) {
draw.ellipse()
.x_y(x as f32, y as f32)
.radius(scale as f32);
}
こんな感じにしておけばOK
自作関数の引数ではi32で値を受けておいて、内部でf32にキャストしてあげれば、いつも使うときは何も気にせず、整数を渡せばいいんです。
2個以上の円を同時に描きたい!
my_ellipseの中は、自由に色々作れるわけです。なにも1つの円しかけないわけじゃないです。
fn my_ellipse(draw: &Draw, x: f32, y: f32, scale: f32) {
draw.ellipse()
.x_y(x, y)
.radius(scale);
draw.ellipse()
.x_y(-x, -y)
.radius(scale);
}
たとえばこうしてみましょう。
my_ellipseの中に、もう一つellipseを追加。これで、同時に2個円が描けます。座標を少しいじってみて、これは、原点対象になるようにしています。
たとば、これをさらに線で結ぶとかね。
fn my_ellipse(draw: &Draw, x: f32, y: f32, scale: f32) {
let point1 = vec2(x,y);
let point2= vec2(-x,-y);
draw.ellipse()
.xy(point1)
.radius(scale);
draw.ellipse()
.xy(point2)
.radius(scale);
draw.line()
.stroke_weight(scale/2.0)
.points(point1,point2)
.color(RED);
}
こんな感じすれば、両端に円ついた線を描くことができます。
まとめ
自分で関数をつくれるようになると、元々ある関数を自分の使いやすいように変化させることができます。さらに、最後の例のように、複雑な処理をひとまとめにして、処理できるようになります。
以上!
コメント