それっぽい機能のそろったゲームを150行以内で

それっぽい機能
* オープニング画面，ゲーム画面，終了画面，結果画面に遷移する
* ハイスコアランキングの表示
* 150行以内
* http://play-siv3d.hateblo.jp/ の書式に極力揃える
* ビジュアル的に面白く

無理やり詰め込んだ，相変わらず謎である

![soreppoi.png](https://qiita-image-store.s3.amazonaws.com/0/34295/a9a9d8d3-b8b5-f714-6899-0de520519a4a.png)

![finish.png](https://qiita-image-store.s3.amazonaws.com/0/34295/0a5fea8d-2b17-6e56-b8eb-9464e8da9b49.png)

![ranking.png](https://qiita-image-store.s3.amazonaws.com/0/34295/0436c169-f723-f32b-1188-d853618e9820.png)


```cpp:Main.cpp
# include <Siv3D.hpp>

void Main()
{
	enum class GameState
	{
		Opening, Game, Finish, Result
	};

	Graphics::SetBackground(Palette::Black);
	Window::SetTitle(L"十字キーで操作");
	GameState gameState = GameState::Opening;
	GameState tGameState = gameState;
	TimerMillisec timer;
	Font font(20);
	timer.start();	

	const double windowWidth = Window::Width();
	const double windowHeight = Window::Height();	
	const double playerHeight = 0.05;
	const double playerPosY = 0.1;
	const double playerSpeed = 0.01;
	const double gravity = 0.001;
	const Color col = ColorF(0.0, 1.0, 0.0);
	
	double playerPosX;
	double playerWidth;
	Vec2 ballPos;
	Vec2 ballVelocity;
	String scoreString;
	unsigned score;
	std::array<unsigned int, 9> scores;
	scores.fill(0);

	std::function<void()> initGame = [&]()
	{
		playerPosX = 0.5;
		playerWidth = 0.1;
		ballPos = Vec2(0.5, 0.8);
		ballVelocity = RandomVec2({-0.001, 0.001}, {-0.001, 0.001});
		scoreString.clear();
		score = 0;
	};

	std::function<void()> setScore = [&]()
	{
		score = timer.elapsed();
		auto minScore = std::min_element(scores.begin(), scores.end());

		if (*minScore < score)
		{
			*minScore = score;
			std::sort(scores.begin(), scores.end(), [&](unsigned int a, unsigned int b){return a > b; });
		}			

		for (auto it = scores.begin(); it < scores.end(); ++it)
		{
			scoreString += Format(it - scores.begin() + 1, L": ");
			scoreString += (*it == score) ? Format(L"***", score, L"***\n") : Format(*it, L'\n');
		}
	};

	std::function<Vec2(const Vec2&)> getPos = [&](const Vec2& pos){return Vec2(windowWidth * pos.x, (1.0 - pos.y) * windowHeight);};

	std::function<void()> updatePos = [&]()
	{
		ballVelocity.x = (ballPos.x < 0.0 || ballPos.x > 1.0) ? -ballVelocity.x : ballVelocity.x;
		ballVelocity.y -= gravity;
		ballPos += ballVelocity;
		playerPosX += playerSpeed * (Input::KeyRight.pressed - Input::KeyLeft.pressed);
		playerPosX = Clamp(playerPosX, 0.0, 1.0);
	};

	std::function<void()> drawBallAndPlayer = [&]()
	{
		RectF(windowWidth * playerWidth, windowHeight * playerHeight).setCenter(getPos({ playerPosX, playerPosY })).draw(col);
		for (int i = -3; i < 4; ++i)
			Circle(getPos(ballPos + static_cast<double>(i) / 3.0 * ballVelocity), 10.0).draw(col);
	};

	vector<std::function<void()>> functions = 
	{
		[&]()
		{
			font(L"ボールを落とさないようにするゲーム\nキー押すとゲーム開始").drawCenter(Window::Center(), col);

			if (Input::AnyKeyClicked())
			{
				initGame();
				gameState = GameState::Game;
			}
		}, [&]()
		{
			font(timer.elapsed()).draw({ 0.0, 0.0 }, col);

			if (RectF(playerWidth, playerHeight).setCenter(playerPosX, playerPosY).intersects(ballPos))
			{
				playerWidth *= 0.9;
				ballVelocity = Vec2(0.03 * (ballPos.x - playerPosX) / playerWidth, -ballVelocity.y);
				ballPos.y = playerPosY + playerHeight / 2.0;
			}

			updatePos();

			drawBallAndPlayer();

			if (ballPos.y < 0.0)
			{
				setScore();
				gameState = GameState::Finish;
			}
		}, [&]()
		{
			font(L"FINISH!!\nscore : ", score).drawCenter(Window::Center(), col);

			updatePos();

			if (ballPos.y < 0.0)
			{
				ballPos.y = 0.0;
				ballVelocity.x = 0.5 * ballVelocity.x;
				ballVelocity.y = -0.5 * ballVelocity.y;
			}
				
			drawBallAndPlayer();

			if (timer.elapsed() > 3000)
				gameState = GameState::Result;
		}, [&]()
		{
			font(scoreString).drawCenter(Window::Center(), col);

			if (Input::AnyKeyClicked())
				gameState = GameState::Opening;
		}
	};

	while (System::Update())
	{
		functions[static_cast<int>(gameState)]();

		if (tGameState != gameState)
		{
			timer.restart();

			tGameState = gameState;
		}
	}
}
```