void Engine::PlayGame()

in NearbyConnectionsCpp/app/src/main/cpp/NearbyNativeActivity.cpp [37:154]


void Engine::PlayGame() {
  ndk_helper::JNIHelper::GetInstance()->RunOnUiThread([this]() {
    LOGI("Playing match");
    if (dialog_) delete dialog_;

    // Start game
    InitializeGame();

    //
    // Using jui_helper, a support library, to create and bind gameplay buttons.
    //
    dialog_ = new jui_helper::JUIDialog(app_->activity);

    // Setting up labels
    time_text_ = new jui_helper::JUITextView("Time Left: 0:00");
    time_text_->AddRule(jui_helper::LAYOUT_PARAMETER_ALIGN_PARENT_TOP,
                        jui_helper::LAYOUT_PARAMETER_TRUE);
    time_text_->AddRule(jui_helper::LAYOUT_PARAMETER_CENTER_IN_PARENT,
                        jui_helper::LAYOUT_PARAMETER_TRUE);
    time_text_->SetAttribute("TextSize", jui_helper::ATTRIBUTE_UNIT_SP, 18.f);
    time_text_->SetAttribute("Padding", 10, 10, 10, 10);

    // Adding formula Text
    math_formula_ = new jui_helper::JUITextView("10 + 5 = ?");
    math_formula_->AddRule(jui_helper::LAYOUT_PARAMETER_BELOW, time_text_);
    math_formula_->AddRule(jui_helper::LAYOUT_PARAMETER_CENTER_IN_PARENT,
                           jui_helper::LAYOUT_PARAMETER_TRUE);
    math_formula_->SetAttribute("TextSize", jui_helper::ATTRIBUTE_UNIT_SP,
                                24.f);
    math_formula_->SetAttribute("Padding", 10, 10, 10, 10);

    // Adding Multiple Choice Buttons
    jui_helper::JUIButton *button = CreateChoiceButton("A", NULL);
    if (button) {
      button->AddRule(jui_helper::LAYOUT_PARAMETER_ALIGN_PARENT_LEFT,
                      jui_helper::LAYOUT_PARAMETER_TRUE);
      button->SetMargins(40, 0, 0, 0);  // todo: make it adaptive
    }
    game_buttons_[0] = button;
    for (int i = 1; i < CHOICES_PER_QUESTION; i++) {
      std::string cap(1, 'A' + i);
      button = CreateChoiceButton(cap.c_str(), game_buttons_[i - 1]);
      game_buttons_[i] = button;
    }

    const int32_t labelWidth = 600;
    const int32_t labelHeight = 300;
    scores_text_ = new jui_helper::JUITextView("0:00");
    scores_text_->AddRule(jui_helper::LAYOUT_PARAMETER_BELOW,
                          game_buttons_[CHOICES_PER_QUESTION - 1]);
    scores_text_->AddRule(jui_helper::LAYOUT_PARAMETER_CENTER_IN_PARENT,
                          jui_helper::LAYOUT_PARAMETER_TRUE);
    scores_text_->SetAttribute("TextSize", jui_helper::ATTRIBUTE_UNIT_SP, 18.f);
    scores_text_->SetAttribute("MinimumWidth", labelWidth);
    scores_text_->SetAttribute("MinimumHeight", labelHeight);
    scores_text_->SetAttribute("Padding", 10, 10, 10, 10);

    UpdateScoreBoardUI(false);

    dialog_->AddView(math_formula_);

    std::for_each(
        game_buttons_, game_buttons_ + CHOICES_PER_QUESTION,
        [this](jui_helper::JUIButton *button) { dialog_->AddView(button); });
    PlayOneRound();

    dialog_->AddView(time_text_);
    dialog_->AddView(scores_text_);

    dialog_->SetAttribute("Title", "Select an answer");
    dialog_->SetCallback(
        jui_helper::JUICALLBACK_DIALOG_DISMISSED,
        [this](jui_helper::JUIDialog *dialog, const int32_t message) {
          LOGI("Dialog dismissed");
          LeaveGame();
          dialog_ = nullptr;
        });

    dialog_->Show();

    //
    // Invoke time counter periodically
    //
    std::thread([this]() {
      ndk_helper::JNIHelper &helper = *ndk_helper::JNIHelper::GetInstance();
      helper.AttachCurrentThread();
      while (playing_ && game_time_ <= GAME_DURATION) {
        // Update game UI, UI update needs to be performed in UI thread
        ndk_helper::JNIHelper::GetInstance()->RunOnUiThread([this]() {
          char str[SCORE_STRING_LEN];
          std::lock_guard<std::mutex> lock(mutex_);
          snprintf(str, SCORE_STRING_LEN, "Time Left: %d",
                   GAME_DURATION - this->game_time_);
          time_text_->SetAttribute("Text", const_cast<const char *>(str));
        });

        // maintain our private clock
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        game_time_ += 1;
      }

      // finish game
      playing_ = false;
      ndk_helper::JNIHelper::GetInstance()->RunOnUiThread([this]() {
        std::lock_guard<std::mutex> lock(mutex_);
        for (int i = 0; i < CHOICES_PER_QUESTION; i++) {
          game_buttons_[i]->SetAttribute("Enabled", false);
        }
        math_formula_->SetAttribute("Enabled", false);
      });

      BroadcastScore(score_counter_, true);

      UpdateScoreBoardUI(true);
      helper.DetachCurrentThread();
    }).detach();
  });
}