1 //// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
2 //// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
3 //// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
4 //// PARTICULAR PURPOSE.
6 //// Copyright (c) Microsoft Corporation. All rights reserved
9 #include "SoundDriver.h"
11 #include "windows.ui.xaml.media.dxinterop.h"
12 #include "GameStateMachine.h"
14 using namespace Microsoft::WRL;
15 using namespace Windows::Foundation;
16 using namespace Windows::Foundation::Collections;
17 using namespace Windows::UI::Core;
18 using namespace Windows::UI::ViewManagement;
20 using namespace Windows::UI::ApplicationSettings;
21 using namespace Windows::UI::Popups;
22 using namespace Windows::UI::Xaml::Controls;
23 using namespace Windows::Graphics::Display;
24 using namespace DirectX;
26 using namespace concurrency;
29 using namespace BasicSprites;
30 using namespace boost;
31 namespace ShootingGame {
32 const float GameMain::BACKBUFFER_WIDTH = 320.0f;
33 const float GameMain::BACKBUFFER_HEIGHT = 240.0f;
36 GameMain::GameMain() : backBufferViewPort_(0.0f,0.0f,BACKBUFFER_WIDTH,BACKBUFFER_HEIGHT) , isDestroy_(true),state_(this)
38 // GameStateMachine machine;
39 soundDriver_.reset(new sf::SoundDriver());
40 soundManager_.reset(new sf::SoundManager(*soundDriver_.get()));
43 //soundThread_ = std::thread(
46 // ExecuteSoundThread();
55 //if(soundThread_.joinable())
57 // soundThread_.join();
61 void GameMain::CreateDeviceIndependentResources()
63 DirectXBase::CreateDeviceIndependentResources();
65 // Create the performance throttler.
67 autoThrottle_ = ref new ::AutoThrottle(1.0f / 60.0f);
70 void GameMain::Initialize(
71 _In_ Windows::UI::Core::CoreWindow^ window,
72 _In_ Windows::UI::Xaml::Controls::SwapChainBackgroundPanel^ swapChainPanel,
76 panel_ = swapChainPanel;
77 Initialize(window,dpi);
79 state_.ProcessEvent(Event::Init());
82 void GameMain::CreateDeviceResources()
84 DirectXBase::CreateDeviceResources();
86 // Create the sprite batch.
88 spriteBatch_ = ref new BasicSprites::SpriteBatch();
89 unsigned int capacity = 1024;
90 if (m_featureLevel < D3D_FEATURE_LEVEL_9_3)
92 capacity = min(Parameters::MaximumCapacityCompatible, capacity);
94 spriteBatch_->Initialize(
99 // Create the Sample Overlay.
101 sampleOverlay_ = ref new ::SampleOverlay();
103 sampleOverlay_->Initialize(
107 m_dwriteFactory.Get(),
108 L"
\83V
\83\85\81[
\83e
\83B
\83\93\83O
\83Q
\81[
\83\80"
115 void GameMain::CreateWindowSizeDependentResources()
117 // DirectXBase::CreateWindowSizeDependentResources();
118 // Store the window bounds so the next time we get a SizeChanged event we can
119 // avoid rebuilding everything if the size is identical.
120 m_windowBounds = m_window->Bounds;
122 // If the swap chain already exists, resize it.
123 if(m_swapChain != nullptr)
126 m_swapChain->ResizeBuffers(2, 0, 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0)
129 // Otherwise, create a new one.
132 // Allocate a descriptor.
133 DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
134 scale_ = floorf(m_window->Bounds.Width * m_dpi / ( 96.0f * BACKBUFFER_WIDTH));
135 swapChainDesc.Width = static_cast<UINT>(m_window->Bounds.Width * m_dpi / 96.0f); // Can not use 0 to get the default on Composition SwapChain
136 swapChainDesc.Height = static_cast<UINT>(m_window->Bounds.Height * m_dpi / 96.0f);
137 swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
138 swapChainDesc.Stereo = false;
139 swapChainDesc.SampleDesc.Count = 1; // don't use multi-sampling
140 swapChainDesc.SampleDesc.Quality = 0;
141 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
142 swapChainDesc.BufferCount = 2; // use double buffering to enable flip
143 swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
144 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all Metro style apps must use this SwapEffect
145 swapChainDesc.Flags = 0;
147 // Once the desired swap chain description is configured, it must be created on the same adapter as our D3D Device
149 // First, retrieve the underlying DXGI Device from the D3D Device.
150 ComPtr<IDXGIDevice1> dxgiDevice;
152 m_d3dDevice.As(&dxgiDevice)
155 // Identify the physical adapter (GPU or card) this device is running on.
156 ComPtr<IDXGIAdapter> dxgiAdapter;
158 dxgiDevice->GetAdapter(&dxgiAdapter)
161 // And obtain the factory object that created it.
162 ComPtr<IDXGIFactory2> dxgiFactory;
164 dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
167 // Obtain the final swap chain for this window from the DXGI factory.
169 dxgiFactory->CreateSwapChainForComposition(
172 nullptr, // allow on all displays
177 ComPtr<ISwapChainBackgroundPanelNative> dxRootPanelAsNative;
179 // set the swap chain on the SwapChainBackgroundPanel
180 reinterpret_cast<IUnknown*>(panel_)->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void**)&dxRootPanelAsNative);
183 dxRootPanelAsNative->SetSwapChain(m_swapChain.Get())
186 // Ensure that DXGI does not queue more than one frame at a time. This both reduces
187 // latency and ensures that the application will only render after each VSync, minimizing
188 // power consumption.
190 dxgiDevice->SetMaximumFrameLatency(1)
195 // Obtain the backbuffer for this window which will be the final 3D rendertarget.
196 ComPtr<ID3D11Texture2D> backBuffer;
198 m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
201 // Create a view interface on the rendertarget to use on bind.
203 m_d3dDevice->CreateRenderTargetView(
210 // Cache the rendertarget dimensions in our helper class for convenient use.
211 D3D11_TEXTURE2D_DESC backBufferDesc = {0};
212 backBuffer->GetDesc(&backBufferDesc);
213 m_renderTargetSize.Width = static_cast<float>(backBufferDesc.Width);
214 m_renderTargetSize.Height = static_cast<float>(backBufferDesc.Height);
216 // Create a descriptor for the depth/stencil buffer.
217 CD3D11_TEXTURE2D_DESC depthStencilDesc(
218 DXGI_FORMAT_D24_UNORM_S8_UINT,
219 backBufferDesc.Width,
220 backBufferDesc.Height,
223 D3D11_BIND_DEPTH_STENCIL
226 // Allocate a 2-D surface as the depth/stencil buffer.
227 ComPtr<ID3D11Texture2D> depthStencil;
229 m_d3dDevice->CreateTexture2D(
236 // Create a DepthStencil view on this surface to use on bind.
238 m_d3dDevice->CreateDepthStencilView(
240 &CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D),
245 // Create a viewport descriptor of the full window size.
246 swapChainViewPort_.Width = static_cast<float>(backBufferDesc.Width);
247 swapChainViewPort_.Height = static_cast<float>(backBufferDesc.Height);
249 // Set the current viewport using the descriptor.
250 m_d3dContext->RSSetViewports(1, &swapChainViewPort_);
252 // Now we set up the Direct2D render target bitmap linked to the swapchain.
253 // Whenever we render to this bitmap, it will be directly rendered to the
254 // swapchain associated with the window.
255 D2D1_BITMAP_PROPERTIES1 bitmapProperties =
257 D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
258 PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
263 // Direct2D needs the dxgi version of the backbuffer surface pointer.
264 ComPtr<IDXGISurface> dxgiBackBuffer;
266 m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
269 // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
271 m_d2dContext->CreateBitmapFromDxgiSurface(
272 dxgiBackBuffer.Get(),
278 // So now we can set the Direct2D render target.
279 m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
281 // Set D2D text anti-alias mode to Grayscale to ensure proper rendering of text on intermediate surfaces.
282 m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
284 // Randomly generate some non-interactive asteroids to fit the screen.
286 sampleOverlay_->UpdateForWindowSizeChange();
287 //
\83o
\83b
\83N
\83o
\83b
\83t
\83@
\82Ì
\8dì
\90¬
288 //ComPtr<ID3D11Texture2D> backBuffer;
290 // m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
292 //D3D11_TEXTURE2D_DESC backBufferDesc = {0};
293 //backBuffer->GetDesc(&backBufferDesc);
295 D3D11_TEXTURE2D_DESC desc = {0};
298 desc.Format = backBufferDesc.Format;
300 desc.SampleDesc.Count = 1;
301 desc.SampleDesc.Quality = 0;
303 desc.Usage = D3D11_USAGE_DEFAULT;
304 desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
305 // desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
307 DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D(&desc,NULL,&backBuffer_));
309 DX::ThrowIfFailed(m_d3dDevice->CreateRenderTargetView(backBuffer_.Get(),0,&backBufferRenderTargetView_));
311 // //
\90[
\93x
\83o
\83b
\83t
\83@
\82Ì
\8dì
\90¬
312 // D3D11_TEXTURE2D_DESC depth = {} ;
313 // depth.Width = desc.Width;//rc.right - rc.left;client_width_;
314 // depth.Height = desc.Height;//rc.bottom - rc.top;client_height_;
315 // depth.MipLevels = 1;
316 // depth.ArraySize = 1;
317 // depth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
318 // depth.SampleDesc.Count = 1;
319 // depth.SampleDesc.Quality = 0;
320 // depth.Usage = D3D11_USAGE_DEFAULT;
321 // depth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
322 // depth.CPUAccessFlags = 0;
323 // depth.MiscFlags = 0;
324 // ComPtr<ID3D11Texture2D> depthT;
325 //DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D( &depth, NULL, &depthT ));
327 // D3D11_DEPTH_STENCIL_VIEW_DESC dsv = {};
328 // dsv.Format = depth.Format;
329 // dsv.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
330 // dsv.Texture2D.MipSlice = 0;
332 //DX::ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( depthT.Get(), &dsv, &backBufferDepthStencilView_ ));
334 spriteBatch_->AddTexture(backBuffer_.Get(),float2());
336 //
\90[
\93x
\83X
\83e
\83\93\83V
\83\8b\83X
\83e
\81[
\83g
\82ð
\8dì
\90¬
\82·
\82é
337 //D3D11_DEPTH_STENCIL_DESC ddsDesc;
338 //::ZeroMemory( &ddsDesc, sizeof( ddsDesc ) );
339 //ddsDesc.DepthEnable = TRUE; //
\90[
\93x
\83e
\83X
\83g
\82ð
\8eg
\97p
\82·
\82é
340 //ddsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
341 //ddsDesc.DepthFunc = D3D11_COMPARISON_LESS;
342 //ddsDesc.StencilEnable = FALSE;
343 //DX::ThrowIfFailed(m_d3dDevice->CreateDepthStencilState( &ddsDesc, &backBufferDepthStencilState_ ));
347 void GameMain::Update(float timeTotal, float timeDelta)
349 // Update the performance throttler.
351 auto control = autoThrottle_->Update(timeDelta);
352 state_.ProcessEvent(Event::Update());
353 //if (control == FrameWorkload::Increase)
355 // m_numParticlesToDraw += SampleSettings::Performance::ParticleCountDelta;
357 //if (control == FrameWorkload::Decrease)
359 // m_numParticlesToDraw -= SampleSettings::Performance::ParticleCountDelta;
361 //if (control != FrameWorkload::Maintain)
363 // m_numParticlesToDraw = max(SampleSettings::Performance::ParticleCountMin, min(SampleSettings::Performance::ParticleCountMax, m_numParticlesToDraw));
364 // if (m_featureLevel < D3D_FEATURE_LEVEL_9_3)
366 // m_numParticlesToDraw = min(static_cast<int>(Parameters::MaximumCapacityCompatible - SampleSettings::NumAsteroids - 1), m_numParticlesToDraw);
370 // Update the non-interactive asteroids.
371 // Their behavior is to drift across the window with a fixed translational and rotational
372 // velocity. Upon crossing a boundary outside the window, their position wraps.
374 //for (auto asteroid = m_asteroidData.begin(); asteroid != m_asteroidData.end(); asteroid++)
376 // static const float border = 100.0f;
377 // asteroid->pos = asteroid->pos + asteroid->vel * timeDelta;
378 // if (asteroid->vel.x < 0)
380 // if (asteroid->pos.x < -border)
382 // asteroid->pos.x = m_windowBounds.Width + border;
387 // if (asteroid->pos.x > m_windowBounds.Width + border)
389 // asteroid->pos.x = -border;
392 // if (asteroid->vel.y < 0)
394 // if (asteroid->pos.y < -border)
396 // asteroid->pos.y = m_windowBounds.Height + border;
401 // if (asteroid->pos.y > m_windowBounds.Height + border)
403 // asteroid->pos.y = -border;
407 // asteroid->rot += asteroid->rotVel * timeDelta;
408 // if (asteroid->rot > static_cast<float>(M_PI))
410 // asteroid->rot -= 2.0f * static_cast<float>(M_PI);
412 // if (asteroid->rot < static_cast<float>(-M_PI))
414 // asteroid->rot += 2.0f * static_cast<float>(M_PI);
418 //// Update the interactive particles.
419 //// Their behavior is to be gravitationally attracted to two oscillating gravity
420 //// wells and repelled by any pressed pointer points. Upon reaching the edge of
421 //// the window, the particles bounce.
423 //// Add two gravity wells that move throughout the window.
424 //float2 wellPositions[] =
427 // (1.0f + 0.8f * cosf(timeTotal / (2.0f * static_cast<float>(M_PI)) + 3.0f)) * m_windowBounds.Width / 2.0f,
428 // (1.0f + 0.8f * sinf(timeTotal / 5.0f)) * m_windowBounds.Height / 2.0f
431 // (1.0f + 0.8f * cosf(timeTotal / static_cast<float>(M_PI * M_PI) + 1.0f)) * m_windowBounds.Width / 2.0f,
432 // (1.0f + 0.8f * sinf(timeTotal / static_cast<float>(M_PI))) * m_windowBounds.Height / 2.0f
436 //for (auto particle = m_particleData.begin(); particle != m_particleData.begin() + m_numParticlesToDraw; particle++)
438 // if (particle->pos.x < 0)
440 // particle->vel.x = abs(particle->vel.x);
442 // if (particle->pos.x > m_windowBounds.Width)
444 // particle->vel.x = -abs(particle->vel.x);
446 // if (particle->pos.y < 0)
448 // particle->vel.y = abs(particle->vel.y);
450 // if (particle->pos.y > m_windowBounds.Height)
452 // particle->vel.y = -abs(particle->vel.y);
455 // for (auto repulsor = m_repulsors.begin(); repulsor != m_repulsors.end(); repulsor++)
457 // float2 delta = particle->pos - repulsor->second;
458 // float deltaLength = length(delta) + 24.0f; // Offset length to avoid division by zero.
459 // float deltaLengthCubed = deltaLength * deltaLength * deltaLength;
460 // particle->vel = particle->vel + SampleSettings::Physics::Gravity * timeDelta * delta / deltaLengthCubed;
463 // for (int i = 0; i < ARRAYSIZE(wellPositions); i++)
465 // float gravitySign = 1.0f;
466 // if ((static_cast<int>(timeTotal / 2.0f) + 1) % 10 == 0)
468 // // Every 20 seconds, "explode" the gravity wells for 2 seconds.
469 // gravitySign = -1.0f;
471 // float2 delta = wellPositions[i] - particle->pos;
472 // float deltaLength = length(delta) + 24.0f;
473 // float deltaLengthCubed = deltaLength * deltaLength * deltaLength;
474 // particle->vel = particle->vel + gravitySign * 0.2f * SampleSettings::Physics::Gravity * timeDelta * delta / deltaLengthCubed;
477 // particle->vel = particle->vel * (1.0f - SampleSettings::Physics::Damping);
479 // // Add random noise to the velocity to prevent particles from locking together.
481 // particle->vel.x += RandFloat(-0.5f, 0.5f);
482 // particle->vel.y += RandFloat(-0.5f, 0.5f);
484 // particle->pos = particle->pos + particle->vel * timeDelta;
488 void GameMain::Render()
490 state_.ProcessEvent(Event::Render());
494 //// Draw the non-interactive asteroids.
496 //for (auto asteroid = m_asteroidData.begin(); asteroid != m_asteroidData.end(); asteroid++)
498 // spriteBatch_->Draw(
501 // PositionUnits::DIPs,
502 // float2(1.0f, 1.0f) * asteroid->scale,
503 // SizeUnits::Normalized,
504 // float4(0.8f, 0.8f, 1.0f, 1.0f),
509 //// Draw the interactive particles.
511 //for (auto particle = m_particleData.begin(); particle != m_particleData.begin() + m_numParticlesToDraw; particle++)
513 // float alpha = length(particle->vel) / 200.0f;
514 // spriteBatch_->Draw(
517 // PositionUnits::DIPs,
518 // float2(32.0f, 32.0f),
520 // float4(0.1f, 0.02f, 0.0f, alpha),
522 // BlendMode::Additive
530 float GameMain::RandFloat(float min, float max)
532 return (static_cast<float>(rand() % RAND_MAX) / static_cast<float>(RAND_MAX)) * (max - min) + min;
535 //
\83T
\83E
\83\93\83h
\8dÄ
\90¶
\83X
\83\8c\83b
\83h
536 void GameMain::ExecuteSoundThread()
538 //sf::com_init comInit;
540 soundManager_->Sequencer().Play();
543 soundDriver_->Render();
544 // Concurrency::wait(800);
545 // soundDriver_->Update();
546 // soundDriver_->Render();
550 void GameMain::StartSound()
554 //
\83T
\83E
\83\93\83h
\8dÄ
\90¶
\83X
\83\8c\83b
\83h
\82Ì
\8aJ
\8en
555 soundTask_ = task<void>(create_async([this]()
557 ExecuteSoundThread();
563 void GameMain::StopSound()
565 //
\83T
\83E
\83\93\83h
\8dÄ
\90¶
\83X
\83\8c\83b
\83h
\82Ì
\92â
\8e~
572 void GameMain::ClearScreen()
574 m_d3dContext->OMSetRenderTargets(
576 backBufferRenderTargetView_.GetAddressOf(),
577 nullptr//backBufferDepthStencilView_.Get()
579 // m_d3dContext->OMSetDepthStencilState(backBufferDepthStencilState_.Get(),0);
580 m_d3dContext->RSSetViewports(1, &backBufferViewPort_);
581 //m_d3dContext->RSSetState(
584 m_d3dContext->ClearRenderTargetView(
585 backBufferRenderTargetView_.Get(),
586 reinterpret_cast<float*>(&D2D1::ColorF(D2D1::ColorF::Black))
589 //m_d3dContext->ClearDepthStencilView(backBufferDepthStencilView_.Get(),D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL,1.0f,0);
593 void GameMain::RenderScreen()
595 m_d3dContext->OMSetRenderTargets(
597 m_renderTargetView.GetAddressOf(),
598 nullptr/*m_depthStencilView.Get()*/
601 m_d3dContext->RSSetViewports(1, &swapChainViewPort_);
604 m_d3dContext->ClearRenderTargetView(
605 m_renderTargetView.Get(),
606 reinterpret_cast<float*>(&D2D1::ColorF(D2D1::ColorF::MidnightBlue))
609 //m_d3dContext->ClearDepthStencilView(m_depthStencilView.Get(),D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL,1.0f,0);
611 spriteBatch_->Begin();
615 float4(m_window->Bounds.Width / 2.0f,m_window->Bounds.Height / 2.0f,0.0f,1.0f),
617 float2(1.0f, 1.0f) * scale_,
618 SizeUnits::Normalized,
619 float4(1.0f, 1.0f, 1.0f, 1.0f),
626 // Render the Sample Overlay.
627 sampleOverlay_->Render();
631 void GameMain::LoadTexture(const std::wstring& filename,ID3D11Texture2D** texPtrAddr)
633 // Load the sprite textures.
635 BasicLoader^ loader = ref new BasicLoader(m_d3dDevice.Get(), m_wicFactory.Get());
636 Platform::String^ f = ref new Platform::String(filename.c_str());