それっぽい機能
* オープニング画面,ゲーム画面,終了画面,結果画面に遷移する
* ハイスコアランキングの表示
* 150行以内
* http://play-siv3d.hateblo.jp/ の書式に極力揃える
* ビジュアル的に面白く
無理やり詰め込んだ,相変わらず謎である
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;
}
}
}