LoginSignup
0
0

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-08-08

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

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

soreppoi.png

finish.png

ranking.png

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;
        }
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0