#include "xna/xna-dx.hpp" namespace xna { Game::Game() { impl = unew(); services = snew(); auto iservice = reinterpret_pointer_cast(services); contentManager = snew(services, ""); contentManager->mainGameService = iservice; gameWindow = snew(); gameWindow->impl->Color(146, 150, 154); gameWindow->Title("XN65"); gameWindow->impl->Size( GraphicsDeviceManager::DefaultBackBufferWidth, GraphicsDeviceManager::DefaultBackBufferHeight, false); gameComponents = snew(); IsFixedTimeStep(isFixedTimeStep); TargetElapsedTime(targetElapsedTime); } void Game::Exit() { gameWindow->impl->Close(); } int Game::StartGameLoop() { MSG msg{}; impl->_stepTimer = xna::StepTimer(); do { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { Tick(); } } while (msg.message != WM_QUIT); EndRun(); return static_cast(msg.wParam); } void Game::Tick() { impl->_stepTimer.Tick([&]() { const auto elapsed = impl->_stepTimer.GetElapsedSeconds(); const auto total = impl->_stepTimer.GetTotalSeconds(); const auto elapsedTimeSpan = TimeSpan::FromSeconds(elapsed); const auto totalTimeSpan = TimeSpan::FromSeconds(total); currentGameTime.ElapsedGameTime = elapsedTimeSpan; currentGameTime.TotalGameTime = totalTimeSpan; Update(currentGameTime); }); BeginDraw(); Draw(currentGameTime); EndDraw(); } int Game::Run() { if (isRunning) return EXIT_FAILURE; try { if (!gameWindow->impl->Create()) { Exception::Throw(Exception::FAILED_TO_CREATE); return false; } Initialize(); if (graphicsDevice == nullptr) { MessageBox(nullptr, "O dispositivo gráfico não foi inicializado corretamente", "XN65", MB_OK); return EXIT_FAILURE; } isRunning = true; BeginRun(); return StartGameLoop(); } catch (std::exception& e) { MessageBox(nullptr, e.what(), "XN65", MB_OK); return EXIT_FAILURE; } } void Game::Initialize() { Keyboard::Initialize(); Mouse::Initialize(gameWindow->Handle()); GamePad::Initialize(); AudioEngine::Initialize(); LoadContent(); } void Game::Draw(GameTime const& gameTime) { if (enabledGameComponents && !drawableGameComponents.empty()) { const auto count = drawableGameComponents.size(); if (count != drawableGameComponentsCount && gameComponents->AutoSort) { GameComponentCollection::DrawSort(drawableGameComponents); drawableGameComponentsCount = count; } for (size_t i = 0; i < count; ++i) { auto& component = drawableGameComponents[i]; if (!component) continue; auto drawable = reinterpret_pointer_cast(component); if (drawable && drawable->Visible()) drawable->Draw(gameTime); } drawableGameComponents.clear(); } graphicsDevice->Present(); } void Game::Update(GameTime const& gameTime) { audioEngine->Update(); if (enabledGameComponents && gameComponents->Count() > 0) { const auto count = gameComponents->Count(); for (size_t i = 0; i < count; ++i) { auto component = gameComponents->At(i); if (!component) continue; if (component->Type() == GameComponentType::Drawable) { drawableGameComponents.push_back(component); } auto updatable = reinterpret_pointer_cast(component); if(updatable && updatable->Enabled()) updatable->Update(gameTime); } } } sptr Game::Window() { return gameWindow; } sptr Game::Device() const { return graphicsDevice; } sptr Game::Components() const { return gameComponents; } sptr Game::Services() { return services; } sptr Game::Content() const { return contentManager; } void Game::EnableGameComponents(bool value) { enabledGameComponents = value; } void Game::AttachGraphicsDevice(sptr const& device) { graphicsDevice = device; } void Game::ResizeWindow(int width, int heigth) { const auto windowBounds = gameWindow->ClientBounds(); if (windowBounds.Width != width || windowBounds.Height != heigth) { gameWindow->impl->Size( width, heigth); gameWindow->impl->Update(); } } void Game::Content(sptr const& value) { contentManager = value; auto iservice = reinterpret_pointer_cast(services); contentManager->mainGameService = iservice; } void Game::IsFixedTimeStep(bool value) { isFixedTimeStep = value; impl->_stepTimer.SetFixedTimeStep(value); } bool Game::IsMouseVisible() const { if (!Mouse::impl) return false; return Mouse::impl->_dxMouse->IsVisible(); } void Game::IsMouseVisible(bool value) { if (!Mouse::impl) return; Mouse::impl->_dxMouse->SetVisible(value); } void Game::TargetElapsedTime(TimeSpan const& value) { if (!isFixedTimeStep) return; const auto ticks = targetElapsedTime.Ticks(); impl->_stepTimer.SetTargetElapsedTicks(ticks); } void Game::ResetElapsedTime() const { impl->_stepTimer.ResetElapsedTime(); } void Game::RunOneFrame() { Tick(); } }