Sei sulla pagina 1di 47

How to Create Your First

Windows 8 Metro-style Game


Chas. Boyd Principal Program Manager Microsoft Corporation

Three Presentations Today


Step by Step through Game Development 1) How to set up the game 2) How to code it <- You are here 3) How to optimize it

Agenda
Quick summary of the platform Step through the process of development from a programmers perspective: App Initialization Opening a Window Rendering Graphics Loading and Saving Adding Input Controls Adding Sound Effects Adding an Art Pipeline This talks sample code is in C++

Platform Overview

Metro style apps


View

Desktop apps

DX C C++
Communication & Data

XAML C# VB WinRT APIs


Graphics & Media
Application Model

HTML / CSS JavaScript


HTML

Model Controller

JavaScript

C C++

C# VB

System Services

Devices & Printing


Internet
Explorer

Win32

.NET SL

Windows Kernel Services

Kernel

Your Killer Game


Movies & Cut Scenes DirectX Video Media Foundation Connected Services Windows Live Windows Store Xbox LIVE

Graphics

Game Input Pointer Point Sensor API XInput

Audio

Local Services

Tools Visual Studio Asset Viewers Asset Processors

Direct3D

WASAPI XAudio2

PLM
AppData Contracts

Direct2D
HTML

XAML

Windows Runtime
All WinRT APIs are native WinRT APIs feel natural in C++, C#/VB, and JavaScript Reuse of portable C++ code just works WinRT APIs provide rich access to devices, OS, and services HTML5/CSS/JavaScript and XAML are great for Metro style apps Providing a rich set of controls Native DirectX is great for Metro style apps

Updated C++ language support File->New Project templates for native DirectX C++ apps DirectX HLSL shader compilation and syntax highlighting Packaging compiled HLSL shaders into the .appx package Support for other asset types in MSBuild and previewer Visualization, processing and packaging of Textures, meshes, shaders, and audio Debugging DirectX API calls

Win32 CoCreateInstance QueryInterface AddRef / Release N/A

WRL ComPtr<IObject> foo.As(&bar) N/A std::vector

WinRT Foo^ foo = ref new Foo() N/A N/A Platform::Array<>^

Chapter 1/6

App Initialization

ref class MyApp : public IFrameworkView { public: MyApp(); // IFrameworkView Methods virtual void Initialize(CoreApplicationView^ applicationView); virtual void SetWindow(CoreWindow^ window); virtual void Load(String^ entryPoint); virtual void Run(); virtual void Uninitialize();

void MyApp::Run() { auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher;

while (!m_windowClosed) { dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); m_renderer->Update(); m_renderer->Render(); m_renderer->Present(); }


}

Chapter 2/6

Handling Window Events

void MyApp::SetWindow(CoreWindow^ window) { window->SizeChanged += ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>( this, &MyApp::OnWindowSizeChanged); ApplicationView::GetForCurrentView()->ViewStateChanged += ref new TypedEventHandler <ApplicationView^, ApplicationViewStateChangedEventArgs^>( this, &MyApp::OnViewStateChanged); }

Resize Handler
void DirectXApp::OnWindowSizeChanged( _In_ CoreWindow^ sender, _In_ WindowSizeChangedEventArgs^ args ) { if (m_window->Bounds.Width != m_windowBounds.Width || m_window->Bounds.Height != m_windowBounds.Height) { m_d2dContext->SetTarget(nullptr); m_d2dTargetBitmap = nullptr; m_renderTargetView = nullptr; m_depthStencilView = nullptr; CreateWindowSizeDependentResources(); } }

void MyApp::OnWindowActivationChanged( CoreWindow^ sender, WindowActivatedEventArgs^ args) { auto state = args->WindowActivationState;

if(state == CoreWindowActivationState::Deactivated) OutputDebugString("Focus Lost");


if(state == CoreWindowActivationState::CodeActivated || state == CoreWindowActivationState::PointerActivated) OutputDebugString("Focus Regained"); }

