Advanced 3D Game Programming with DirectX - phần 3 pot

71 408 0
Advanced 3D Game Programming with DirectX - phần 3 pot

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

143 HRESULT WINAPI DirectSoundCreate8( LPCGUID lpcGuid, LPDIRECTSOUND8 * ppDS, LPUNKNOWN pUnkOuter ); lpcGuid A pointer to a GUID that describes the device you wish to create. While you can enumerate all of the sound devices with DirectSoundEnumerate, generally there is only one sound card on a machine. To get the default device (which is what you want, usually), set this to NULL. ppDS A pointer to an LPDIRECTSOUND8 interface pointer that will be filled with a valid interface pointer if the function succeeds. pUnkOuter Used for COM aggregation; leave this as NULL. Sample code to create the sound interface appears in the following: LPDIRECTSOUND8 m_pDSound = 0; // Create IDirectSound using the primary sound device hr = DirectSoundCreate8( NULL, &m_pDSound, NULL ); if( FAILED( hr ) ) { // Handle critical error } Setting the Cooperative Level After you acquire the interface pointer, the next step is to declare how cooperative you intend on being. Just like DirectInput, this is done using the SetCooperativeLevel command. HRESULT IDirectSound8::SetCooperativeLevel( HWND hwnd, DWORD dwLevel ); 144 hwnd Handle to the window to be associated with the DirectSound object. This should be the primary window. dwLevel One of the following flags, describing the desired cooperative level.  DSSCL_EXCLUSIVE—Grab exclusive control of the sound device. When the application has focus, it is the only audible application.  DSSCL_NORMAL—Smoothest, yet most restrictive cooperative level. The primary format cannot be changed. This is the cooperative level the sound layer uses.  DSSCL_PRIORITY—Like DDSCL_NORMAL except the primary format may be changed.  DSSCL_WRITEPRIMARY—This is the highest possible priority for an application to have. It can't play any secondary buffers, and it has the ability to manually mangle the bits of the primary buffer. Only for the extremely hardcore! This code will be changing the primary format of the sound buffer, so I'll go ahead and set this to DSSCL_PRIORITY. Sample code to do this appears in the following: // pDSound is a valid LPDIRECTSOUND8 object. HRESULT hr = pDSound->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ); if( FAILED( hr ) ) { /* handle error */ } Grabbing the Primary Buffer Since the sound layer sets the cooperative level's priority, it can do some crazy things like change the format of the primary buffer. Generally it's best to set the primary buffer to the same format that all of your secondary buffers will be in; this makes the mixer's job easier, as it doesn't have to resample any sound effects to be able to mix them into the primary buffer. You can imagine what would happen if you tried to play a 22 KHz sound effect in a 44 KHz buffer without resampling: You would run out of samples twice as soon as you would expect, and the sound effect would have sort of a chipmunkish quality to it. To change the format of the primary buffer, you just need to grab it using CreateSoundBuffer, fill out a new format description, and set it using the SetFormat() method on the primary buffer. Listing 4.2 has code that sets the primary format to 22 KHz, 16-bit stereo. Listing 4.2: Sample code to change the format of the primary buffer 145 // pDSound is a valid LPDIRECTSOUND object. LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; sAutoZero<DSBUFFERDESC> dsbd; dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbd.dwBufferBytes = 0; dsbd.lpwfxFormat = NULL; HRESULT hr = pDSound->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ); if( FAILED( hr ) ) { /* handle error */ } // Set primary buffer format to 22 kHz and 16-bit output. WAVEFORMATEX wfx; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 22050; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.wBitsPerSample/8* wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; HRESULT hr = hr = pDSBPrimary->SetFormat(&wfx) if( FAILED( ) ) { throw cGameError( "SetFormat (DS) failed!" ); } 146 SafeRelease( pDSBPrimary ); With all the code in place, you can actually write the sound layer class. The header appears in Listing 4.3, and the source code is in Listing 4.4. Listing 4.3: SoundLayer.h /******************************************************************* * Advanced 3D Game Programming using DirectX 9.0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Desc: Sample application for Direct3D * * copyright (c) 2002 by Peter A Walsh and Adrian Perez * See license.txt for modification and distribution information ******************************************************************/ #ifndef _SOUNDLAYER_H #define _SOUNDLAYER_H #include <dsound.h> #include "GameErrors.h" // Added by ClassView class cSound; class cSoundLayer { LPDIRECTSOUND8 m_pDSound; LPDIRECTSOUNDBUFFER8 m_pPrimary; // primary mixer static cSoundLayer* m_pGlobalSLayer; 147 cSoundLayer( HWND hWnd ); public: virtual ~cSoundLayer(); static cSoundLayer* GetSound() { return m_pGlobalSLayer; } LPDIRECTSOUND8 GetDSound() { return m_pDSound; } static void Create( HWND hWnd ) { new cSoundLayer( hWnd ); } }; inline cSoundLayer* Sound() { return cSoundLayer::GetSound(); } #endif //_SOUNDLAYER_H Listing 4.4: SoundLayer.cpp /******************************************************************* * Advanced 3D Game Programming using DirectX 9.0 148 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Desc: Sample application for Direct3D * * copyright (c) 2002 by Peter A Walsh and Adrian Perez * See license.txt for modification and distribution information ******************************************************************/ #include "stdafx.h" #include "SoundLayer.h" #include "Sound.h" cSoundLayer* cSoundLayer::m_pGlobalSLayer = NULL; cSoundLayer::cSoundLayer( HWND hWnd ) { m_pDSound = NULL; m_pPrimary = NULL; if( m_pGlobalSLayer ) { throw cGameError( "cSoundLayer already initialized!" ); } m_pGlobalSLayer = this; HRESULT hr; LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; // Create IDirectSound using the primary sound device hr = DirectSoundCreate8( NULL, &m_pDSound, NULL ); if( FAILED( hr ) ) { 149 throw cGameError( "DirectSoundCreate failed!" ); } // Set coop level to DSSCL_PRIORITY hr = m_pDSound->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ); if( FAILED( hr ) ) { throw cGameError( "SetCooperativeLevel (DS) failed!" ); } // Get the primary buffer sAutoZero<DSBUFFERDESC> dsbd; dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbd.dwBufferBytes = 0; dsbd.lpwfxFormat = NULL; hr = m_pDSound->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ); if( FAILED( hr ) ) { throw cGameError( "SetFormat (DS) failed!" ); } // Set primary buffer format to 22 kHz and 16-bit output. WAVEFORMATEX wfx; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 22050; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.wBitsPerSample/8* wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; 150 if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) ) { throw cGameError( "CreateSoundBuffer (DS) failed!" ); } SafeRelease( pDSBPrimary ); } cSoundLayer::~cSoundLayer() { SafeRelease( m_pPrimary ); SafeRelease( m_pDSound ); m_pGlobalSLayer = NULL; } The cSound Class To help facilitate the creation and playback of secondary buffers, I constructed an encapsulation class called cSound. A cSound object can be constructed either from a filename or from another cSound object. The copy constructor uses a ref-counting map so that all cSounds based on the same WAV file use the same CWaveSoundRead object. The overhead of the map could have been avoided if the CWaveSoundRead code was changed to accommodate the needed functionality, but I felt it was better to leave the code unchanged from the DirectX SDK. Without any further ado, let's just dive into the code. The details of how this code works isn't terribly interesting but have a look through it anyway to get accustomed to it. Listing 4.5: Sound.h /******************************************************************* * Advanced 3D Game Programming using DirectX 9.0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Desc: Sample application for Direct3D * * copyright (c) 2002 by Peter A Walsh and Adrian Perez * See license.txt for modification and distribution information 151 ******************************************************************/ #ifndef _SOUND_H #define _SOUND_H #include <map> #include "SoundLayer.h" #include "Wavread.h" class cSound { CWaveSoundRead* m_pWaveSoundRead; LPDIRECTSOUNDBUFFER8 m_pBuffer; int m_bufferSize; /** * Multiple sounds that use the same * file shouldn't reread it, they should * share the CWSR object. This map * implements rudimentary reference counting. * I would have just changed CWaveSoundRead, * but I wanted to keep it unchanged from the * samples. */ static std::map< CWaveSoundRead*, int > m_waveMap; void Init(); public: cSound( char* filename ); cSound( cSound& in ); 152 cSound& operator=( const cSound &in ); virtual ~cSound(); void Restore(); void Fill(); void Play( bool bLoop = false ); bool IsPlaying(); }; #endif //_SOUND_H Listing 4.6: Sound.cpp /******************************************************************* * Advanced 3D Game Programming using DirectX 9.0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Desc: Sample application for Direct3D * * copyright (c) 2002 by Peter A Walsh and Adrian Perez * See license.txt for modification and distribution information ******************************************************************/ #include "stdafx.h" #include "WavRead.h" #include "Sound.h" using std::map; [...]... find the += and −= operators Listing 5.7: Addition and subtraction operators for point3 inline point3 operator+(point3 const &a, point3 const &b) { return point3 ( a.x+b.x, a.y+b.y, a.z+b.z ); }; inline point3 operator-(point3 const &a, point3 const &b) { return point3 176 ( a.x-b.x, a.y-b.y, a.z-b.z ); }; Vector-Scalar Multiplication/Division Often, you may want to increase or decrease the length... requirement if you want to be a successful 3D coder Don't worry, though; I'll try to keep this chapter as interesting as possible Points Let's start with the most basic of basic primitives: the 3D point, or vector Points are paramount in 3D graphics The vertices of objects, the objects' locations and directions, and their velocities/forces are all described with 3D points Three-dimensional objects have width,... Listing 5.1: The point3 structure (defined in point3.h) struct point3 { union { struct { float x,y,z; // 3 real components of the vector }; float v [3] ; // Array access useful in for loops }; 171 // Default constructor point3(){} // Construct a point with 3 given inputs point3( float X, float Y, floatZ): x(X), y(Y), z(Z) { } // more will go in here }; This class uses a union in conjunction with a nameless... Hi-Hat\n"; // Tell Direct3D we are about to start rendering Graphics( )-> GetDevice( )-> BeginScene(); // Output the text Graphics( )-> DrawTextString( 1, 1, D3DCOLOR_XRGB( 0, 255, 0), help.c_str() ); // Tell Direct3D we are done rendering Graphics( )-> GetDevice( )-> EndScene(); // Present the back buffer to the primary surface Graphics( )-> Flip(); } void cDSSampleApp::KeyDown( int key ) { switch( key ) { case... multiplication/division operators for point3 inline point3 operator*(point3 const &a, float const &b) { return point3 177 ( a.x*b, a.y*b, a.z*b ); }; inline point3 operator*(float const &a, point3 const &b) { return point3 ( a*b.x, a*b.y, a*b.z ); }; inline point3 operator/(point3 const &a, float const &b) { float inv = 1.f / b; // Cache the division return point3 ( a.x*inv, a.y*inv, a.z*inv ); }; Vector... that connects them (which is the vector b–a) and computes its length The code appears in Listing 5.6 Listing 5.6: point3::Dist inline static float point3::Dist( const point3 &a, const point3 &b ) 174 { point3 distVec( b.x - a.x, b.y - a.y, b.z - a.z ); return distVec.Mag(); } point3 Operators Now that there is a basic primitive I can use, like other primitives (e.g., int or float), I need some way... D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0,0,200), 1.0f, 0 ); // Set up the strings string help; help += "DirectSound Sample application\n"; help += "Vocal Percussion with Adrian Perez\n"; 164 help += " [1]: Keg drum\n"; help += " [2]: Crash 1\n"; help += " [3] : Crash 2\n"; help += " [4]: Bass drum\n"; help += " [5]: Snare drum\n"; help += " [6]: Hi-Hat\n"; // Tell Direct3D we are about to... keystrokes With some practice you can get a pretty swank beat going The code behind the sample appears in Listing 4.7 Listing 4.7: The vocal percussion DirectSound sample app /******************************************************************* * Advanced 3D Game Programming using DirectX 9.0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Desc: Sample application for Direct3D * *... 5.2: point3::Assign // Reassign a point without making a temporary structure inline void point3::Assign( float X, float Y, float Z ) { x=X; y=Y; z=Z; } Mag and MagSquared The function Mag uses the 3D version of the Pythagorean theorem mentioned previously to calculate the length of the point structure (the distance from the point to the origin) The code appears in Listing 5 .3 Listing 5 .3: point3::Mag... !(*iter )-> IsPlaying() ) { (*iter )-> Play(); return; } } /** * A sound wasn't found Create a new one */ DP("spawning a new sound\n"); cSound* pNew = new cSound( *m_sounds[num][0] ); m_sounds[num].push_back( pNew ); m_sounds[num][ m_sounds[num].size() - 1 ]-> Play(); } void cDSSampleApp::DoFrame( float timeDelta ) { // Clear the previous contents of the back buffer Graphics( )-> GetDevice( )-> Clear( 0, 0, D3DCLEAR_TARGET . Listing 4 .3, and the source code is in Listing 4.4. Listing 4 .3: SoundLayer.h /******************************************************************* * Advanced 3D Game Programming using DirectX. /******************************************************************* * Advanced 3D Game Programming using DirectX 9.0 148 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Desc: Sample application for Direct3D * * copyright. /******************************************************************* * Advanced 3D Game Programming using DirectX 9.0 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Desc: Sample application for Direct3D * * copyright

Ngày đăng: 08/08/2014, 23:20

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan