ungroup/ungroup_game

View on GitHub
src/client/rendering/RenderingController.cpp

Summary

Maintainability
Test Coverage
#include "RenderingController.hpp"

#include "RenderingUtil.hpp"

RenderingController::RenderingController(sf::RenderWindow& window, GameObjectController& goc,
                                         GameObjectStore& gos, uint32_t player_id, bool headless) :
    m_window(window),
    m_uiData({}), m_gameObjectController(goc), m_resourceStore(),
    m_animationController(m_resourceStore),
    m_backgroundController(sf::Vector2u(GAME_SETTINGS.GAME_SIZE), m_resourceStore),
    m_playerId(player_id),
    m_gameObjectRenderer(m_resourceStore, m_gameObjectController.getResourceController(),
                         m_gameObjectController.getGroupController(),
                         m_gameObjectController.getMineController(),
                         m_gameObjectController.getPlayerController(), m_playerId),
    m_guiController(m_window.getSize(), m_resourceStore), m_headless(headless) {
    m_window.setFramerateLimit(RenderingDef::WINDOW_FRAME_LIMIT);
    m_window.setVerticalSyncEnabled(RenderingDef::VSYNC_ENABLED);
    sf::Vector2f window_size = sf::Vector2f(m_window.getSize());

    // Create buffer to draw game onto. Buffer can be scaled to give pixelated effect
    if (!m_buffer.create(GAME_SETTINGS.GAME_SIZE.x, GAME_SETTINGS.GAME_SIZE.y)) {
        throw std::runtime_error("Failed to create buffer.");
    }
    m_buffer.setSmooth(false);

    m_bufferSprite = sf::Sprite(m_buffer.getTexture());
    m_bufferSprite.setScale(RenderingDef::GAME_SCALING_FACTOR);

    // Create views to draw GUI and player view
    m_windowView = sf::View(window_size / 2.f, window_size);
    m_playerView = sf::View({}, sf::Vector2f(m_window.getSize()));
    m_playerView.setCenter(GAME_SETTINGS.GAME_SIZE * 2.f);

    // Connecting text parameters
    m_connectingText.setFont(*m_resourceStore.getFont(RenderingDef::FontKey::monogram));
    m_connectingText.setCharacterSize(100.f);
    m_connectingText.setFillColor(sf::Color::White);

    // Winner text parameters
    m_winnerText.setFont(*m_resourceStore.getFont(RenderingDef::FontKey::monogram));
    m_winnerText.setCharacterSize(100.f);
    m_winnerText.setFillColor(sf::Color::White);
}

void RenderingController::preUpdate() {
    // noop
}

void RenderingController::update(sf::Int32 delta_ms) {
    if (m_headless) {
        return;
    }

    m_animationController.update(delta_ms);
}

void RenderingController::postUpdate(sf::Int32 update_time, const UIData& ui_data) {
    if (m_headless) {
        return;
    }

    m_uiData = ui_data;
    m_guiController.update(m_uiData);

    updateCamera(update_time);

    // todo(sourenp|#199|2020-04-29) Reenable background update issue with player jitter resolved
    // auto player_position = m_gameObjectController.getPlayerPosition(m_playerId);
    // m_backgroundController.update(player_position);
}

void RenderingController::updateCamera(sf::Int32 delta_ms) {
    auto player_position = m_gameObjectController.getPlayerPosition(m_playerId);
    sf::Vector2f player_position_in_view = RenderingUtil::mapCoordToPixelScaled(
        player_position, m_window, m_windowView, RenderingDef::GAME_SCALING_FACTOR);
    m_playerView.setCenter(VectorUtil::lerp(
        m_playerView.getCenter(), player_position_in_view,
        VectorUtil::clamp((RenderingDef::CAMERA_CHASE * GAME_SETTINGS.MIN_TIME_STEP_SEC) * delta_ms,
                          0, 1)));
}

void RenderingController::draw() {
    if (m_headless) {
        return;
    }

    switch (m_uiData.game_status) {
        case GameStatus::not_started: {
            drawNotStarted();
            break;
        }
        case GameStatus::playing: {
            drawPlaying();
            break;
        }
        case GameStatus::game_over: {
            drawGameOver();
            break;
        }
    }
}

void RenderingController::drawNotStarted() {
    m_window.clear(RenderingDef::CONNECTING_SCREEN_COLOR);

    m_connectingText.setString("Connecting...");
    sf::FloatRect textRect = m_connectingText.getLocalBounds();
    m_connectingText.setOrigin(textRect.left + textRect.width / 2.0f,
                               textRect.top + textRect.height / 2.0f);
    m_connectingText.setPosition(sf::Vector2f(m_window.getSize()) / 2.f);
    m_window.draw(m_connectingText);

    m_window.display();
}

void RenderingController::drawPlaying() {
    m_window.clear(RenderingDef::OUT_OF_BOUNDS_COLOR);
    m_buffer.clear(RenderingDef::OUT_OF_BOUNDS_COLOR);

    // Draw game from player view
    m_window.setView(m_playerView);

    m_backgroundController.draw(m_buffer);
    m_gameObjectRenderer.draw(m_buffer);
    m_animationController.draw(m_buffer);
    m_window.draw(m_bufferSprite);

    // Draw GUI from window view
    m_window.setView(m_windowView);
    m_gameObjectRenderer.drawUI(m_window, m_playerView);
    m_guiController.draw(m_window);

    m_buffer.display();
    m_window.display();
}

void RenderingController::drawGameOver() {
    m_window.clear(RenderingDef::WINNER_SCREEN_COLOR);

    m_winnerText.setString("Winner: " + std::to_string(m_uiData.winner_player_id));
    sf::FloatRect textRect = m_winnerText.getLocalBounds();
    m_winnerText.setOrigin(textRect.left + textRect.width / 2.0f,
                           textRect.top + textRect.height / 2.0f);
    m_winnerText.setPosition(sf::Vector2f(m_window.getSize()) / 2.f);
    m_window.draw(m_winnerText);

    m_window.display();
}