C++
Siv3D
Siv3DDay 21

Siv3D/OpenSiv3Dの便利な機能

こんにちは。この記事ではSiv3D(August2016 v2)やOpenSiv3D(v0.1.7)の便利な機能など、開発に役立つものを紹介しようと思います。

2D図形の描画

Siv3Dには星や多角形などの2D図形を描画する機能があります。

半径 200 , 回転 0 ,中心位置 { 320, 240 } の黄色い星を描画

star.cpp
Geometry2D::CreateStar(200, 0.0, { 320, 240 }).draw(Palette::Yellow);

OpenSiv3Dだと

star.cpp
Shape2D::Star(200, { 320,240 }, 0.0).draw(Palette::Yellow);

と書くことができます。
このほかにも多角形や十字形なども描画可能です。

文字のいろいろな描画方法

Siv3Dには標準で文字をある程度変化させる機能が備わっています。

font.cpp
//通常の文字
const Font font(45);
//細い文字
const Font font(45, Typeface::Light);
//太い文字
const Font font(45, Typeface::Bold);
//イタリック体
const Font font(45, Typeface::Default, FontStyle::Italic);
//ドット文字
const Font font(45, Typeface::Default, FontStyle::Bitmap);

上下左右のキーによる自機操作

Siv3DのVec2をつかえばキーボード操作で自機を動かすことが簡単にできます。
例えばこのようなものを作りたいとします。

自機の初期位置は真ん中。
上下左右のキーで1フレームに5ピクセル動く。
画面外に出ないようにする。

真ん中におきたいときは、Window::Center()という関数をつかいます。

center.cpp
Vec2 player = Window::Center();

上下左右のキーによる自機操作の場合、

before.cpp
if (Input::KeyRight.pressed)player.x += 5;
if (Input::KeyLeft.pressed)player.x -= 5;
if (Input::KeyDown.pressed)player.y += 5;
if (Input::KeyUp.pressed)player.y -= 5;

というようなコードは

after.cpp
Vec2 direction(Input::KeyRight.pressed - Input::KeyLeft.pressed, Input::KeyDown.pressed - Input::KeyUp.pressed);
if (!direction.isZero()) {
    player.moveBy(direction.setLength(5));
}

に置き換えることができます。
Input::Key○○.pressed は bool型で、true か false ,つまり 1 か 0 をかえしてくれるのでこのように書くことができるのです。
setLength(5)というのは力の大きさを5倍するという意味です。
さらに、画面外に出ないようにするには、

before.cpp
if (player.x < 0)player.x = 0;
if (player.x > 640)player.x = 640;
if (player.y < 0)player.y = 0;
if (player.y > 480)player.y = 480;

というコードでもよいですが、

after.cpp
player.x = Clamp(player.x, 0.0, 640.0);
player.y = Clamp(player.y, 0.0, 480.0);

にするとスマートになります。

以上をまとめると、

vector.cpp
Vec2 player = Window::Center();
Vec2 direction(Input::KeyRight.pressed - Input::KeyLeft.pressed, Input::KeyDown.pressed - Input::KeyUp.pressed);
if (!direction.isZero()) {
    player.moveBy(direction.setLength(5));
    player.x = Clamp(player.x, 0.0, 640.0);
    player.y = Clamp(player.y, 0.0, 480.0);
}

というようなコードになります。
OpenSiv3Dの場合は Input::Key○○.pressed を Key○○.pressed() に変えればよいです。

指定した回数繰り返す

20回繰り返す

この場合、

before.cpp
for (int i = 0;i < 20;++i) 

というふうに書いてもいいですが、

after.cpp
for (auto i : step(20)) 

このように楽に書くことができます。

長方形のグラデーション

Rect の draw( ) の第一引数には4つまで色を指定でき、指定した色でグラデーションをかけてくれます。
例えば、

gradation.cpp
Rect(0, 0, 200, 250).draw({ Palette::Blue,Palette::Cyan,Palette::Yellow });

のように、3つの色を波括弧でくくってみると、無題.png
のように斜めにグラデーションされます。
また、OpenSiv3D限定ですが、

gradation.cpp
Rect(0, 0, 200, 250).draw(Arg::top = ColorF(0.1, 1.0, 0.1, 1.0),Arg::bottom = ColorF(0.1, 1.0, 0.8, 1.0));

というふうに書けば、
無題.png
のように,上から下へグラデーションをかけることも可能です。

弾の描画(OpenSiv3D)

従来であれば

shoot.cpp
Array<Vec2> shots;
if (Input::KeyZ.clicked){
    shots.push_back(Window::Center());
}

for (auto& s : shots){
        s.y -= 8.0;
        Circle(s, 7).draw(Palette::Orange);
}

と書かなくてはなりませんでした。
しかし、OpenSiv3Dでは、

shoot.cpp
Array<Vec2> shots;
if (KeyZ.down()){
    shots.push_back(Window::Center());
}

shots.each([](Vec2& s) { s.y -= 8.0; });
shots.each([](const Vec2& s) { Circle(s, 7).draw(Palette::Orange); });

というふうに書くことができるようになりました。
この他にも、OpenSiv3DではArrayに様々な機能が実装されているので、是非調べてみてください。

開発に役立つこと

Siv3Dの開発に役立つものとして、Siv3Dのリファレンス(OpenSiv3D版はこちら)は勿論、他にもブロック崩しの解説付きコードミニサンプル集などがあります。ミニサンプルのなかに創作意欲が掻き立てられるものがあるかもしれません。また、忙しい人のためのゲームひな形 for Siv3Dなども参考にするといいかもしれません。

おわりに

「Siv3D/OpenSiv3Dの便利な機能」、いかがだったでしょうか。この記事が皆さまの役にたったら幸いです。
Siv3D/OpenSiv3Dには今回紹介したもの以外にも便利な機能がたくさんあるので、是非しらべてみてください。
そろそろ終わりが近づいてきたSiv3D Advent Calendar 2017。明日は Nicious さんの記事です。