ポーズの管理をしやすくする

#はじめに
ゲームを作っていてポーズを実装したいときに例えば

```ruby:Main.cpp
void Main()
{

	bool isPause=false;

	while (System::Update())
	{
		if (Input::MouseL.clicked)
		{
			isPause = !isPause;
		}

		if (!isPause)
		{
			//更新
			//Update();
		}

		//描画
		//Draw();

	}
}
```
このようにしたり、

HamFrameworkの`SceneManager`を使っている場合は

```ruby:Scene.h
void update()override
{
	if (Input::MouseL.clicked)
	{
		m_isPause = !m_isPause;
	}
	if (m_isPause)
		return;

	/*
	処理
	*/
}
```
このようにして更新の処理を呼ばない用にして対処することができます。

しかし、経過時間に依存する

- `Stopwatch`
- `EasingController`
- `Effect`

などを使用して実装していた場合は、これら全ての`pause`関数も呼び出さないと意図していない動作になってしまう場合があります。

数が少ないときは問題ないかもしれませんが、ゲームの規模が大きくなったり細かい演出のためにEasingを多用したりした時に全ての`pause`関数を呼ぶのは大変だったりします。

自分もゲームを作りこんだ後にポーズを実装しようとした時に、この問題に苦労したことがありました。

そこで今回は、これら全てをたった1行の関数を呼ぶだけで止めたり再開できるようにしたいと思います。
#方針
では、それを実装するためにどのようにするかの方針をざっくり説明します。

1. ポーズが必要なクラスは`IPause`クラスを継承する
    - ポーズを行う`pause`関数をオーバーライド
    - リジュームを行う`resume`関数をオーバーライド
2. ポーズを管理する`PauseManager`をつくる
    - メンバ変数にポーズが必要なインスタンスへのポインタのリスト`std::list<IPause*>`をもつ
    - 全てのポーズを行うメンバ関数`pauseAll`をもつ
    - 全てのリジュームを行うメンバ関数`resumeAll`をもつ
2.  `IPause`を継承したクラスのインスタンスの生成時に、自身のポインタを`PauseManager`のリストにわたす
3.  `IPause`を継承したクラスのインスタンスの破棄時に、`PauseManager`のリストから自身へのポインタを**削除**する

#実装

実際に上のような方針で実装してみた一例

今回はPuaseManagerをシングルトンパターンにして実装していますが必ずしもそうである必要はありません。

```ruby:PauseManager.h
#pragma once
#include<Siv3D.hpp>

class IPause;

//-------------------------------------------------------
// PauseManager
//-------------------------------------------------------

//シングルトンで実装
class PauseManager final : Uncopyable
{
	friend IPause;
private:
	PauseManager() = default;

	//管理するリスト
	std::list<IPause*> m_pauseList;

	void pauseAll();
	void resumeAll();

	//リストへデータの追加
	void add(IPause*const pause)
	{
		m_pauseList.emplace_back(pause);
	}
	//リストからデータの削除
	void erase(const IPause*const pause)
	{
		s3d::Erase(m_pauseList, pause);
	}

	static PauseManager& Instance()
	{
		static PauseManager instance;
		return instance;
	}

	static void Add(IPause*const pause)
	{
		Instance().add(pause);
	}

	static void Erase(const IPause*const pause)
	{
		Instance().erase(pause);
	}
public:

	//すべてポーズ
	static void Pause()
	{
		Instance().pauseAll();
	}

	//すべてリジューム
	static void Resume()
	{
		Instance().resumeAll();
	}


};

//-------------------------------------------------------
// IPause
//-------------------------------------------------------

//ポーズさせたいクラスはこれを継承
class IPause
{
public:
	IPause()
	{
		PauseManager::Add(this);
	}
	virtual ~IPause()
	{
		PauseManager::Erase(this);
	}

	virtual void pause() = 0;
	virtual void resume() = 0;

};

//-------------------------------------------------------

//すべてポーズ
void PauseManager::pauseAll()
{
	for (auto&& elm : m_pauseList)
	{
		elm->pause();
	}
}

//すべてリジューム
void PauseManager::resumeAll()
{
	for (auto&& elm : m_pauseList)
	{
		elm->resume();
	}
}






```

今回の実装方法は2つのclassが絡み合うので宣言や定義順を考慮する必要があります。

##Stopwatchなどに適応させるために
ここまで実装できたら、実際にStopwatchやEasingContlloerに適応してみましょう。

```ruby:Main.cpp
class PauseableStopwatch:
	public IPause,
	public Stopwatch
{
public:
	//コンストラクタ
	PauseableStopwatch(bool startImmediately = false):
        Stopwatch(startImmediately)
        {}

	void pause()override
	{
		this->Stopwatch::pause();
	}

	void resume()override
	{
		this->Stopwatch::resume();
	}

};

```
これで、`PauseableStopwatch`のインスタンスは`PauseManager::Pause`関数を呼べばポーズされるようになりました。

同様にEasingControllerやEffectもやってもいいですが、このようにそれぞれ対応する新しいクラスを作っていては大変なのでtemplateを使用すると1つのクラスですみます。

```ruby:Main.cpp
/*
Stopwatch Effect EasingControllerはメソッド名が共有なのでtemplateでやんちゃする
*/
template<class Type>
class Pauseable:
	public IPause,
	public Type
{
public:
	//コンストラクタの引継ぎ
	using Type::Type;

	void pause()override
	{
		this->Type::pause();
	}

	void resume()override
	{
		this->Type::resume();
	}

};

```

```using 基底クラス名::基底クラス名;```と書くことで基底クラスのコンストラタを引き継いで省略することできます。


#サンプル

実際に使ってみる

```ruby:Main.cpp


# include <Siv3D.hpp>

#include"PauseManager.h"

template<class Type>
class Pauseable:
	public IPause,
	public Type
{
public:
	//コンストラクタの引継ぎ
	using Type::Type;

	void pause()override
	{
		this->Type::pause();
	}

	void resume()override
	{
		this->Type::resume();
	}

};

void Main()
{

	Pauseable<EasingController<int>> easing(0,1000,Easing::Quad,5000);

	Pauseable<Stopwatch> stopwatch(true);

	bool isPause=false;

	while (System::Update())
	{
		if (!easing.isActive())
		{
			easing.start();
		}

		if (Input::MouseL.clicked)
		{
			if (isPause)
			{
				PauseManager::Resume();
			}
			else
			{
				PauseManager::Pause();
			}
			isPause = !isPause;
		}

		ClearPrint();
		Println(easing.easeInOut());
		Println(stopwatch.ms());

	}
}


```

#まとめ
 - 経過時間に依存するものはポーズしたいときに管理が大変になる
 - インスタンスへのポインタのリストを作っておくことでまとめてポーズできる