in ID@XboxSDK/GameSave/Xbox/GameLogic/GameBoardScreen.cpp [725:1060]
void GameBoardScreen::Draw(float totalTime, float elapsedTime)
{
auto spriteBatch = Manager()->GetSpriteBatch();
auto gameFont = Manager()->GetSpriteFont();
auto blendStates = Manager()->GetCommonStates();
auto scaleMatrix = DX::GetScaleMatrixForWindow(Manager()->GetWindowBounds());
// Draw background
spriteBatch->Begin(SpriteSortMode_Deferred, blendStates->NonPremultiplied(), nullptr, nullptr, nullptr, nullptr, scaleMatrix);
spriteBatch->Draw(m_background->GetResourceViewTemporary(), XMFLOAT2(0, 0));
spriteBatch->End();
if (IsActive() && m_isGameSaveManagerInitialized)
{
MenuScreen::Draw(totalTime, elapsedTime);
}
if (m_state != ScreenState::Active)
{
return;
}
auto gameSaveManager = Game->GameSaveManager;
assert(gameSaveManager->HasActiveBoard);
std::lock_guard<std::mutex> lock(gameSaveManager->ActiveBoardGameSave->m_mutex);
auto activeBoardNum = gameSaveManager->ActiveBoardNumber;
auto activeBoard = gameSaveManager->ActiveBoard;
auto activeBoardGameSave = gameSaveManager->ActiveBoardGameSave;
auto activeBoardMetadata = activeBoardGameSave->m_containerMetadata;
spriteBatch->Begin(SpriteSortMode_Deferred, blendStates->NonPremultiplied(), nullptr, nullptr, nullptr, nullptr, scaleMatrix);
// Draw numbers of the visible game boards and highlight the active one
XMFLOAT2 position = c_saveSlotFirstNumber_TopCenter;
XMFLOAT2 origin = XMFLOAT2(m_saveSlotNumbers[0]->Width() / 2.0f, 0.0f);
for (auto i = m_firstSlotToDisplay; i < m_firstSlotToDisplay + 3; ++i)
{
if (i == m_firstSlotToDisplay + 2)
position.x -= 10; // UI correction: 3rd board number is not the same distance from the 2nd as the 2nd is from the 1st
if (i == activeBoardNum)
{
spriteBatch->Draw(m_saveSlotActiveNumbers[i - 1]->GetResourceViewTemporary(), position, nullptr, Colors::White, 0.0f, origin);
}
else
{
spriteBatch->Draw(m_saveSlotNumbers[i - 1]->GetResourceViewTemporary(), position, nullptr, Colors::White, 0.0f, origin);
}
position.x += c_saveSlotNumber_PixelsBetweenCenters;
}
// Draw active board title and dirty status
Platform::String^ gameBoardTitleStr = "WordGame";
if (activeBoardNum > 0)
{
gameBoardTitleStr += " Board " + activeBoardNum.ToString();
}
if (gameSaveManager->IsActiveBoardDirty)
{
gameBoardTitleStr += "*";
}
m_gameBoardTitleFont->DrawString(spriteBatch.get(), gameBoardTitleStr->Data(), c_gameTitle_UpperLeft);
// Draw player name
Platform::String^ userDisplayStr = "User: " + ref new Platform::String(Game->LiveResources->GetGamertag().c_str());
m_gameBoardMetadataFont->DrawString(spriteBatch.get(), userDisplayStr->Data(), c_playerName_UpperLeft, Colors::White, 0.0f, XMFLOAT2(0, 0), c_playerName_Scale);
// Draw active board metadata (last save date, current user gamertag)
Platform::String^ gameBoardMetadataDisplay;
if (activeBoardMetadata->m_isGameDataOnDisk)
{
gameBoardMetadataDisplay += activeBoardGameSave->m_isGameDataLoaded ? "BOARD LOADED" : "BOARD NOT LOADED";
if (activeBoardMetadata->m_needsSync)
{
gameBoardMetadataDisplay += " (NEEDS SYNC)";
}
gameBoardMetadataDisplay += " (Last Modified: " + FormatLocalTimeFromDateTime(activeBoardMetadata->m_lastModified) + ")";
}
else
{
if (gameSaveManager->IsActiveBoardDirty)
{
gameBoardMetadataDisplay += "BOARD NOT SAVED";
}
else
{
gameBoardMetadataDisplay += "BOARD NOT STARTED";
}
}
m_gameBoardMetadataFont->DrawString(spriteBatch.get(), gameBoardMetadataDisplay->Data(), c_gameSaveMetadata_UpperLeft, Colors::White, 0.0f, XMFLOAT2(0, 0), c_gameSaveMetadata_Scale);
// Draw active board dev metadata (sync status/mode)
if (m_isGameSaveManagerInitialized)
{
Platform::String^ devModeMetadata = "Sync Mode: ";
if (gameSaveManager->IsSyncOnDemand)
{
devModeMetadata += "Sync-On-Demand";
}
else
{
devModeMetadata += "Full Sync";
}
devModeMetadata += " Remaining Quota: " + gameSaveManager->RemainingQuotaInBytes.ToString() + " bytes";
m_gameBoardMetadataFont->DrawString(spriteBatch.get(), devModeMetadata->Data(), c_gameSaveAdditionalMetadata_UpperLeft, Colors::White, 0.0f, XMFLOAT2(0, 0), c_gameSaveMetadata_Scale);
}
else
{
m_gameBoardMetadataFont->DrawString(spriteBatch.get(), L"Sync Status: Not Initialized", c_gameSaveAdditionalMetadata_UpperLeft);
}
// Draw current score
auto scoreColor = m_isOverLimitOnLetters ? Colors::Red : Colors::White;
gameFont->DrawString(spriteBatch.get(), m_score.ToString()->Data(), c_currentScore_UpperLeft, scoreColor, 0.0f, XMFLOAT2(0, 0), c_currentScore_Scale);
m_gameBoardMetadataFont->DrawString(spriteBatch.get(), L"SCORE", c_currentScoreLabel_UpperLeft);
// Draw remaining letters count
if (m_lettersRemaining.size() >= 26)
{
XMFLOAT2 letterPosition = c_lettersRemaining_UpperLeft;
for (wchar_t letter = L'A'; letter <= L'Z'; ++letter)
{
auto letterIndex = letter - L'A';
auto lettersRemaining = m_lettersRemaining[letterIndex];
auto letterValue = c_letterValues[letterIndex];
Platform::String^ countStr = letter + "=" + letterValue.ToString() + "(" + lettersRemaining.ToString() + ")";
auto countColor = c_lettersRemaining_Color;
if (lettersRemaining < 0)
{
countColor = Colors::Red;
}
else if (lettersRemaining == 0)
{
countColor = Colors::Yellow;
}
m_gameBoardLettersRemainingFont->DrawString(spriteBatch.get(), countStr->Data(), letterPosition, countColor, 0.0f, XMFLOAT2(0, 0), c_lettersRemaining_Scale);
// Get next letter position
if ((letterIndex + 1) % 9 == 0)
{
letterPosition.x = c_lettersRemaining_UpperLeft.x;
letterPosition.y += c_lettersRemaining_LetterOffset.y;
}
else
{
letterPosition.x += c_lettersRemaining_LetterOffset.x;
}
}
}
// Draw help text for remaining letters section
Platform::String^ lettersRemainingHelp = "Letter = X pts (# remaining)";
XMFLOAT2 lettersRemainingHelpPosition = c_lettersRemainingHelp_Center;
auto lettersRemainingHelpSize = m_gameBoardLettersRemainingFont->MeasureString(lettersRemainingHelp->Data());
XMFLOAT2 lettersRemainingHelpOrigin = XMFLOAT2(XMVectorGetX(lettersRemainingHelpSize) / 2.0f, m_gameBoardLettersRemainingFont->GetLineSpacing() / 2.0f);
m_gameBoardLettersRemainingFont->DrawString(spriteBatch.get(), lettersRemainingHelp->Data(), c_lettersRemainingHelp_Center, c_lettersRemaining_Color, 0.0f, lettersRemainingHelpOrigin);
// Draw tile cursor
if (!m_menuActive)
{
XMFLOAT2 cursorCenter = XMFLOAT2(c_letterTileFirstTile_Center.x + (c_letterTile_CenterOffset.x * m_cursorPosition.x), c_letterTileFirstTile_Center.y + (c_letterTile_CenterOffset.y * m_cursorPosition.y));
spriteBatch->Draw(m_cursor->GetResourceViewTemporary(), cursorCenter, nullptr, Colors::White, 0.0f, XMFLOAT2(float(m_cursor->Width() / 2), float(m_cursor->Height() / 2)));
}
// Draw placed letters
for (uint32_t j = 0; j < activeBoard.m_boardHeight; ++j)
{
for (uint32_t i = 0; i < activeBoard.m_boardWidth; ++i)
{
XMFLOAT2 tileCenter = XMFLOAT2(c_letterTileFirstTile_Center.x + (c_letterTile_CenterOffset.x * i), c_letterTileFirstTile_Center.y + (c_letterTile_CenterOffset.y * j));
auto currentTile = activeBoard.GetGameTile(XMUINT2(i, j));
if (currentTile.m_placed)
{
if (currentTile.m_letter)
{
// draw letter (centered on tile)
Platform::String^ letter = currentTile.m_letter.ToString();
XMVECTOR letterSize = m_gameBoardTileFont->MeasureString(letter->Data());
XMFLOAT2 letterOrigin = XMFLOAT2(XMVectorGetX(letterSize) / 2.0f + 6.0f, XMVectorGetY(letterSize) / 2.0f);
if (letter == "Q")
{
letterOrigin.x += 2.0f; // correct some display issues
}
m_gameBoardTileFont->DrawString(spriteBatch.get(), letter->Data(), tileCenter, Colors::Pink, 0.0f, letterOrigin, 0.75f);
// draw letter value (top-left-justified, offset from tile center)
Platform::String^ letterValue = c_letterValues[letter->Data()[0] - L'A'].ToString();
XMFLOAT2 letterValuePosition = XMFLOAT2(tileCenter.x + c_letterTileValue_OffsetFromTileCenter.x, tileCenter.y + c_letterTileValue_OffsetFromTileCenter.y);
XMVECTOR letterValueSize = m_gameBoardTileValueFont->MeasureString(letterValue->Data());
float letterValueScale = 0.45f;
m_gameBoardTileValueFont->DrawString(spriteBatch.get(), letterValue->Data(), letterValuePosition, Colors::Yellow, 0.0f, XMFLOAT2(0, 0), letterValueScale);
}
else
{
// draw the non-alphabetic texture
}
}
// draw word arrows
auto trackerTile = GetWordTrackerTile(XMUINT2(i, j));
if (trackerTile.m_wordRight)
{
XMFLOAT2 horizontalWordLinkerCenter = XMFLOAT2(c_wordLinkFirstHorizontal_Center.x + (c_letterTile_CenterOffset.x * i), c_wordLinkFirstHorizontal_Center.y + (c_letterTile_CenterOffset.y * j));
spriteBatch->Draw(m_hortizontalWordLinker->GetResourceViewTemporary(), horizontalWordLinkerCenter, nullptr, Colors::White, 0.0f, XMFLOAT2(float(m_hortizontalWordLinker->Width() / 2), float(m_hortizontalWordLinker->Height() / 2)));
}
if (trackerTile.m_wordDown)
{
XMFLOAT2 verticalWordLinkerCenter = XMFLOAT2(c_wordLinkFirstVertical_Center.x + (c_letterTile_CenterOffset.x * i), c_wordLinkFirstVertical_Center.y + (c_letterTile_CenterOffset.y * j));
spriteBatch->Draw(m_verticalWordLinker->GetResourceViewTemporary(), verticalWordLinkerCenter, nullptr, Colors::White, 0.0f, XMFLOAT2(float(m_verticalWordLinker->Width() / 2), float(m_verticalWordLinker->Height() / 2)));
}
}
}
// Draw input control help
bool displayGamepadControls = true;
#ifndef _XBOX_ONE // current Xbox game board background already has controls baked on to it
XMFLOAT2 controlHelpPosition = c_inputControlsHelp_UpperLeft;
displayGamepadControls = InputState::IsAnyGamepadConnected();
if (displayGamepadControls)
{
// draw save slot controls
spriteBatch->Draw(m_saveSlotLeftControl->GetResourceViewTemporary(), c_saveSlotLeftControlHelp_Center, nullptr, Colors::White, 0.0f, XMFLOAT2(float(m_saveSlotLeftControl->Width() / 2), float(m_saveSlotLeftControl->Height() / 2)));
spriteBatch->Draw(m_saveSlotRightControl->GetResourceViewTemporary(), c_saveSlotRightControlHelp_Center, nullptr, Colors::White, 0.0f, XMFLOAT2(float(m_saveSlotRightControl->Width() / 2), float(m_saveSlotRightControl->Height() / 2)));
// draw swap letter control
spriteBatch->Draw(m_swapLetterControl->GetResourceViewTemporary(), controlHelpPosition);
controlHelpPosition.x += float(m_swapLetterControl->Width());
Platform::String^ helpText = " Swap Letter";
m_gameBoardControlsHelpFont->DrawString(spriteBatch.get(), helpText->Data(), controlHelpPosition, Colors::SandyBrown, 0.0f, XMFLOAT2(0, 0), c_inputControlsHelp_Scale);
controlHelpPosition.x += XMVectorGetX(m_gameBoardControlsHelpFont->MeasureString(helpText->Data())) * c_inputControlsHelp_Scale + 40.f;
// draw cursor movement control
spriteBatch->Draw(m_moveCursorControl->GetResourceViewTemporary(), controlHelpPosition);
controlHelpPosition.x += float(m_moveCursorControl->Width());
helpText = " Move Cursor";
m_gameBoardControlsHelpFont->DrawString(spriteBatch.get(), helpText->Data(), controlHelpPosition, Colors::SandyBrown, 0.0f, XMFLOAT2(0, 0), c_inputControlsHelp_Scale);
controlHelpPosition.x += XMVectorGetX(m_gameBoardControlsHelpFont->MeasureString(helpText->Data())) * c_inputControlsHelp_Scale + 40.f;
// draw clear letter button
spriteBatch->Draw(m_clearLetterControl->GetResourceViewTemporary(), controlHelpPosition);
controlHelpPosition.x += float(m_clearLetterControl->Width());
helpText = " Clear Letter";
m_gameBoardControlsHelpFont->DrawString(spriteBatch.get(), helpText->Data(), controlHelpPosition, Colors::SandyBrown, 0.0f, XMFLOAT2(0, 0), c_inputControlsHelp_Scale);
controlHelpPosition.x += XMVectorGetX(m_gameBoardControlsHelpFont->MeasureString(helpText->Data())) * c_inputControlsHelp_Scale + 40.f;
// draw menu control
spriteBatch->Draw(m_menuControl->GetResourceViewTemporary(), controlHelpPosition);
controlHelpPosition.x += float(m_menuControl->Width());
helpText = " Cycle Commands List";
m_gameBoardControlsHelpFont->DrawString(spriteBatch.get(), helpText->Data(), controlHelpPosition, Colors::SandyBrown, 0.0f, XMFLOAT2(0, 0), c_inputControlsHelp_Scale);
}
else
{
// draw save slot keys
Platform::String^ helpText = "[1-9]: Select Save Slot";
// draw cursor movement keys
helpText += " Arrows: Move Cursor";
// draw letter keys
helpText += " [A-Z]: Place Letter";
// draw clear letter key
helpText += " [Del/Spc]: Clear Letter";
// draw log scroll keys
helpText += " [PgUp/PgDn]: Scroll Log";
m_gameBoardControlsHelpFont->DrawString(spriteBatch.get(), helpText->Data(), controlHelpPosition, Colors::SandyBrown, 0.0f, XMFLOAT2(0, 0), c_inputControlsHelp_Scale);
}
#endif
// Draw game debug log
auto logPosition = XMFLOAT2(c_debugLog_Region.X, c_debugLog_Region.Y);
size_t maxDisplayLines = static_cast<size_t>(c_debugLog_Region.Height / m_logFontHeight);
auto logIndexSize = Log::g_displayLog.size();
auto logIndexBegin = size_t(0);
auto logIndexEnd = logIndexSize - 1;
if (m_logLineBegin > 0)
{
// no auto-scrolling, display starting at requested line number
logIndexBegin = m_logLineBegin - 1;
logIndexEnd = std::min(logIndexEnd, logIndexBegin + maxDisplayLines - 1);
}
else if (logIndexSize > maxDisplayLines)
{
// auto-scroll
logIndexBegin = logIndexSize - maxDisplayLines;
}
for (auto i = logIndexBegin; i <= logIndexEnd; ++i)
{
m_logFont->DrawString(spriteBatch.get(), Log::g_displayLog[i]->Data(), logPosition);
logPosition.y += m_logFontHeight;
}
// Draw scroll indicators
if (logIndexBegin > 0)
{
if (displayGamepadControls)
{
spriteBatch->Draw(m_logScrollUpControl->GetResourceViewTemporary(), c_debugLogScrollUpIcon_Center, nullptr, Colors::White, 0.0f, XMFLOAT2(float(m_logScrollUpControl->Width() / 2), float(m_logScrollUpControl->Height() / 2)));
}
else
{
wchar_t logScrollUpKeyString[] = L"PgUp";
XMVECTOR logScrollUpKeySize = m_gameBoardControlsHelpFont->MeasureString(logScrollUpKeyString);
XMFLOAT2 logScrollUpKeyOrigin = XMFLOAT2(XMVectorGetX(logScrollUpKeySize) / 2.f, m_gameBoardControlsHelpFont->GetLineSpacing() / 2.f);
m_gameBoardControlsHelpFont->DrawString(spriteBatch.get(), logScrollUpKeyString, c_debugLogScrollUpIcon_Center, Colors::SandyBrown, 0.0f, logScrollUpKeyOrigin, c_inputControlsHelp_Scale);
}
}
if (m_logLineBegin > 0)
{
if (displayGamepadControls)
{
spriteBatch->Draw(m_logScrollDownControl->GetResourceViewTemporary(), c_debugLogScrollDownIcon_Center, nullptr, Colors::White, 0.0f, XMFLOAT2(float(m_logScrollDownControl->Width() / 2), float(m_logScrollDownControl->Height() / 2)));
}
else
{
wchar_t logScrollDownKeyString[] = L"PgDn";
XMVECTOR logScrollDownKeySize = m_gameBoardControlsHelpFont->MeasureString(logScrollDownKeyString);
XMFLOAT2 logScrollDownKeyOrigin = XMFLOAT2(XMVectorGetX(logScrollDownKeySize) / 2.f, m_gameBoardControlsHelpFont->GetLineSpacing() / 2.f);
m_gameBoardControlsHelpFont->DrawString(spriteBatch.get(), logScrollDownKeyString, c_debugLogScrollDownIcon_Center, Colors::SandyBrown, 0.0f, logScrollDownKeyOrigin, c_inputControlsHelp_Scale);
}
}
spriteBatch->End();
}