ToggleFullScreen() を作ってみる、便利な Window<>フルスクリーン切り替え


ToggleFullScreen() 関数を作ってみるとは、
XNAライブラリの Window とフルスクリーンを関数を呼ぶだけで切り替えられる機能です。

XNAライブラリを使っていた時お世話になりました。



https://sorceryforce.net/ja/tips/xna-system-toggle-fullscreen


要約すると、XNAライブラリでは


                this.graphics.ToggleFullScreen();

この命令だけで、Windows ＜＞ フルスクリーン  の切り替えができます。

過去の記事（下記）で、Windowとフルスクリーンの切り替え は行っていますので、それを改造しようと思います。

https://qiita.com/loppta/items/16eb7b3b1faaf6444096

この時より、少しバージョンアップしているOpenSiv3D(0.4.3)にしました。

等倍でWindow表示する場合は大丈夫でしたが、

レトロゲームのサイズで等倍だと画面が小さすぎてしまうので、
３倍で表示させようとするとどうしても、初めの1回目だけは下記のようになります。
等倍の画面の右下当たり余白が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/9fe0b5ce-f6d0-82de-d574-4bb03e8b74a3.png)

で、なんとかこの動作は回避できるように無理やり組みました。

```cpp:openSiv3d_main.cpp
# include <Siv3D.hpp> // OpenSiv3D v0.4.3
namespace System2
{
    /// <summary>
    /// 一定時間待つ
    /// </summary>
    /// <param name="ms">待つ時間（ミリ秒）</param>
    void Sleep(int ms)
    {
        for (Stopwatch sw(true); sw.ms() < ms;);
    }
}
namespace TVgame
{
    //http://site.oukasei.com/?p=1230
    const Size DreamCast=   DisplayResolution::VGA_640x480;
    const Size PS4HD    =   DisplayResolution::HD_1280x720;
    const Size PS4FHD   =   DisplayResolution::FHD_1920x1080;
    const Size NES      =   Size{ 256, 224 };
    const Size FC       =   Size{ 256, 224 };
    const Size SFC      =   Size{ 256, 224 };
    const Size GENESIS  =   Size{ 320, 224 };
    const Size MD       =   Size{ 320, 224 };
    const Size SEGA_MS  =   Size{ 256, 224 };
    const Size SEGA_MK3 =   Size{ 256, 192 };
}
namespace Graphics2
{
    void SetScreenSize(Size screenSize = DisplayResolution::HD_1280x720, bool fullScreen = false, double scale = 1);
    void ToggleFullScreen();
}
namespace Graphics2
{
    Size sceneSize;
    Size windowSize;
    /// <summary>
    /// 
    /// 画面のサイズ決定
    /// 
    /// ToggleFullScreenができるようにします
    /// 
    /// Windowsサイズが小さすぎるとき、scaleを2以上にしてください
    /// </summary>
    /// <param name="screenSize">画素数  TV</param>
    /// <param name="fullScreen">全画面</param>
    /// <param name="scale">Windowの表示サイズが小さすぎるときに1より大きい数を入れてください</param>
    void SetScreenSize(Size screenSize,bool fullScreen,double scale)
    {
        Graphics2::windowSize = (screenSize * scale).asPoint();
        Window::Resize(Graphics2::windowSize); //重いのでこの命令はフルスクリーン切り替え時には行わない
        Graphics2::sceneSize = screenSize;
        Scene::Resize(screenSize);
        fullScreen = !fullScreen; // これをしないとscaleが1以外の値が入ると描画がおかしくなるため仕方なく
        Window::SetFullscreen(fullScreen);
        Graphics2::ToggleFullScreen(); // これをしないとscaleが1以外の値が入ると描画がおかしくなるため仕方なく
    }
    /// <summary>
    /// Window画面＜＞フルスクリーン切り替え
    /// </summary>
    void ToggleFullScreen()
    {   
        static int first = 0;
        static bool fullScreen=false;
        fullScreen = !fullScreen;
        Window::SetFullscreen(fullScreen);  // Windowかフルスクリーン切り替え
        Scene::Resize(Graphics2::sceneSize);
    }
};
//https://sorceryforce.net/ja/tips/xna-system-toggle-fullscreen

void Main()
{
    Graphics::SetTargetFrameRateHz(60);   // 60FPS固定
// MegaDrive(海外だとGenesis)の幅と高さのピクセル
    Window::SetTitle(U"Retro game");  // ウィンドウタイトル（フルスクリーンでは表示されない）
    // ウィンドウの枠を非表示にする
    //Window::SetStyle(WindowStyle::Frameless);   // ウィンドウ枠を消す

    bool fullscreen = true;
#ifdef _DEBUG
    fullscreen = false;
#endif

    Graphics2::SetScreenSize(TVgame::GENESIS,fullscreen,3);

    // シーンをウィンドウに転送する際の拡大縮小フィルタを「補間なし」に
    Scene::SetTextureFilter(TextureFilter::Nearest);

    // 背景を水色にする

    // 大きさ 60 のフォントを用意
    const Font font(60);

    // 320*224のテクスチャを用意(メガドライブと同じ画素数)
    const Texture genesisScreen(U"sonic3tails.gif");

    while (System::Update())
    {
        if (KeySpace.down())
        {
            Graphics2::ToggleFullScreen();// Windowの時、画面が小さいので2倍に拡大
        }
        if (KeyN.down()) // 補間なし
        {
            Scene::SetTextureFilter(TextureFilter::Nearest);
        }
        if (KeyL.down()) // 補間あり
        {
            Scene::SetTextureFilter(TextureFilter::Linear);
        }
        genesisScreen.draw();
    }
}

```

スペースキーで Window＜＞フルスクリーンの切り替えができます。

これにより、ゲームと言えばフルスクリーンでしょう！という人にも大丈夫です。

フルスクリーンはブレークポイント入れたりするデバッグ作業にはかなり支障をきたすので、
そういう時は簡単にWindow画面にできます。

3倍で拡大してWindow表示しています。スペースキーでフルスクリーンもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/c34c4ca3-f142-250d-afc8-7ce6e138c67c.png)




下記画像を右クリックして <B>sonic3tails.gif</B>  という名前で保存してプロジェクトのAppフォルダに入れれば使えます。
![sonic3tails.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/32da2d11-4128-3166-83bd-7269442cf61f.gif)

余談：

XNAライブラリでは便利な命令もあるので、たまに同等機能を考えたいです。
外国人の方はXNAライブラリにかなり似たライブラリにまだ人気があるようで、さすがにオワコン時に炎上した人たちならではです。
MonoGame  FNA　ほかにもいくつかあったような気がします。イメージ的にはXNA互換ライブラリです。

OpenSiv3Dの0.4.3の次の新バージョンが出ました。
新機能追加で、プロジェクト生成時に１００M以上増えてしまったそうです。
自分は大した機能は使っていないので、可能であれば、DXライブラリのように２DのみOpenSiv３Dとかそういう別のが欲しかったです。
また、60FPSに設定する命令もなぜか消えてしまったので、デバイス制御がらみで何か致命的なバグでもあったのか、
ちょっと不安なので様子見です。
他もグラフィック制御がらみで何かあるかもとか、その辺です。
物理と３D機能は復活されましたが、FBXファイルやモーションデータなどはまだ使えないようです。