{ DisplayOrientations::None; DisplayOrientations::Landscape; DisplayOrientations::LandscapeFlipped; DisplayOrientations::Portrait; DisplayOrientations::PortraitFlipped; } using namespace Windows::Graphics::Display; DisplayProperties::AutoRotationPreferences = DisplayOrientations::Landscape | DisplayOrientations::LandscapeFlipped; // Enable rotation by OS/Accelerometer // Lock rotation by OS/Accelerometer // and enable this orientation

Chapter 3/6

Rendering Graphics

3D Graphics via Direct3D 11


3D Graphics uses the same API as on Desktop/Classic WinRT API set includes only the latest DirectX 11 syntax DirectX 11 API supports multiple hardware generations via FeatureLevels: Feature_Level_9, Feature_Level_10, Feature_Level_11 Direct3D 11 updated for Windows 8

Creating a swap chain


CoreWindow ComPtr ID3D11Device1 ComPtr IDXGISwapChain1 RT // apps core window // renderer // front/back buffers of

// Obtain the final swap chain for this window from the DXGI factory.
// // // // // the Direct3D device that will render to it IUnknown interface on our core window double or triple buffered, stereo, etc. allow on all displays the resulting swap chain object

nullptr

void myApp::Render() { m_d3dContext->OMSetRenderTargets( // rebind every frame! 1, m_renderTargetView.GetAddressOf(), m_depthStencilView.Get() ); if (!m_loadingComplete) return; // only draw the cube once it's loaded // (this is async)

m_d3dContext->IASetVertexBuffers( 0, 1, m_vertexBuffer.GetAddressOf(), &stride, &offset ); m_d3dContext->IASetIndexBuffer( m_indexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0 );

m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

m_d3dContext->IASetInputLayout(m_inputLayout.Get());
m_d3dContext->VSSetConstantBuffers( 0, 1, m_constantBuffer.GetAddressOf() ); m_d3dContext->VSSetShader( m_vertexShader.Get(), nullptr, 0 ); m_d3dContext->PSSetShader( m_pixelShader.Get(), nullptr, 0 ); m_d3dContext->DrawIndexed( m_indexCount, 0, 0 ); }

Chapter 4/7

Loading and Saving

Process Lifetime Management


Suspend/Resume

User Launches App

Running App

suspending resuming

Suspended App

Low Memory

Terminated App

using namespace Concurrency;

float f = 1.0f; // task defined with capturing lambda task<int>([=]() { return foo(f); }).then([](int x) // continuation lambda argument is return value of previous { bar(x); // continuation using existing function baz() }).then(baz);

void MyApp::OnSuspending(Object^ sender, SuspendingEventArgs^ args) { SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); task<void>([=]() { auto localState = ApplicationData::Current->LocalSettings->Values; auto roamingState = ApplicationData::Current->RoamingSettings->Values; localState->Insert( "GameTime", PropertyValue::CreateSingle(m_gameTime)); roamingState->Insert( "MaxLevel", PropertyValue::CreateUInt32(m_maxLevelUnlocked)); }).then([=]() { deferral->Complete(); }); }

void MyApp::Load(String^ entryPoint) { LoadMyGameStateAsync().then([=]() { auto localState = ApplicationData::Current->LocalSettings->Values; auto roamingState = ApplicationData::Current->RoamingSettings->Values; m_gameTime = safe_cast<IPropertyValue^> (localState->Lookup("GameTime"))->GetSingle(); m_maxLevelUnlocked = safe_cast<IPropertyValue^> (roamingState->Lookup("MaxLevel"))->GetUInt32(); }).then([=]() { m_loadingComplete = true; }); }

