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 "MainPage.xaml.h"
12 using namespace Microsoft::WRL;
13 //using namespace Windows::Foundation;
14 //using namespace Windows::Foundation::Collections;
15 //using namespace Windows::UI::Core;
16 //using namespace Windows::UI::ViewManagement;
18 //using namespace Windows::UI::ApplicationSettings;
19 //using namespace Windows::UI::Popups;
20 //using namespace Windows::UI::Xaml::Controls;
21 //using namespace Windows::Graphics::Display;
22 using namespace DirectX;
24 using namespace concurrency;
25 using namespace BasicSprites;
27 namespace ShootingGame {
29 const float GameMain::BACKBUFFER_WIDTH = 320.0f;
30 const float GameMain::BACKBUFFER_HEIGHT = 240.0f;
34 :backBufferViewPort_(0.0f,0.0f,BACKBUFFER_WIDTH,BACKBUFFER_HEIGHT) , isDestroy_(true),state_(this),
35 eventHolder_(::CreateEventEx(NULL, NULL, 0, EVENT_MODIFY_STATE | SYNCHRONIZE))
37 // GameStateMachine machine;
38 soundDriver_.reset(new sf::SoundDriver());
39 soundManager_.reset(new sf::SoundManager(*soundDriver_.get()));
41 //soundThread_ = std::thread(
44 // ExecuteSoundThread();
53 //if(soundThread_.joinable())
55 // soundThread_.join();
59 void GameMain::CreateDeviceIndependentResources()
61 DirectXBase::CreateDeviceIndependentResources();
63 // Create the performance throttler.
65 autoThrottle_ = ref new ::AutoThrottle(1.0f / 60.0f);
68 void GameMain::Initialize(
69 _In_ Windows::UI::Core::CoreWindow^ window,
70 _In_ Windows::UI::Xaml::Controls::SwapChainBackgroundPanel^ swapChainPanel,
74 panel_ = swapChainPanel;
75 Initialize(window,dpi);
77 state_.ProcessEvent(Event::Init());
80 void GameMain::CreateDeviceResources()
82 DirectXBase::CreateDeviceResources();
84 // Create the sprite batch.
86 spriteBatch_ = ref new BasicSprites::SpriteBatch();
87 unsigned int capacity = 1024;
88 if (m_featureLevel < D3D_FEATURE_LEVEL_9_3)
90 capacity = min(Parameters::MaximumCapacityCompatible, capacity);
92 spriteBatch_->Initialize(
97 // Create the Sample Overlay.
99 sampleOverlay_ = ref new ::SampleOverlay();
101 sampleOverlay_->Initialize(
105 m_dwriteFactory.Get(),
106 L"
\83V
\83\85\81[
\83e
\83B
\83\93\83O
\83Q
\81[
\83\80"
113 void GameMain::CreateWindowSizeDependentResources()
115 // DirectXBase::CreateWindowSizeDependentResources();
116 // Store the window bounds so the next time we get a SizeChanged event we can
117 // avoid rebuilding everything if the size is identical.
118 m_windowBounds = m_window->Bounds;
120 // If the swap chain already exists, resize it.
121 if(m_swapChain != nullptr)
124 m_swapChain->ResizeBuffers(2, 0, 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0)
127 // Otherwise, create a new one.
130 // Allocate a descriptor.
131 DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
132 scale_ = floorf(m_window->Bounds.Width * m_dpi / ( 96.0f * BACKBUFFER_WIDTH));
133 swapChainDesc.Width = static_cast<UINT>(m_window->Bounds.Width * m_dpi / 96.0f); // Can not use 0 to get the default on Composition SwapChain
134 swapChainDesc.Height = static_cast<UINT>(m_window->Bounds.Height * m_dpi / 96.0f);
135 swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
136 swapChainDesc.Stereo = false;
137 swapChainDesc.SampleDesc.Count = 1; // don't use multi-sampling
138 swapChainDesc.SampleDesc.Quality = 0;
139 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
140 swapChainDesc.BufferCount = 2; // use double buffering to enable flip
141 swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
142 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all Metro style apps must use this SwapEffect
143 swapChainDesc.Flags = 0;
145 // Once the desired swap chain description is configured, it must be created on the same adapter as our D3D Device
147 // First, retrieve the underlying DXGI Device from the D3D Device.
148 ComPtr<IDXGIDevice1> dxgiDevice;
150 m_d3dDevice.As(&dxgiDevice)
153 // Identify the physical adapter (GPU or card) this device is running on.
154 ComPtr<IDXGIAdapter> dxgiAdapter;
156 dxgiDevice->GetAdapter(&dxgiAdapter)
159 // And obtain the factory object that created it.
160 ComPtr<IDXGIFactory2> dxgiFactory;
162 dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
165 // Obtain the final swap chain for this window from the DXGI factory.
167 dxgiFactory->CreateSwapChainForComposition(
170 nullptr, // allow on all displays
175 ComPtr<ISwapChainBackgroundPanelNative> dxRootPanelAsNative;
177 // set the swap chain on the SwapChainBackgroundPanel
178 reinterpret_cast<IUnknown*>(panel_)->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void**)&dxRootPanelAsNative);
181 dxRootPanelAsNative->SetSwapChain(m_swapChain.Get())
184 // Ensure that DXGI does not queue more than one frame at a time. This both reduces
185 // latency and ensures that the application will only render after each VSync, minimizing
186 // power consumption.
188 dxgiDevice->SetMaximumFrameLatency(1)
193 // Obtain the backbuffer for this window which will be the final 3D rendertarget.
194 ComPtr<ID3D11Texture2D> backBuffer;
196 m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
199 // Create a view interface on the rendertarget to use on bind.
201 m_d3dDevice->CreateRenderTargetView(
208 // Cache the rendertarget dimensions in our helper class for convenient use.
209 D3D11_TEXTURE2D_DESC backBufferDesc = {0};
210 backBuffer->GetDesc(&backBufferDesc);
211 m_renderTargetSize.Width = static_cast<float>(backBufferDesc.Width);
212 m_renderTargetSize.Height = static_cast<float>(backBufferDesc.Height);
214 // Create a descriptor for the depth/stencil buffer.
215 CD3D11_TEXTURE2D_DESC depthStencilDesc(
216 DXGI_FORMAT_D24_UNORM_S8_UINT,
217 backBufferDesc.Width,
218 backBufferDesc.Height,
221 D3D11_BIND_DEPTH_STENCIL
224 // Allocate a 2-D surface as the depth/stencil buffer.
225 ComPtr<ID3D11Texture2D> depthStencil;
227 m_d3dDevice->CreateTexture2D(
234 // Create a DepthStencil view on this surface to use on bind.
236 m_d3dDevice->CreateDepthStencilView(
238 &CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D),
243 // Create a viewport descriptor of the full window size.
244 swapChainViewPort_.Width = static_cast<float>(backBufferDesc.Width);
245 swapChainViewPort_.Height = static_cast<float>(backBufferDesc.Height);
247 // Set the current viewport using the descriptor.
248 m_d3dContext->RSSetViewports(1, &swapChainViewPort_);
250 // Now we set up the Direct2D render target bitmap linked to the swapchain.
251 // Whenever we render to this bitmap, it will be directly rendered to the
252 // swapchain associated with the window.
253 D2D1_BITMAP_PROPERTIES1 bitmapProperties =
255 D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
256 PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
261 // Direct2D needs the dxgi version of the backbuffer surface pointer.
262 ComPtr<IDXGISurface> dxgiBackBuffer;
264 m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
267 // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
269 m_d2dContext->CreateBitmapFromDxgiSurface(
270 dxgiBackBuffer.Get(),
276 // So now we can set the Direct2D render target.
277 m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
279 // Set D2D text anti-alias mode to Grayscale to ensure proper rendering of text on intermediate surfaces.
280 m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
282 // Randomly generate some non-interactive asteroids to fit the screen.
284 sampleOverlay_->UpdateForWindowSizeChange();
285 //
\83o
\83b
\83N
\83o
\83b
\83t
\83@
\82Ì
\8dì
\90¬
286 //ComPtr<ID3D11Texture2D> backBuffer;
288 // m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
290 //D3D11_TEXTURE2D_DESC backBufferDesc = {0};
291 //backBuffer->GetDesc(&backBufferDesc);
293 D3D11_TEXTURE2D_DESC desc = {0};
296 desc.Format = backBufferDesc.Format;
298 desc.SampleDesc.Count = 1;
299 desc.SampleDesc.Quality = 0;
301 desc.Usage = D3D11_USAGE_DEFAULT;
302 desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
303 // desc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
305 DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D(&desc,NULL,&backBuffer_));
307 DX::ThrowIfFailed(m_d3dDevice->CreateRenderTargetView(backBuffer_.Get(),0,&backBufferRenderTargetView_));
309 // //
\90[
\93x
\83o
\83b
\83t
\83@
\82Ì
\8dì
\90¬
310 // D3D11_TEXTURE2D_DESC depth = {} ;
311 // depth.Width = desc.Width;//rc.right - rc.left;client_width_;
312 // depth.Height = desc.Height;//rc.bottom - rc.top;client_height_;
313 // depth.MipLevels = 1;
314 // depth.ArraySize = 1;
315 // depth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
316 // depth.SampleDesc.Count = 1;
317 // depth.SampleDesc.Quality = 0;
318 // depth.Usage = D3D11_USAGE_DEFAULT;
319 // depth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
320 // depth.CPUAccessFlags = 0;
321 // depth.MiscFlags = 0;
322 // ComPtr<ID3D11Texture2D> depthT;
323 //DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D( &depth, NULL, &depthT ));
325 // D3D11_DEPTH_STENCIL_VIEW_DESC dsv = {};
326 // dsv.Format = depth.Format;
327 // dsv.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
328 // dsv.Texture2D.MipSlice = 0;
330 //DX::ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( depthT.Get(), &dsv, &backBufferDepthStencilView_ ));
332 spriteBatch_->AddTexture(backBuffer_.Get(),float2());
334 //
\90[
\93x
\83X
\83e
\83\93\83V
\83\8b\83X
\83e
\81[
\83g
\82ð
\8dì
\90¬
\82·
\82é
335 //D3D11_DEPTH_STENCIL_DESC ddsDesc;
336 //::ZeroMemory( &ddsDesc, sizeof( ddsDesc ) );
337 //ddsDesc.DepthEnable = TRUE; //
\90[
\93x
\83e
\83X
\83g
\82ð
\8eg
\97p
\82·
\82é
338 //ddsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
339 //ddsDesc.DepthFunc = D3D11_COMPARISON_LESS;
340 //ddsDesc.StencilEnable = FALSE;
341 //DX::ThrowIfFailed(m_d3dDevice->CreateDepthStencilState( &ddsDesc, &backBufferDepthStencilState_ ));
345 void GameMain::Update(float timeTotal, float timeDelta)
347 // Update the performance throttler.
349 auto control = autoThrottle_->Update(timeDelta);
350 state_.ProcessEvent(Event::Update());
351 //if (control == FrameWorkload::Increase)
353 // m_numParticlesToDraw += SampleSettings::Performance::ParticleCountDelta;
355 //if (control == FrameWorkload::Decrease)
357 // m_numParticlesToDraw -= SampleSettings::Performance::ParticleCountDelta;
359 //if (control != FrameWorkload::Maintain)
361 // m_numParticlesToDraw = max(SampleSettings::Performance::ParticleCountMin, min(SampleSettings::Performance::ParticleCountMax, m_numParticlesToDraw));
362 // if (m_featureLevel < D3D_FEATURE_LEVEL_9_3)
364 // m_numParticlesToDraw = min(static_cast<int>(Parameters::MaximumCapacityCompatible - SampleSettings::NumAsteroids - 1), m_numParticlesToDraw);
368 // Update the non-interactive asteroids.
369 // Their behavior is to drift across the window with a fixed translational and rotational
370 // velocity. Upon crossing a boundary outside the window, their position wraps.
372 //for (auto asteroid = m_asteroidData.begin(); asteroid != m_asteroidData.end(); asteroid++)
374 // static const float border = 100.0f;
375 // asteroid->pos = asteroid->pos + asteroid->vel * timeDelta;
376 // if (asteroid->vel.x < 0)
378 // if (asteroid->pos.x < -border)
380 // asteroid->pos.x = m_windowBounds.Width + border;
385 // if (asteroid->pos.x > m_windowBounds.Width + border)
387 // asteroid->pos.x = -border;
390 // if (asteroid->vel.y < 0)
392 // if (asteroid->pos.y < -border)
394 // asteroid->pos.y = m_windowBounds.Height + border;
399 // if (asteroid->pos.y > m_windowBounds.Height + border)
401 // asteroid->pos.y = -border;
405 // asteroid->rot += asteroid->rotVel * timeDelta;
406 // if (asteroid->rot > static_cast<float>(M_PI))
408 // asteroid->rot -= 2.0f * static_cast<float>(M_PI);
410 // if (asteroid->rot < static_cast<float>(-M_PI))
412 // asteroid->rot += 2.0f * static_cast<float>(M_PI);
416 //// Update the interactive particles.
417 //// Their behavior is to be gravitationally attracted to two oscillating gravity
418 //// wells and repelled by any pressed pointer points. Upon reaching the edge of
419 //// the window, the particles bounce.
421 //// Add two gravity wells that move throughout the window.
422 //float2 wellPositions[] =
425 // (1.0f + 0.8f * cosf(timeTotal / (2.0f * static_cast<float>(M_PI)) + 3.0f)) * m_windowBounds.Width / 2.0f,
426 // (1.0f + 0.8f * sinf(timeTotal / 5.0f)) * m_windowBounds.Height / 2.0f
429 // (1.0f + 0.8f * cosf(timeTotal / static_cast<float>(M_PI * M_PI) + 1.0f)) * m_windowBounds.Width / 2.0f,
430 // (1.0f + 0.8f * sinf(timeTotal / static_cast<float>(M_PI))) * m_windowBounds.Height / 2.0f
434 //for (auto particle = m_particleData.begin(); particle != m_particleData.begin() + m_numParticlesToDraw; particle++)
436 // if (particle->pos.x < 0)
438 // particle->vel.x = abs(particle->vel.x);
440 // if (particle->pos.x > m_windowBounds.Width)
442 // particle->vel.x = -abs(particle->vel.x);
444 // if (particle->pos.y < 0)
446 // particle->vel.y = abs(particle->vel.y);
448 // if (particle->pos.y > m_windowBounds.Height)
450 // particle->vel.y = -abs(particle->vel.y);
453 // for (auto repulsor = m_repulsors.begin(); repulsor != m_repulsors.end(); repulsor++)
455 // float2 delta = particle->pos - repulsor->second;
456 // float deltaLength = length(delta) + 24.0f; // Offset length to avoid division by zero.
457 // float deltaLengthCubed = deltaLength * deltaLength * deltaLength;
458 // particle->vel = particle->vel + SampleSettings::Physics::Gravity * timeDelta * delta / deltaLengthCubed;
461 // for (int i = 0; i < ARRAYSIZE(wellPositions); i++)
463 // float gravitySign = 1.0f;
464 // if ((static_cast<int>(timeTotal / 2.0f) + 1) % 10 == 0)
466 // // Every 20 seconds, "explode" the gravity wells for 2 seconds.
467 // gravitySign = -1.0f;
469 // float2 delta = wellPositions[i] - particle->pos;
470 // float deltaLength = length(delta) + 24.0f;
471 // float deltaLengthCubed = deltaLength * deltaLength * deltaLength;
472 // particle->vel = particle->vel + gravitySign * 0.2f * SampleSettings::Physics::Gravity * timeDelta * delta / deltaLengthCubed;
475 // particle->vel = particle->vel * (1.0f - SampleSettings::Physics::Damping);
477 // // Add random noise to the velocity to prevent particles from locking together.
479 // particle->vel.x += RandFloat(-0.5f, 0.5f);
480 // particle->vel.y += RandFloat(-0.5f, 0.5f);
482 // particle->pos = particle->pos + particle->vel * timeDelta;
486 void GameMain::Render()
488 state_.ProcessEvent(Event::Render());
492 //// Draw the non-interactive asteroids.
494 //for (auto asteroid = m_asteroidData.begin(); asteroid != m_asteroidData.end(); asteroid++)
496 // spriteBatch_->Draw(
499 // PositionUnits::DIPs,
500 // float2(1.0f, 1.0f) * asteroid->scale,
501 // SizeUnits::Normalized,
502 // float4(0.8f, 0.8f, 1.0f, 1.0f),
507 //// Draw the interactive particles.
509 //for (auto particle = m_particleData.begin(); particle != m_particleData.begin() + m_numParticlesToDraw; particle++)
511 // float alpha = length(particle->vel) / 200.0f;
512 // spriteBatch_->Draw(
515 // PositionUnits::DIPs,
516 // float2(32.0f, 32.0f),
518 // float4(0.1f, 0.02f, 0.0f, alpha),
520 // BlendMode::Additive
528 float GameMain::RandFloat(float min, float max)
530 return (static_cast<float>(rand() % RAND_MAX) / static_cast<float>(RAND_MAX)) * (max - min) + min;
533 //
\83T
\83E
\83\93\83h
\8dÄ
\90¶
\83X
\83\8c\83b
\83h
534 void GameMain::ExecuteSoundThread()
536 //sf::com_init comInit;
538 soundManager_->Sequencer().Play();
541 soundDriver_->Render();
542 // Concurrency::wait(800);
543 // soundDriver_->Update();
544 // soundDriver_->Render();
546 ::SetEvent(eventHolder_.get());
547 //isDestroy_ = false;
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~
568 WaitForSingleObjectEx(eventHolder_.get(),INFINITE,FALSE);
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());