プログラマーの卵の日記

備忘録になってます!小難しそうなことから超簡単なことまでやってます!!

【C++】0から1の数値をいろいろなやり方でフェードさせてみた

 ※補足:図とか出力を見やすくするため、DxLibを使ってますが表題とはあまり関係ないです。
 また、後日追記更新する可能性があります。(絶対するとは言ってない)

 

構成


No.1 経緯
No.2 サイン波
No.3 二乗カーブ
No.4 線形補間







      No.1 経緯


 サウンドの勉強してたらフェードの話になって、半分の数値では半分の音量ならないから一気に下げてゆっくり0にしなって言われたので
色んなやり方でやってみようと思いました。
ちなみにそこでは、最大音量に対して0.27倍くらいが半分くらいになると書かれていた。





      No.2 サイン波


 サイン波だとこんな感じなると思います。分かりやすいように、左の数値では0から1までを25フレームとして、右の図では160フレームにしています。

f:id:yutateno:20200302014002p:plain




 関わりそうなコードだけを上げるとこんな感じです。


struct XY
{
	float x, y;
};

float Sin_ZeroToOne(const int t_maxCount, int t_nowCount)
{
	int temp = t_maxCount * 2;
	return std::sin(DX_PI / temp * t_nowCount);
}

/// --------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	if (Init(640, 480, 32, "Game") == false) return -1;

	const int max = 25;
	for (int i = 0; i <= max; ++i)
	{
		printfDx("%2d: %f\n", i, Sin_ZeroToOne(max, i));
	}

	const int maxDraw = 160;
	XY xy[maxDraw];
	for (int i = 1; i <= maxDraw; ++i)
	{
		int temp = i - 1;
		xy[temp].x = i + 240;
		xy[temp].y = 240 - Sin_ZeroToOne(maxDraw, i) * 120;
	}

	// メインループ
	while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() && !CheckHitKey(KEY_INPUT_ESCAPE))
	{
		for (int i = 1; i <= maxDraw; ++i)
		{
			int temp = i - 1;
			DrawPixel(xy[temp].x, xy[temp].y, GetColor(255, 255, 255));
		}
	}


 まぁ実行すればfloatからint型の変換ですうんたらかんたら言われますが、それは置いといて
こんな感じですと。特に説明はいらないと思います。





      No.3 二乗カーブ


 ぶっちゃけ合っているかわからないけど二乗カーブなってると思いながら作ってみたらこんな感じになった。
細かい部分はサイン波のやつと大体一緒。

f:id:yutateno:20200302014026p:plain




 さっきのサイン波のコードと違う部分だけ上げるとこんなところです。


float Squared_ZeroToOne(const int t_maxCount, int t_nowCount)
{
	float temp = 1.0f / t_maxCount * t_nowCount;
	return temp * temp;
}


 数値だけ見たら凄いゆっくりなように見えますが、フェードアウトという意味で見たら良いのかもしれない。





  No.4 線形補間


 C++20で追加されてるらしい線形補間でやってみた。波だとのこぎり波みたいな感じだし、サウンドのフェードという意味では思った通りのフェードにならないかもしれないけど一応作ってみた。

f:id:yutateno:20200302151533p:plain





 さっきのサイン波のコードと違う部分だけ上げるとこんなところです。


float lerp(float a, float b, float t)
{
	return a + t * (b - a);
}

float Lerp_ZeroToOne(const int t_maxCount, int t_nowCount)
{
	float temp = 1.0f / t_maxCount * t_nowCount;
	return lerp(0.0f, 1.0f, temp);
}


 シーンのフェードとか演出用とかでなら使えるかもしれない。