task<byte*> LoadSkyAsync() { auto folder = Package::Current->InstalledLocation; return task<StorageFile^>( folder->GetFileAsync("sky.dds")).then([](StorageFile^ file){ return FileIO::ReadBufferAsync(file); }).then([](IBuffer^ buffer){ auto fileData = ref new Array<byte>(buffer->Length); DataReader::FromBuffer(buffer)->ReadBytes(fileData); return fileData->Data; }); } ... LoadSkyAsync().then([=](byte* skyTextureData) { CreateTexture(skyTextureData); m_loadingComplete = true; });

Chapter 5/7

Adding Input

Mouse and Touch Input


win->PointerPressed += ref new TypedEventHandler<CoreWindow^,PointerEventArgs^> (this, &LonLatController::OnPointerPressed); void LonLatController::OnPointerPressed( _In_ CoreWindow^ sender, _In_ PointerEventArgs^ args ) { float2 position = float2( args->CurrentPoint->Position.X, args->CurrentPoint->Position.Y );

// position of contact

m_lonLatLastPoint = position; // save for use in controller m_lonLatPointerID = args->CurrentPoint->PointerId; }

// Arrow keys or WASD example auto upKeyState = window->GetKeyAsyncState(VirtualKey::Up); auto wKeyState = window->GetAsyncKeyState(VirtualKey::W);

if (upKeyState & CoreVirtualKeyStates::Down || wKeyState & CoreVirtualKeyStates::Down) { m_playerPosition.y += 1.0f; }

using Windows::Devices::Sensors; // Get current reading from sensor OrientationSensorReading^ orientationReading = m_orientationsensor->GetCurrentReading(); SensorQuaternion^ quat = orientationReading->Quaternion; // Transform quaternion from device orientation space to world space // Orientation space is Z-up, right-handed coordinate system // World space is Y-up, left-handed coordinate system XMVECTOR orientationQuat = XMVectorSet(-quat->X, quat->Z, quat->Y, -quat->W); // Create a rotation matrix from the quaternion // This matrix can be used to rotate an object inside the scene to match // the rotation of the device XMMATRIX rotXMMatrix = XMMatrixRotationQuaternion(orientationQuat);

Windows 8 supports Xbox360 -compatible controllers

Check out new ControllerSketch sample


Demonstrates game controller usage from JavaScript app

if ( m_xinputState.Gamepad.wButtons & XINPUT_GAMEPAD_A ) { m_aButtonWasPressed = true; } else if ( m_aButtonWasPressed ) { m_aButtonWasPressed = false; // Trigger once, only on button release TriggerSoundEffect(); }

if (abs(thumbLeftX) < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) thumbLeftX = 0;


SHORT thumbLeftY = inputState.Gamepad.sThumbLY; if (abs(thumbLeftY) < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) thumbLeftY = 0; combinedTiltX += (float)thumbLeftX / 32768.0f; combinedTiltY += (float)thumbLeftY / 32768.0f;

Chapter 6/7

Adding Sound Effects

// Create the XAudio2 engine and mastering voice on the default audio device

// Load all audio data for the sound effect into a single in-memory buffer new // Create a single source voice for a sound effect

// Trigger sound effect: queue in-memory buffer for playback and start the voice

Chapter 7/7

Creating an Asset Pipeline

Author-time Asset
shader.hlsl

Build Step

Run-time Asset
shader.cso

Packager

Package
texture.bmp texture.dds myApp .appx

mesh.obj

mesh.vbo

music.wav

music.wma

Installer

Run-time Asset
shader.cso

Loader Component

Bindable API object


Shader

Package
texture.dds myApp .appx Texture

mesh.vbo

VertexBuffer

music.wma

Stream

Pro Dev Hints


Find commands in the IDE via the search textport

Set up a multi-monitor dev PC with a touch monitor as the primary To work with the samples, set a breakpoint inside the DX:: macro in DirectSample.h line 18

Time to Act
Biggest opportunity. Ever.
Windows 8 Consumer Preview is now available.

Check out the store.


Go build great games. http://dev.windows.com

Q&A

Potrebbero piacerti anche