void GameSurface::Create() { m_background = loader::Image(k_imageBackground); decltype(FindGroups()) sets; m_selectedGem = k_noGem; std::size_t times = 0; do { // i = gems.size() to avoid unnecesary clears for (auto i = m_gems.size(); i < GEM_COUNT; ++i) { auto position = CalculateGemPosition(i); position.X = 0; position.Y = -OFFSET_Y - position.Y; m_gems.emplace_back(*this, position); } sets.swap(FindGroups()); ++times; for (auto& set : sets) // Randomize found sets { for (auto& i : set) { auto color = static_cast<GemColor>( std::rand() % GemSurface::COLOR_COUNT); m_gems[i].SetColor(color); } } } while (!sets.empty()); m_animation = Animation::FALL_ANIMATION; SDL_Log("Acceptable grid found in %d iterations", times); m_candlewick.Start(); m_scoreboard.Start(); m_gameOver = false; }
AbstractSurface::Status GameSurface::Update( const std::chrono::time_point<std::chrono::system_clock>& time) { Status status = AbstractSurface::Status::CONTINUE; for (auto& gem : m_gems) { if (gem.Update(time) == AbstractSurface::Status::ANIMATION) { status = AbstractSurface::Status::ANIMATION; } } if (status == AbstractSurface::Status::CONTINUE) { if (m_animation == Animation::FALL_ANIMATION) { m_animation = Animation::NO_ANIMATION; } else if (m_animation == Animation::SWAPPING_ANIMATION) { SDL_assert(m_swapping.first != m_swapping.second); m_destroyingGems.swap(FindGroups()); if (m_destroyingGems.empty()) { Swap(m_swapping.first, m_swapping.second, true); } else StartDestruction(); } else if (m_animation == Animation::DESTROY_ANIMATION) { while(!FillRow()); m_destroyingGems.swap(FindGroups()); if (!m_destroyingGems.empty()) StartDestruction(); } else if (m_animation == Animation::ROLLBACK_ANIMATION) { SDL_assert(m_swapping.first != m_swapping.second); #ifdef _DEBUG auto&& groups = FindGroups(); SDL_assert(groups.empty()); #endif m_animation = Animation::NO_ANIMATION; m_selectedGem = k_noGem; } } { m_candlewick.Update(time); if (m_scoreboard.Update(time) == AbstractSurface::Status::EXIT) { m_gameOver = true; } } return status; }
TError TCred::LoadGroups(const std::string &user) { if (FindGroups(user, Gid, Groups)) { L_ERR() << "Cannot load groups for " << user << std::endl; Groups.resize(1); Groups[0] = Gid; } return TError::Success(); }
std::set<std::vector<std::uint8_t>> GameSurface::FindGroups() const { decltype(FindGroups()) ret; typedef std::function<void(std::vector<std::uint8_t>&)> MatchFunction; const MatchFunction matchLeft = [&](std::vector<std::uint8_t>& data) { auto last = data.back(); auto next = last - 1; if ((last % COLUMNS) != 0 && m_gems[last].GetColor() == m_gems[next].GetColor()) { data.push_back(last - 1); matchLeft(data); } }; const MatchFunction matchRight = [&](std::vector<std::uint8_t>& data) { auto last = data.back(); auto next = last + 1; if ((last % COLUMNS) != COLUMNS - 1 && m_gems[last].GetColor() == m_gems[next].GetColor()) { data.push_back(last + 1); matchRight(data); } }; const MatchFunction matchUp = [&](std::vector<std::uint8_t>& data) { auto last = data.back(); auto next = last - COLUMNS; if ((last / COLUMNS) != 0 && m_gems[last].GetColor() == m_gems[next].GetColor()) { data.push_back(last - COLUMNS); matchUp(data); } }; const MatchFunction matchDown = [&](std::vector<std::uint8_t>& data) { auto last = data.back(); auto next = last + COLUMNS; if (last + COLUMNS < GEM_COUNT && m_gems[last].GetColor() == m_gems[next].GetColor()) { data.push_back(last + COLUMNS); matchDown(data); } }; const auto size = m_gems.size(); for (std::uint8_t i = 0u; i < size; ++i) { auto start = std::chrono::system_clock::now(); std::vector<std::uint8_t> horizontal{ i }, vertical{ i }; matchLeft(horizontal); std::reverse(horizontal.begin(), horizontal.end()); matchRight(horizontal); matchUp(vertical); std::reverse(vertical.begin(), vertical.end()); matchDown(vertical); if (horizontal.size() >= 3) ret.insert(horizontal); if (vertical.size() >= 3) ret.insert(vertical); } return ret; }