始めまして。入社3年目のプログラマー J と申します。
キャッシュを考慮したコードを書いてみよう!を書いた人の同期です。
今回は、手付けで実装する簡単なUIのプログラムを紹介したいと思います。
UIを手付けで実装するメリットは、性能が低いハードでのFPS保持や、複雑・オシャレな動きをさせたいなどがあります。
デメリットとしては、プログラマーの工数が増えるのでスケジュールとの相談だったりです。
使用したライブラリはSiv3Dです。
お手軽にプログラムが書けるので個人的におススメです。
Siv3D Reference-JP
まずは四角形を1つ表示してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// ---------------------------------------- include # include <Siv3D.hpp> // ---------------------------------------- function void Main() { // ウィンドウのタイトルを設定する Window::SetTitle(L"UI Sample"); while (System::Update()) { Rect(Point(100, 100), 150, 50).draw({ 0, 255, 0, 255 }); } } |
次にUIに必要なインアニメ、アウトアニメ、待ちアニメを制御する処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
// ---------------------------------------- include # include <Siv3D.hpp> // ---------------------------------------- enum // 状態の種類 enum eState { eState_In, // インアニメ中 eState_Out, // アウトアニメ中 eState_Wait,// 待機アニメ中 eState_Num, // 最大値 }; // ---------------------------------------- static // 現在の状態 static eState s_State = eState_Wait; // 描画フラグ static bool s_IsDisp = false; // ---------------------------------------- function // 描画関数 static void _Draw() { switch (s_State) { // インアニメ case eState_In: break; // アウトアニメ case eState_Out: break; // 待ちアニメ case eState_Wait: break; } Rect(Point(100, 100), 150, 50).draw({ 0, 255, 0, 255 }); } // メイン関数 void Main() { // ウィンドウのタイトルを設定する Window::SetTitle(L"UI Sample"); while (System::Update()) { if (s_IsDisp) { _Draw(); } } } |
状態の種類、現在の状態、描画フラグを定義し、更新処理をswitchで分けるようにしました。
このコードを実行すると s_IsDisp が false のためUI表示されません。
それでは、
・左クリックしたら状態を eState_In にしてUIを表示
・インアニメ中はα値を60フレームで0から255に変化
・右クリックしたら状態を eState_Out にする
・アウトアニメ中はα値を30フレームで255から0に変化してUIを非表示
となるように実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
// ---------------------------------------- include # include <Siv3D.hpp> // ---------------------------------------- enum // 状態の種類 enum eState { eState_In, // インアニメ中 eState_Out, // アウトアニメ中 eState_Wait,// 待機アニメ中 eState_Num, // 最大値 }; // ---------------------------------------- static static eState s_State = eState_Wait; // 現在の状態 static bool s_IsDisp = false; // 描画フラグ static int s_Timer = 0; // アニメ用タイマー // ---------------------------------------- const static const int ALPHA_MAX = 255; // α値の最大値 static const int IN_ANIM_TIME = 60; // インアニメの時間 static const int OUT_ANIM_TIME = 30; // アウトアニメの時間 // ---------------------------------------- function // 描画関数 static void _Draw() { int alpha = ALPHA_MAX; // α値 switch (s_State) { // インアニメ case eState_In: { double rate = static_cast<double>(s_Timer) / IN_ANIM_TIME; alpha = static_cast<int>(rate * ALPHA_MAX); // アニメ終了チェック、終了したら待ちアニメ状態にする if (++s_Timer >= IN_ANIM_TIME) { s_State = eState_Wait; } } break; // アウトアニメ case eState_Out: { double rate = static_cast<double>(OUT_ANIM_TIME - s_Timer) / OUT_ANIM_TIME; alpha = static_cast<int>(rate * ALPHA_MAX); // アニメ終了チェック、終了したらUIを非表示にする if (++s_Timer >= OUT_ANIM_TIME) { s_IsDisp = false; } } break; // 待ちアニメ case eState_Wait: // 何もしない break; } Rect(Point(100, 100), 150, 50).draw({ 0, 255, 0, alpha }); } // メイン関数 void Main() { // ウィンドウのタイトルを設定する Window::SetTitle(L"UI Sample"); while (System::Update()) { // 左クリック if (Input::MouseL.clicked) { s_State = eState_In; s_IsDisp = true; s_Timer = 0; } // 右クリック else if (Input::MouseR.clicked) { s_State = eState_Out; s_IsDisp = true; s_Timer = 0; } if (s_IsDisp) { _Draw(); } } } |
特に難しいことはせず、最終的なパラメータに対してオフセットするような形です。
これで基本部分の実装はできました。
あとはアニメーションの補間にイージングを使用し、移動、拡縮、回転などを加えるとクオリティアップできます。
また、状態を増やすことでイン、アウトだけでなく、別の動きを追加することも簡単です。
最後に
やはり、手付けでアニメーションを実装するのは時間がかかるものの、見た目が良く、処理速度が速いので、時間があるときは是非お試しください。
それでは。
(Visited 737 times, 1 visits today)