OpenSiv3DのTransitonで滑らかにトランジションさせる

OpenSiv3Dの新機能*1であるTransitonを使うと画像の切り替えなどが滑らかにできるようになります。イージングも簡単に扱えてすごいですね。

今回はこのTransiton機能を公式のリファレンスと自作のサンプル片手に解説したいと思います。

f:id:movementi:20180202194014j:plainf:id:movementi:20180202194013j:plain
自作の昼と夜を滑らかに切り替えるプログラム

目次

公式のリファレンス

scrapbox.io

Transitonを使うと、瞬間的ではなく滑らかにハイライトさせられます

マウスオーバーで図形をハイライト - Siv3D - Scrapbox

ハイライトっていい響きですね。画像の切り替えなんて言ってる自分との語彙力の差をビンビンに感じます。*2

※追記(2018/03/01)

ご指摘を受けハイライトからトランジションにタイトル変えました。全部は書き直してないのでいい感じに読み直してもらえると幸いです。


環境

OpenSiv3D Ver0.2.0及びWindows10です。
OpenSiv3Dはまだ開発途中なのでバージョンが進むとコードをコピペしても動かない可能性があります。ご了承ください。

コード全文

# include <Siv3D.hpp>
void Main()
{
    const Texture sun(Emoji(U"🌞"), TextureDesc::Mipped);
    const Texture moon(Emoji(U"🌝"), TextureDesc::Mipped);
    const Texture tree(Emoji(U"🌳"), TextureDesc::Mipped);
    
    Transition transition(0.3s, 0.301s);

    while (System::Update())
    {
        transition.update(MouseL.pressed());

        //空
        Rect(0, 0, Window::Size()).draw(ColorF(U"#41A7FF").setA(transition.value()));
        Rect(0, 0, Window::Size()).draw(ColorF(U"#181991").setA(1.0-transition.value()));

        //大地
        Rect(0, 300, Window::Size()).draw(ColorF(U"#95EB00").setA(transition.easeIn(Easing::Sine)));
        Rect(0, 300, Window::Size()).draw(ColorF(U"#207720").setA(1.0 - transition.easeIn(Easing::Sine)));

        //木
        tree.drawAt(200, 300, ColorF(transition.value()*0.6+0.4));

        //月と太陽
        sun.drawAt(100, 100, AlphaF(transition.value()));
        moon.drawAt(Window::Width() - 100, 100, AlphaF(1.0-transition.value()));
    }
}

このコードをそのままコピーアンドペーストすれば使えます。
なおTransitionはOpenSiv3Dの新機能のため旧Siv3Dのプロジェクトにコピーアンドペーストしても使えません。ご注意ください。

解説

絵文字テクスチャの準備

const Texture sun(Emoji(U"🌞"), TextureDesc::Mipped);
const Texture moon(Emoji(U"🌝"), TextureDesc::Mipped);
const Texture tree(Emoji(U"🌳"), TextureDesc::Mipped);

絵文字のテクスチャを用意します。
Texture型コンストラクタに画像のファイルパスの代わりにEmoji(好きな絵文字)を入れて初期化します。

旧Siv3Dではワイド文字のL""だったものがUTF32リテラルU""に変わっているので注意。 絵文字機能のおかげでグラフィカルなことが絵を用意しなくてもできてホント便利ですねぇ。

Transition型のインスタンスを作成

Transition transition(0.3s, 0.301s);

本日のキモとなる部分です。 Transition型のインスタンスを作成します。第一引数には「入り」にかかる時間を、第二引数には「出」にかかる時間を入れます。

数字の後ろにsをつけることで○秒と指定できます。今回の場合0.3秒と0.301秒というわけですね。なお0.001は違いをわかりやすくするためのものです。*3

ちなみにこの後ろにsつけてどうこうする機能ユーザー定義リテラルって言うらしいですよ。

Transitionの更新

  transition.update(MouseL.pressed());

本日のキモとなる部分2。
MouseL.pressed()はマウスが左クリックされてる間trueを返します。

そしてこのupdate関数は引数の中身がtrueだと「入り」の時間に合わせた速度でvalue()が返す値を0.0から1.0まで増加させます。今回の場合は0.0から1.0まで0.3秒かかる速度で0.0あるいはtrueになった時点での値から1.0まで増加させるということです。

逆にupdate関数の中身がfalseだと「出」の時間に合わせた速度で1.0から0.0まで減少させます。今回の場合は1.0から0.0まで0.301秒かかる速度で1.0あるいはfalseになった時点での値から0.0まで減少させるわけですね。

描画

//空
Rect(0, 0, Window::Size()).draw(ColorF(U"#41A7FF").setA(transition.value()));
Rect(0, 0, Window::Size()).draw(ColorF(U"#181991").setA(1.0-transition.value()));

//大地
Rect(0, 300, Window::Size()).draw(ColorF(U"#95EB00").setA(transition.easeIn(Easing::Sine)));
Rect(0, 300, Window::Size()).draw(ColorF(U"#207720").setA(1.0 - transition.easeIn(Easing::Sine)));

//木
tree.drawAt(200, 300, ColorF(transition.value()*0.6+0.4));

//月と太陽
sun.drawAt(100, 100, AlphaF(transition.value()));
moon.drawAt(Window::Width() - 100, 100, AlphaF(1.0-transition.value()));

行数は多いですがやることは全行だいたい同じです。

カラーコードから色を取得

ColorF(U"#95EB00")でカラーコードから色を取得することが出来ます。これもOpenSiv3Dからの新機能です。

transition.value()

transition.value()が上で説明した0.0から1.0まで返す関数です。

アルファ値の変更

setA()はColorF型のアルファ値を変更します。0.0が完全透明1.0が完全不透明です。

昼と夜

transition.value()1.0-transition.value()を使い分け昼と夜を再現します。今回はクリック中は昼にそうでない時は夜になる設定です。

イージング

transition.easeIn(Easing::Sine)のようにイージングも簡単に取り扱えます。
基本はvalue()と同じです。関数名及び引数でイージングを指定します。

イージングについてはこちら(旧Siv3D Wikiイージング · Siv3D/Reference-JP Wiki · GitHub

木の影

tree.drawAt(200, 300, ColorF(transition.value()*0.6+0.4));
transition.value()の値を使って夜のときは木を暗く昼のときは明るくなるように色を乗算します。

完成品

f:id:movementi:20180202194012g:plain
左クリックを続けると昼に離すと夜になる

さいごに

30行もないコードでここまでリッチなハイライトができてイージングも出来て絵文字をテクスチャとして用意できる。
OpenSiv3Dは素晴らしい。

ところで今現在OpenSiv3Dに入っている絵文字フォントはGoogleが作成したNoto Emojiの旧バージョンなのですが、最新のAndroid8.0版ではデザインの刷新が行われいままでの日本人受けするフラットデザインな絵文字からいかにも外国人受けしそうなリアル目な絵文字に変わってしまいました。

どう変わったのか詳しくはコチラ(英語サイト) blog.emojipedia.org

個人的にはOpenSiv3Dには今のバージョンの絵文字を採用し続けて欲しいんですけど、新絵文字の追加は新デザインの方でのみ行われており完全に旧バージョンとして切り捨てられてしまってるんですよね…

さてさてOpenSiv3Dの絵文字はこの先どうなることやら…

追記

2018/03/01

*1:実は新機能じゃないとかだと恥ずかしい

*2:この記事のタイトルはもともと「OpenSiv3DのTransitonで滑らかに切り替える」でしたが変えました

*3:ミスじゃないよわざとだよ