home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // File: GameProc.cpp
- //
- // Desc: Game processing routines
- //
- // Copyright (C) 1995-2001 Microsoft Corporation. All Rights Reserved.
- //-----------------------------------------------------------------------------
- #include <math.h>
- #include "duel.h"
- #include "gameproc.h"
- #include "gfx.h"
- #include "DPUtil.h"
- #include "diutil.h"
- #include "dsutil.h"
- #include "dputil.h"
- #include "lobby.h"
- #include "dsound.h"
- #include "d3dtypes.h"
- #include "stdio.h"
-
-
- //-----------------------------------------------------------------------------
- // Globals
- //-----------------------------------------------------------------------------
- extern DWORD g_dwKeys;
- extern LPDIRECTDRAWSURFACE g_pddsShip[NUM_SHIP_TYPES];
- extern BOOL g_bShowFrameCount;
- extern LPDIRECTDRAWSURFACE g_pddsNumbers;
- extern BOOL g_bHostPlayer;
- extern BOOL g_bIsActive;
- extern DPSESSIONDESC2* g_pdpsd;
- extern HWND g_hwndMain;
- extern HINSTANCE g_hInst;
- extern BOOL g_bReliable;
- extern BOOL g_bAsync;
- extern BOOL g_bUseProtocol;
- extern LPDIRECTPLAYVOICECLIENT g_pVoiceClient;
- extern LPDIRECTSOUND3DLISTENER g_pDSListener;
-
-
- FRAG g_Frags[64]; // ship framents
- BLOCKS g_Blocks; // field layout
- VOID* g_pvReceiveBuffer = NULL; // buffer to store received messages
- DWORD g_dwReceiveBufferSize = 0; // size of buffer
- DPID g_LocalPlayerDPID; // our player id
- BOOL g_bHaveHostInit; // do we need to do host initializaton
- int g_nProgramState; // current state of the game
- DWORD g_dwFrameCount; // used for fps calc
- DWORD g_dwFramesLast; // ..
- DWORD g_dwFrameTime; // ..
- BOOL g_bUpdate; // TRUE if player data needs to be updated
- BOOL g_bSessionLost; // did we get disconnected ?
- HOSTMSG g_HostMsg; // message buffer
- BLOCKHITMSG g_BlockHitMsg; // ..
- SHIPHITMSG g_ShipHitMsg; // ..
- ADDBLOCKMSG g_AddBlockMsg; // ..
- CONTROLMSG g_ControlMsg; // ..
- SYNCMSG g_SyncMsg; // ..
-
- SoundObject* g_pBulletFiringSound = NULL;
- SoundObject* g_pShipExplodeSound = NULL;
- SoundObject* g_pShipEngineSound = NULL;
- SoundObject* g_pShipStartSound = NULL;
- SoundObject* g_pShipStopSound = NULL;
- SoundObject* g_pShipBounceSound = NULL;
- SoundObject* g_pBlockExplodeSound = NULL;
-
-
- // Used to determine new joiner's ship type
- static int g_ShipTypesUsed[NUM_SHIP_TYPES];
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InitMessageBuffers()
- // Desc: Sets up buffes used for sending different types of messages
- //-----------------------------------------------------------------------------
- VOID InitMessageBuffers()
- {
- g_HostMsg.byType = MSG_HOST;
- g_BlockHitMsg.byType = MSG_BLOCKHIT;
- g_ShipHitMsg.byType = MSG_SHIPHIT;
- g_AddBlockMsg.byType = MSG_ADDBLOCK;
- g_ControlMsg.byType = MSG_CONTROL;
- g_SyncMsg.byType = MSG_SYNC;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: LaunchGame()
- // Desc: Sets up the game layout and launches
- //-----------------------------------------------------------------------------
- VOID LaunchGame()
- {
- HRESULT hr;
-
- // initialize message buffers and other module globals
- InitMessageBuffers();
- g_bSessionLost = FALSE;
-
- // get current session description (g_pdpsd is initialized in here)
- hr = DPUtil_GetSessionDesc();
- if (FAILED(hr) || (!g_pdpsd))
- {
- ShowError(IDS_DPLAY_ERROR_GSD);
- ExitGame();
- return;
- }
-
- // Is this session using the DirectPlay Protocol?
- g_bUseProtocol = (g_pdpsd->dwFlags & DPSESSION_DIRECTPLAYPROTOCOL) != 0;
-
- // update window title
- UpdateTitle();
-
- // initialize random number seed
- srand((int)GetTickCount());
-
- // clear front buffer before changing palette
- EraseScreen();
- FlipScreen();
-
- // Begin collecting input
- DIUtil_ReacquireInputDevices();
-
- // init the ship type tracking
- ZeroMemory( g_ShipTypesUsed, sizeof(g_ShipTypesUsed) );
-
- // initialize us
- hr = InitOurShip();
- if( FAILED(hr) )
- {
- ExitGame();
- return;
- }
-
- // get the field layout
- if( g_bHostPlayer )
- {
- // initialize field (done only by host)
- InitField();
-
- // we have host initialization
- g_bHaveHostInit = TRUE;
-
- // start updating screen
- g_bIsActive = TRUE;
- }
- else
- {
- // get it from host, if we are joining
- g_bHaveHostInit = FALSE;
- }
-
- return;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ExitGame()
- // Desc: Game termination code
- //-----------------------------------------------------------------------------
- VOID ExitGame()
- {
- // shut down app
- PostMessage( g_hwndMain, WM_CLOSE, 0, 0 );
- }
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InitOurShip()
- // Desc: Initializes our ship's initial attributes
- //-----------------------------------------------------------------------------
- HRESULT InitPlayerLocalSoundData( SHIP* pShip )
- {
- HRESULT hr;
-
- if( g_pVoiceClient )
- {
- if( FAILED( hr = g_pVoiceClient->Create3DSoundBuffer( pShip->dpidID,
- NULL, 0, 0,
- &pShip->pDSBVoice ) ) )
- return hr;
- }
-
- return S_OK;
- }
-
-
- //-----------------------------------------------------------------------------
- // Name: InitOurShip()
- // Desc: Initializes our ship's initial attributes
- //-----------------------------------------------------------------------------
- HRESULT InitOurShip()
- {
- SHIP ship;
- HRESULT hr;
-
- // Wipe out everything
- ZeroMemory( &ship, sizeof(ship) );
-
- // Calculate ship type based on the number of players in the game
- // we cycle through four ships (Y,R,G,B) for now.
- // This old algorithm's computation will be overridden by HOST_MSG
- ship.byType = (BYTE) ((g_pdpsd->dwCurrentPlayers-1) % NUM_SHIP_TYPES);
- g_ShipTypesUsed[ship.byType] = 1; // our color
-
- ship.dPosX = randInt( 0, MAX_SHIP_X );
- ship.dPosY = randInt( 0, MAX_SHIP_Y );
- ship.cFrame = (char) randInt( 0, MAX_SHIP_FRAME );
- ship.bEnable = TRUE;
- ship.dpidID = g_LocalPlayerDPID;
- ship.pDSBVoice = NULL;
-
- if( FAILED( hr = DPUtil_TestAudioSetup( g_hwndMain ) ) )
- return hr;
-
- if( g_bHostPlayer )
- {
- if( FAILED( hr = DPUtil_VoiceStart() ) )
- return hr;
- }
-
- if( FAILED( hr = DPUtil_VoiceConnect() ) )
- return hr;
-
- // Set our local data
- hr = DPUtil_SetPlayerLocalData( g_LocalPlayerDPID, &ship, sizeof(ship) );
- if( FAILED(hr) )
- {
- ShowError(IDS_DPLAY_ERROR_SPLD);
- return hr;
- }
-
- // No ship fragments
- for( int i=0; i<64; i++ )
- g_Frags[i].valid = FALSE;
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: SetPlayerLocalSoundDataCB()
- // Desc: Initializes and registers a player's local SOUND data ONLY.
- //-----------------------------------------------------------------------------
- BOOL WINAPI SetPlayerLocalSoundDataCB( DPID dpId, DWORD dwPlayerType,
- LPCDPNAME lpName, DWORD dwFlags,
- VOID* lpContext )
- {
- SHIP ship;
- DWORD dwSize = sizeof(ship);
- HRESULT hr;
-
- DPUtil_GetPlayerLocalData(dpId, &ship, &dwSize);
-
- // no player data yet
- if (0 == dwSize)
- return TRUE;
-
- InitPlayerLocalSoundData( &ship );
-
- hr = DPUtil_GetPlayerLocalData( dpId, &ship, &dwSize );
- return (DP_OK == hr);
- };
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InitLocalSoundData()
- // Desc: Initializes and registers all players' sound data ONLY
- //-----------------------------------------------------------------------------
- HRESULT InitLocalSoundData()
- {
- return DPUtil_EnumPlayers(&(g_pdpsd->guidInstance), SetPlayerLocalSoundDataCB, NULL, 0);
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ReleaseLocalSoundData()
- // Desc: Releases a single ship's local sound buffers.
- //-----------------------------------------------------------------------------
- HRESULT ReleasePlayerLocalSoundData( SHIP* pShip )
- {
- HRESULT hr;
-
- if( pShip && g_pVoiceClient && pShip->pDSBVoice )
- {
- if( FAILED( hr = g_pVoiceClient->Delete3DSoundBuffer( pShip->dpidID, &pShip->pDSBVoice ) ) )
- return hr;
- }
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ReleasePlayerLocalData()
- // Desc: Retrieves and releases a player's local data from dplay.
- //-----------------------------------------------------------------------------
- BOOL WINAPI ReleasePlayerLocalDataCB( DPID dpId, DWORD dwPlayerType,
- LPCDPNAME lpName, DWORD dwFlags,
- VOID* lpContext)
- {
- SHIP ship;
- DWORD dwSize = sizeof(SHIP);
- HRESULT hr;
-
- hr = DPUtil_GetPlayerLocalData( dpId, &ship, &dwSize );
- if( FAILED(hr) )
- goto FAIL;
-
- // no player data yet
- if (0 == dwSize)
- return TRUE;
-
- ReleasePlayerLocalSoundData(&ship);
-
- hr = DPUtil_SetPlayerLocalData(dpId, &ship, dwSize );
- if (FAILED(hr))
- goto FAIL;
-
- // success
- return TRUE;
- FAIL:
- // we failed
- return FALSE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ReleaseLocalData()
- // Desc: Releases local data of ALL players.
- //-----------------------------------------------------------------------------
- VOID ReleaseLocalData()
- {
- if( g_nProgramState == PS_ACTIVE )
- {
- if( FAILED( DPUtil_EnumPlayers( &g_pdpsd->guidInstance,
- ReleasePlayerLocalDataCB,
- NULL, 0 ) ) )
- {
- ShowError(IDS_DPLAY_ERROR_EP);
- }
- }
- };
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ProcessUserInput()
- // Desc: Processes any input from the user and updates our ship state
- //-----------------------------------------------------------------------------
- VOID ProcessUserInput( SHIP* pShip )
- {
- static dwOldKeys = 0;
-
- g_bUpdate = FALSE;
-
- // DSOUND: check if the engine was turned off
- if( !(g_dwKeys & (KEY_DOWN | KEY_UP)) &&
- (dwOldKeys & (KEY_DOWN | KEY_UP)) )
- {
- g_dwKeys |= KEY_ENGINEOFF;
-
- g_ControlMsg.byState = (BYTE)g_dwKeys;
- // let everyone know that we just turned our engine off
- SendGameMessage( (GENERICMSG*)&g_ControlMsg, DPID_ALLPLAYERS );
- }
-
- // update our ship state
- UpdateState( pShip, g_dwKeys );
-
- // remember current keys for next frame
- dwOldKeys = g_dwKeys;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: UpdateState()
- // Desc: Updates the current state of our ship, given user input
- //-----------------------------------------------------------------------------
- VOID UpdateState( SHIP* pShip, DWORD dwControls )
- {
- static DWORD dwTimePrevUpdate = 0;
- DWORD dwTimeNow = timeGetTime();
-
- pShip->dwKeys = dwControls;
-
- // Ship orientation
- FLOAT fAngle = (FLOAT)( ( pShip->cFrame / 40.0f ) * 2 * 3.1415926283 );
-
- // Don't accept these keyboard inputs faster than 50
- // times per second (every 20 ms)
- if( dwTimeNow - dwTimePrevUpdate > 20 )
- {
- if( dwControls & KEY_LEFT )
- {
- g_bUpdate = TRUE;
- pShip->cFrame--;
- if( pShip->cFrame < 0 )
- pShip->cFrame += MAX_SHIP_FRAME;
- }
- if( dwControls & KEY_RIGHT )
- {
- g_bUpdate = TRUE;
- pShip->cFrame++;
- if( pShip->cFrame >= MAX_SHIP_FRAME )
- pShip->cFrame -= MAX_SHIP_FRAME;
- }
-
- if( dwControls & KEY_UP )
- {
- g_bUpdate = TRUE;
- pShip->dVelX += sin(fAngle) * 10.0 / 1000.0;
- pShip->dVelY += -cos(fAngle) * 10.0 / 1000.0;
- }
- if( dwControls & KEY_DOWN )
- {
- g_bUpdate = TRUE;
- pShip->dVelX -= sin(fAngle) * 10.0 / 1000.0;
- pShip->dVelY -= -cos(fAngle) * 10.0 / 1000.0;
- }
- dwTimePrevUpdate = dwTimeNow;
- }
-
- if( dwControls & KEY_STOP )
- {
- g_bUpdate = TRUE;
- pShip->dVelX = 0.0;
- pShip->dVelY = 0.0;
- }
- if( !pShip->bBulletEnable && pShip->bEnable )
- {
- if( dwControls & KEY_FIRE )
- {
- g_bUpdate = TRUE;
- // launch a new bullet
- pShip->dBulletPosX = (WORD)( sin(fAngle)*6.0 + 16.0 + pShip->dPosX );
- pShip->dBulletPosY = (WORD)(-cos(fAngle)*6.0 + 16.0 + pShip->dPosY );
- pShip->dBulletVelX = sin(fAngle)*500.0/1000.0;
- pShip->dBulletVelY = -cos(fAngle)*500.0/1000.0;
- pShip->bBulletEnable = TRUE;
- pShip->dwBulletFrame = 0;
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: SendSync()
- // Desc: Sends a sync message with the rendevous position. We are using a
- // synchronization technique in which every player informs everyone else
- // where the player is going to be at the end of the next sync interval.
- // Based on this rendezvous position, everyone tries to move their
- // corresponding ghosts to the rendezvous position by the end of the
- // interval.
- //-----------------------------------------------------------------------------
- VOID SendSync( SHIP* pShip )
- {
- g_SyncMsg.byShipType = pShip->byType;
- g_SyncMsg.cFrame = pShip->cFrame;
- g_SyncMsg.dPosX = pShip->dPosX + pShip->dVelX*1000;
- g_SyncMsg.dPosY = pShip->dPosY + pShip->dVelY*1000;
-
- SendGameMessage( (GENERICMSG*)&g_SyncMsg, DPID_ALLPLAYERS );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: UpdateDisplayStatus()
- // Desc: Updates the disable timeout. Enables the ship if disable timeout has
- // elapsed.
- //-----------------------------------------------------------------------------
- VOID UpdateDisplayStatus( SHIP* pShip )
- {
- DWORD dwTickDiff;
- DWORD dwTickCount;
-
- // current time
- dwTickCount = timeGetTime();
-
- // time elapsed since last update
- dwTickDiff = dwTickCount - pShip->dwLastTick;
-
- // timestamp
- pShip->dwLastTick = dwTickCount;
-
- // update time-out
- pShip->iCountDown -= dwTickDiff;
-
- // time-out ?
- if( pShip->iCountDown < 0 )
- {
- // get new position and enable our lpShip
- pShip->dPosX = randInt( 0, MAX_SHIP_X );
- pShip->dPosY = randInt( 0, MAX_SHIP_Y );
- pShip->cFrame = (char) randInt( 0, MAX_SHIP_FRAME );
- pShip->bEnable = TRUE;
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: UpdatePosition()
- // Desc: Updates our ship's position
- //-----------------------------------------------------------------------------
- VOID UpdatePosition( DPID dpId, SHIP* lpShip )
- {
- int x,y;
- BYTE oldxCell, oldyCell, newxCell, newyCell, mask, col, row;
- double thisTick, totalTick, xtick, ytick;
- DWORD dwTickCount;
- DWORD dwTickDiff;
-
- if( !lpShip->bEnable )
- return;
-
- // how long has it been since we last updated
- dwTickCount = timeGetTime();
- dwTickDiff = dwTickCount - lpShip->dwLastTick;
-
- // current timestamp
- lpShip->dwLastTick = dwTickCount;
-
- oldxCell = (int)(lpShip->dPosX+16.0) >> 4;
- oldyCell = (int)(lpShip->dPosY+16.0) >> 4;
-
- // compute new position
- lpShip->dPosX += lpShip->dVelX * dwTickDiff;
- lpShip->dPosY += lpShip->dVelY * dwTickDiff;
-
- newxCell = (int)(lpShip->dPosX+16.0) >> 4;
- newyCell = (int)(lpShip->dPosY+16.0) >> 4;
- if(oldxCell != newxCell)
- {
- // we allow ghosts to pass through the blocks
- if( (dpId == g_LocalPlayerDPID) && IsHit( newxCell, newyCell ) )
- {
- if( lpShip->dVelX > 0.0 )
- lpShip->dPosX = (oldxCell << 4) + 15 - 16;
- else
- lpShip->dPosX = (oldxCell << 4) - 16;
- lpShip->dVelX = -lpShip->dVelX*0.9;
- newxCell = oldxCell;
- lpShip->bBounced = TRUE;
- }
- }
- if(oldyCell != newyCell)
- {
- // we allow ghosts to pass through the blocks
- if( (dpId == g_LocalPlayerDPID) && IsHit( newxCell, newyCell ) )
- {
- if( lpShip->dVelY > 0.0 )
- lpShip->dPosY = (oldyCell << 4) + 15 - 16;
- else
- lpShip->dPosY = (oldyCell << 4) - 16;
-
- lpShip->dVelY = -lpShip->dVelY*0.9;
- lpShip->bBounced = TRUE;
- }
- }
-
- if( lpShip->dPosX > MAX_SHIP_X )
- {
- lpShip->dPosX = MAX_SHIP_X;
- lpShip->dVelX = -lpShip->dVelX*0.9;
- lpShip->bBounced = TRUE;
- }
- else if ( lpShip->dPosX < 0 )
- {
- lpShip->dPosX =0;
- lpShip->dVelX = -lpShip->dVelX*0.9;
- lpShip->bBounced = TRUE;
- }
- if( lpShip->dPosY > MAX_SHIP_Y )
- {
- lpShip->dPosY = MAX_SHIP_Y;
- lpShip->dVelY = -lpShip->dVelY*0.9;
- lpShip->bBounced = TRUE;
- }
- else if ( lpShip->dPosY < 0 )
- {
- lpShip->dPosY =0;
- lpShip->dVelY = -lpShip->dVelY*0.9;
- lpShip->bBounced = TRUE;
- }
-
- if ((dpId == g_LocalPlayerDPID) && lpShip->bBounced)
- {
- SendSync(lpShip);
- }
-
- if( !lpShip->bBulletEnable )
- return;
-
- // update the active bullet
- lpShip->dwBulletFrame += dwTickDiff;
- if( lpShip->dwBulletFrame >= MAX_BULLET_FRAME )
- {
- lpShip->bFiring = FALSE;
- lpShip->bBulletEnable = FALSE;
- return;
- }
-
-
- if( lpShip->dBulletVelX != 0.0 )
- xtick = 8.0/lpShip->dBulletVelX;
- else
- xtick = 999999.0;
-
- if( lpShip->dBulletVelY != 0.0 )
- ytick = 8.0/lpShip->dBulletVelY;
- else
- ytick = 999999.0;
-
- if( xtick < 0.0 )
- xtick = -xtick;
- if( ytick < 0.0 )
- ytick = -ytick;
-
- if( xtick < ytick )
- thisTick = xtick;
- else
- thisTick = ytick;
-
- if( thisTick > dwTickDiff )
- thisTick = dwTickDiff;
-
- for( totalTick = 0.0; totalTick < dwTickDiff; )
- {
- totalTick += thisTick;
-
- lpShip->dBulletPosX += lpShip->dBulletVelX * thisTick;
- lpShip->dBulletPosY += lpShip->dBulletVelY * thisTick;
-
- if( lpShip->dBulletPosX > MAX_BULLET_X )
- {
- lpShip->dBulletPosX = MAX_BULLET_X;
- lpShip->dBulletVelX = -lpShip->dBulletVelX*0.9;
- }
- else if ( lpShip->dBulletPosX < 0 )
- {
- lpShip->dBulletPosX =0;
- lpShip->dBulletVelX = -lpShip->dBulletVelX*0.9;
- }
- if( lpShip->dBulletPosY > MAX_BULLET_Y )
- {
- lpShip->dBulletPosY = MAX_BULLET_Y;
- lpShip->dBulletVelY = -lpShip->dBulletVelY*0.9;
- }
- else if ( lpShip->dBulletPosY < 0 )
- {
- lpShip->dBulletPosY =0;
- lpShip->dBulletVelY = -lpShip->dBulletVelY*0.9;
- }
-
- // check to see if it hit anything
- x = (int)(lpShip->dBulletPosX + 0.5) + 1;
- y = (int)(lpShip->dBulletPosY + 0.5) + 1;
-
- row = y >> 4;
- col = x >> 4;
- mask = 1 << (col & 0x7);
- col = col >> 3;
- if( g_Blocks.bits[row][col] & mask )
- {
- // dwScored a block hit
- g_BlockHitMsg.byRow = row;
- g_BlockHitMsg.byCol = col;
- g_BlockHitMsg.byMask = mask;
- SendGameMessage( (GENERICMSG*)&g_BlockHitMsg, DPID_ALLPLAYERS);
-
- g_Blocks.bits[row][col] &= ~mask;
- lpShip->dwScore += 10;
- lpShip->bBulletEnable = FALSE;
- lpShip->bBlockHit = TRUE;
- lpShip->bFiring = FALSE;
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: IsHit()
- // Desc: Tells if there is a block at (x,y) location
- //-----------------------------------------------------------------------------
- BOOL IsHit( int x, int y )
- {
- int col, mask;
-
- // outside screen boundaries?
- if( (x < 0) || (y < 0) || (x >= 40) || (y >= 30) )
- return TRUE;
-
- // look at the block bits
- mask = 1 << (x & 0x7);
- col = x >> 3;
- if( g_Blocks.bits[y][col] & mask )
- return TRUE;
- else
- return FALSE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InitField
- // Desc: Initializes block positions on the field
- //-----------------------------------------------------------------------------
- VOID InitField()
- {
- int i, x, y;
-
- // clear all g_Blocks
- for(x=0; x<5; x++)
- for(y=0; y<30; y++)
- g_Blocks.bits[y][x] = 0;
-
- // set random gBlocks
- for(i=0; i<400; i++)
- {
- x = randInt(0, 40);
- y = randInt(0, 30);
- if( !setBlock(x, y) ) i--;
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: AddBlock()
- // Desc: Adds a block to the field
- //-----------------------------------------------------------------------------
- VOID AddBlock()
- {
- // Maybe add a block?
- if( g_bHostPlayer && g_bIsActive && ( randInt( 0, 100 ) > 98 ) )
- {
- int x = randInt( 0, 40);
- int y = randInt( 0, 30);
- if( setBlock( x, y) )
- {
- g_AddBlockMsg.byX = (BYTE)x;
- g_AddBlockMsg.byY = (BYTE)y;
- SendGameMessage( (GENERICMSG*)&g_AddBlockMsg, DPID_ALLPLAYERS );
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: setBlock()
- // Desc: Turns on a block
- //-----------------------------------------------------------------------------
- BOOL setBlock( int x, int y )
- {
- BYTE mask, col;
-
- mask = 1 << (x & 0x7);
- col = x >> 3;
-
- // is Block already set?
- if( g_Blocks.bits[y][col] & mask )
- return FALSE;
-
- // set the block and return success
- g_Blocks.bits[y][col] |= mask;
- return TRUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: AddFrag()
- // Desc: Turns on a fragment
- //-----------------------------------------------------------------------------
- VOID AddFrag( SHIP* pShip, int offX, int offY )
- {
- for( int i=0; i<64; i++ ) // Find available fragment
- {
- if( !g_Frags[i].valid )
- break;
- }
- if( i == 64 )
- return;
-
- g_Frags[i].dPosX = offX + pShip->dPosX;
- g_Frags[i].dPosY = offY + pShip->dPosY;
- g_Frags[i].pdds = g_pddsShip[pShip->byType];
- g_Frags[i].src.top = 32 * ( (int)pShip->cFrame / 10 ) + offX;
- g_Frags[i].src.left = 32 * ( (int)pShip->cFrame % 10 ) + offY;
- g_Frags[i].src.right = g_Frags[i].src.left + 8;
- g_Frags[i].src.bottom = g_Frags[i].src.top + 8;
- g_Frags[i].dVelX = ((double)offX - 12.0)/24.0;
- g_Frags[i].dVelY = ((double)offY - 12.0)/24.0;
- g_Frags[i].valid = TRUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: UpdateFragment()
- // Desc: Updates the position of a fragment
- //-----------------------------------------------------------------------------
- VOID UpdateFragment( int i )
- {
- DWORD dwTickCount;
- static DWORD dwTickDiff;
- static DWORD dwLastTick;
-
- if( i == 0 )
- {
- dwTickCount = timeGetTime();
- dwTickDiff = dwTickCount - dwLastTick;
- dwLastTick = dwTickCount;
-
- // If the FPS is high, keep the fragments moving
- if( dwTickDiff < 10 )
- dwTickDiff = 10;
- }
-
- if( !g_Frags[i].valid )
- return;
-
- g_Frags[i].dPosX += (int) (g_Frags[i].dVelX * dwTickDiff);
- g_Frags[i].dPosY += (int) (g_Frags[i].dVelY * dwTickDiff);
- if( (g_Frags[i].dPosX < 0.0) || (g_Frags[i].dPosX >= 632.0) ||
- (g_Frags[i].dPosY < 0.0) || (g_Frags[i].dPosY >= 472.0) )
- {
- g_Frags[i].valid = FALSE;
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DestroyShip()
- // Desc: Adds a bunch of fragments to show that the ship is destroyed
- //-----------------------------------------------------------------------------
- VOID DestroyShip( SHIP* pShip )
- {
- // Set flag for explosion sound
- pShip->bDeath = TRUE;
-
- // Add ship fragments
- AddFrag( pShip, 0, 0 );
- AddFrag( pShip, 8, 0 );
- AddFrag( pShip, 16, 0 );
- AddFrag( pShip, 24, 0 );
- AddFrag( pShip, 0, 8 );
- AddFrag( pShip, 8, 8 );
- AddFrag( pShip, 16, 8 );
- AddFrag( pShip, 24, 8 );
- AddFrag( pShip, 0, 16 );
- AddFrag( pShip, 8, 16 );
- AddFrag( pShip, 16, 16 );
- AddFrag( pShip, 24, 16 );
- AddFrag( pShip, 0, 24 );
- AddFrag( pShip, 8, 24 );
- AddFrag( pShip, 16, 24 );
- AddFrag( pShip, 24, 24 );
-
- // Play explosion sound
- ProcessSoundFlags( pShip );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: UpdateFrame()
- // Desc: Refreshes the screen
- //-----------------------------------------------------------------------------
- BOOL UpdateFrame()
- {
- static DWORD dwSyncLastTick = 0L;
- static DWORD dwUpdateLastTick = 0L;
- static DWORD dwLobbyMsgLastTick = 0L;
- DWORD dwTickCount;
- SHIP ship;
- DWORD dwSize;
- HRESULT hr;
- int i;
-
- switch( g_nProgramState )
- {
- case PS_ACTIVE:
- // Use DirectInput to read game-play keys
- DIUtil_ReadKeys( &g_dwKeys );
-
- // get our local data
- dwSize = sizeof(ship);
- hr = DPUtil_GetPlayerLocalData( g_LocalPlayerDPID, &ship, &dwSize );
- if( FAILED(hr) )
- return FALSE;
-
- if( !ship.bEnable )
- {
- // Ppdate disable timeout and display status
- UpdateDisplayStatus( &ship );
- }
- else
- {
- // Process any change in game controls
- ProcessUserInput( &ship );
-
- dwTickCount = timeGetTime();
-
- // Synchronize if it's time
- if( g_bIsActive && ((dwTickCount - dwSyncLastTick) > SYNC_INTERVAL) )
- {
- SendSync( &ship );
- dwSyncLastTick = dwTickCount;
- }
-
- // If our player changed any keys, let everyone know
- if( g_bUpdate )
- {
- // Control the number of packets we send
- if( (dwTickCount - dwUpdateLastTick) > UPDATE_INTERVAL )
- {
- // Let others know
- g_ControlMsg.byState = (BYTE)g_dwKeys;
- SendGameMessage( (GENERICMSG*)&g_ControlMsg, DPID_ALLPLAYERS );
- dwUpdateLastTick = dwTickCount;
- }
- }
-
- // If connected to a lobby, occasionally report score as a property
- if( DoingLobbyMessages() &&
- (dwTickCount - dwLobbyMsgLastTick) > 10000 ) // every 10 sec
- {
- DPLDATA_PLAYERSCORE playerScore;
- ZeroMemory(&playerScore, sizeof(DPLDATA_PLAYERSCORE));
- playerScore.dwScoreCount = 1;
- playerScore.Score[0] = (LONG)ship.dwScore;
- LobbyMessageSetProperty( &DPLPROPERTY_PlayerScore, &playerScore,
- sizeof(DPLDATA_PLAYERSCORE));
- dwLobbyMsgLastTick = dwTickCount;
- }
- }
-
- // Save ship data as RenderPlayerCB reads stored data
- hr = DPUtil_SetPlayerLocalData( g_LocalPlayerDPID, &ship, sizeof(ship) );
- if( FAILED(hr) )
- {
- ShowError(IDS_DPLAY_ERROR_SPLD);
- return FALSE;
- }
-
- // Update fragments
- for( i=0; i<64; i++ )
- UpdateFragment(i);
-
- // Add a block
- AddBlock();
-
- // Render everything
- if( !DrawScreen() )
- {
- return FALSE;
- }
- break;
-
- case PS_REST:
- if( g_bHaveHostInit )
- {
- SetGamePalette();
- g_nProgramState = PS_ACTIVE;
- }
- break;
- }
-
- return TRUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ProcessSoundFlags()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID ProcessSoundFlags( SHIP* pShip )
- {
- // Get object positions for panning sounds
- RECT rc;
- GetClientRect( g_hwndMain, &rc );
- FLOAT fShipXPos = (FLOAT)( ( 2 * pShip->dPosX ) / rc.right ) - 1;
- FLOAT fShipYpos = (FLOAT)( (-2 * pShip->dPosY ) / rc.bottom ) - 1;
- FLOAT fBulletXPos = (FLOAT)( ( 2 * pShip->dPosX ) / rc.right ) - 1;
- FLOAT fBulletYpos = (FLOAT)( (-2 * pShip->dPosY ) / rc.bottom ) - 1;
-
- // Set sound state based on user input and ship state
- if( pShip->bDeath ) // nothing but the boom
- {
- DSUtil_StopSound( g_pBulletFiringSound );
- DSUtil_StopSound( g_pShipBounceSound );
- DSUtil_StopSound( g_pShipStopSound );
- DSUtil_StopSound( g_pShipStartSound );
- DSUtil_StopSound( g_pShipEngineSound );
- DSUtil_PlaySound( g_pShipExplodeSound, 0 );
-
- pShip->bEngineRunning = FALSE;
- pShip->bMoving = FALSE;
- pShip->dwKeys = 0; // No input for a dead ship
- pShip->bDeath = FALSE; // Turn off sound flag.
- }
-
- if( pShip->dwKeys & KEY_STOP )
- {
- if( pShip->bMoving )
- {
- DSUtil_StopSound( g_pShipEngineSound );
- DSUtil_PlaySound( g_pShipStopSound, 0 );
- pShip->bEngineRunning = FALSE;
- pShip->bMoving = FALSE;
- }
- }
-
- if( pShip->dwKeys & KEY_ENGINEOFF )
- {
- DSUtil_StopSound( g_pShipEngineSound );
- pShip->bEngineRunning = FALSE;
- }
-
- if( pShip->dwKeys & (KEY_UP | KEY_DOWN) )
- {
- if( !pShip->bEngineRunning ) // Turn on engine
- {
- DSUtil_PlaySound( g_pShipEngineSound, DSBPLAY_LOOPING );
- if( !pShip->bMoving ) //"fire-up-engine" sound
- {
- DSUtil_PlayPannedSound( g_pShipStartSound, fShipXPos );
- pShip->bMoving = TRUE;
- }
- pShip->bEngineRunning = TRUE;
- }
- }
-
- if( pShip->pDSBVoice )
- {
- pShip->pDSBVoice->SetPosition( D3DVAL( pShip->dPosX - 320 ) * D3DVAL(6.0f/640.f),
- -D3DVAL( pShip->dPosY - 240 ) * D3DVAL(6.0f/640.f),
- D3DVAL(0),
- DS3D_DEFERRED );
-
- pShip->pDSBVoice->SetVelocity( D3DVAL( pShip->dVelX * 10 ), //exagerater vel
- -D3DVAL( pShip->dVelY * 10 ),
- D3DVAL(0),
- DS3D_DEFERRED );
- }
-
- if( pShip->dwKeys & KEY_FIRE )
- {
- if( !pShip->bFiring )
- {
- DSUtil_PlayPannedSound( g_pBulletFiringSound, fShipXPos );
-
- pShip->bFiring = TRUE;
- }
- }
-
- if( pShip->bBlockHit )
- {
- DSUtil_PlayPannedSound( g_pBlockExplodeSound, fBulletXPos );
- pShip->bBlockHit = FALSE;
- }
-
- if( pShip->bBounced )
- {
- DSUtil_PlayPannedSound( g_pShipBounceSound, fShipXPos );
- pShip->bBounced = FALSE;
- }
-
- g_pDSListener->CommitDeferredSettings();
-
- pShip->dwKeys = 0;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: RenderPlayerCB()
- // Desc: Renders a ship in its current state. Also checks if we hit the ship
- // and informs the ship that it has been destroyed.
- //-----------------------------------------------------------------------------
- BOOL WINAPI RenderPlayerCB( DPID dpId, DWORD dwPlayerType, LPCDPNAME lpName,
- DWORD dwFlags, VOID* lpContext )
- {
- SHIP ship;
- SHIP ourShip;
- DWORD dwSize = sizeof(ship);
- BOOL bHit = FALSE;
- HRESULT hr;
- DWORD dwTickCount;
-
- // Get ship data
- hr = DPUtil_GetPlayerLocalData( dpId, &ship, &dwSize );
- if( FAILED(hr) )
- return FALSE;
-
- // No player data yet
- if( 0 == dwSize )
- return TRUE;
-
- // Ignore current ship ?
- if( ship.bIgnore )
- {
- // If this ship was being ignored, update ignore time-out
- // A time-out is used here to ensure that this ship doesn't get ignored
- // forever on our screen in case the destroy message was dropped.
- dwTickCount = timeGetTime();
- ship.iCountDown -= dwTickCount - ship.dwLastTick;
- ship.dwLastTick = dwTickCount;
- if( ship.iCountDown < 0 )
- {
- ship.bIgnore = FALSE;
- }
-
- // Save ship data
- hr = DPUtil_SetPlayerLocalData( dpId, &ship, sizeof(ship) );
- if( FAILED(hr) )
- return FALSE;
-
- // We are ignoring this ship, so just bail
- return TRUE;
- }
-
- // Bail if ship is disabled
- if( !ship.bEnable)
- return TRUE;
-
- // Update ship's position
- UpdatePosition( dpId, &ship );
-
- // Get our player data to compare with others
- dwSize = sizeof(ship);
- hr = DPUtil_GetPlayerLocalData( g_LocalPlayerDPID, &ourShip, &dwSize );
- if( FAILED(hr) )
- return FALSE;
-
- // Check if our bullet hit the current ship
- if( (dpId != g_LocalPlayerDPID) && ourShip.bBulletEnable && ship.bEnable )
- {
- if( (ourShip.dBulletPosX > ship.dPosX) &&
- (ourShip.dBulletPosX < (ship.dPosX + 32.0) ) &&
- (ourShip.dBulletPosY > ship.dPosY) &&
- (ourShip.dBulletPosY < (ship.dPosY + 32.0) ) )
- {
- // Hasta-la-vista baby
- DestroyShip( &ship );
- // We nailed it
- bHit = TRUE;
- // Turn off ship locally
- ship.bEnable = FALSE;
- // Temporarily ignore ship until we get a response
- ship.bIgnore = TRUE;
- // Set its ignore time-out
- ship.iCountDown = HIDE_TIMEOUT;
- // Time-stamp
- ship.dwLastTick = timeGetTime();
- // Turn our bullet off
- ship.bBulletEnable = FALSE;
- // Update our score
- ourShip.dwScore += 1000;
- // Save our score
- hr = DPUtil_SetPlayerLocalData( g_LocalPlayerDPID, &ourShip, sizeof(ourShip) );
- if( FAILED(hr) )
- {
- ShowError(IDS_DPLAY_ERROR_SPLD);
- return FALSE;
- }
- }
- }
-
- // Render the ship
- if( ship.bBulletEnable ) DrawBullet(&ship);
- if( ship.bEnable ) DrawShip(&ship);
-
- ProcessSoundFlags( &ship );
-
- // Save ship data
- hr = DPUtil_SetPlayerLocalData( dpId, &ship, sizeof(ship) );
- if( FAILED(hr) )
- return FALSE;
-
- // Inform the player
- if( bHit )
- {
- g_ShipHitMsg.Id = dpId;
- SendGameMessage( (GENERICMSG*)&g_ShipHitMsg, dpId );
- }
-
- return TRUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DrawScreen()
- // Desc: Renders the current frame
- //-----------------------------------------------------------------------------
- BOOL DrawScreen()
- {
- HRESULT hr;
-
- // Clear screen
- EraseScreen();
-
- // Render players
- hr = DPUtil_EnumPlayers( NULL, RenderPlayerCB, NULL, 0 );
- if( FAILED(hr) )
- {
- ShowError(IDS_DPLAY_ERROR_EP);
- return FALSE;
- }
-
- // Render field
- for( int y=0; y<30; y++ )
- {
- for( int x=0; x<40; x++ )
- {
- BYTE mask = 1 << (x & 0x7);
- BYTE col = x >> 3;
- if( g_Blocks.bits[y][col] & mask )
- DrawBlock( x, y );
- }
- }
-
- // Render score
- if (!DrawScore())
- return FALSE;
-
- // Render fragments
- DrawFragments();
-
- // Render frame rate
- if( g_bShowFrameCount )
- DisplayFrameRate();
-
- // Show
- FlipScreen();
-
- return TRUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DisplayFrameRate()
- // Desc: Renders current frame rate
- //-----------------------------------------------------------------------------
- VOID DisplayFrameRate()
- {
- static DWORD dwFrames = 0;
-
- g_dwFrameCount++;
-
- DWORD dwTime = timeGetTime() - g_dwFrameTime;
- if( dwTime > 1000 )
- {
- dwFrames = (g_dwFrameCount*1000)/dwTime;
- g_dwFrameTime = timeGetTime();
- g_dwFrameCount = 0;
- }
-
- if( dwFrames == 0 )
- return;
-
- if (dwFrames != g_dwFramesLast)
- g_dwFramesLast = dwFrames;
-
- char strFPS[256];
- sprintf( strFPS, "%d", dwFrames );
- BltNumber( strFPS, 295, 10);
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DrawScore()
- // Desc: Renders our current score
- //-----------------------------------------------------------------------------
- BOOL DrawScore()
- {
- SHIP ship;
- DWORD dwSize;
- CHAR strScore[11];
- int rem;
- HRESULT hr;
-
- dwSize = sizeof(ship);
- hr = DPUtil_GetPlayerLocalData( g_LocalPlayerDPID, &ship, &dwSize );
- if( FAILED(hr) )
- return FALSE;
-
- // Calculate dwScore string
- strScore[0] = (BYTE)ship.dwScore/100000 + '0';
- rem = ship.dwScore % 100000;
- strScore[1] = rem/10000 + '0';
- rem = ship.dwScore % 10000;
- strScore[2] = rem/1000 + '0';
- rem = ship.dwScore % 1000;
- strScore[3] = rem/100 + '0';
- rem = ship.dwScore % 100;
- strScore[4] = rem/10 + '0';
- rem = ship.dwScore % 10;
- strScore[5] = rem + '0';
- strScore[6] = '\0';
-
- // Blt score
- BltNumber( strScore, 8, 8 );
-
- // Save ship data
- hr = DPUtil_SetPlayerLocalData( g_LocalPlayerDPID, &ship, sizeof(ship) );
- if( FAILED(hr) )
- {
- ShowError(IDS_DPLAY_ERROR_SPLD);
- return FALSE;
- }
-
- return TRUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DrawBlock()
- // Desc: Renders a block
- //-----------------------------------------------------------------------------
- VOID DrawBlock( int x, int y )
- {
- RECT src;
- src.top = 0;
- src.left = 224;
- src.right = src.left + 16;
- src.bottom = src.top + 16;
- BltObject( x << 4, y << 4, g_pddsNumbers, &src, DDBLTFAST_SRCCOLORKEY );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DrawShip()
- // Desc: Renders a ship
- //-----------------------------------------------------------------------------
- VOID DrawShip( SHIP* pShip )
- {
- RECT src;
- src.top = 32 * (pShip->cFrame / 10 );
- src.left = 32 * (pShip->cFrame % 10 );
- src.right = src.left + 32;
- src.bottom = src.top + 32;
- BltObject( (int)pShip->dPosX, (int)pShip->dPosY, g_pddsShip[pShip->byType],
- &src, DDBLTFAST_SRCCOLORKEY );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DrawBullet()
- // Desc: Renders a bullet
- //-----------------------------------------------------------------------------
- VOID DrawBullet( SHIP* pShip )
- {
- RECT src;
- src.top = BULLET_Y;
- src.left = BULLET_X + (pShip->byType)*4;
- src.right = src.left + 3;
- src.bottom = src.top + 3;
- BltObject( (int)pShip->dBulletPosX, (int)pShip->dBulletPosY, g_pddsNumbers,
- &src, DDBLTFAST_SRCCOLORKEY );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DrawFragments()
- // Desc: Renders the fragments
- //-----------------------------------------------------------------------------
- VOID DrawFragments()
- {
- for( int i=0; i<64; i++)
- {
- if( g_Frags[i].valid )
- {
- BltObject( (int)g_Frags[i].dPosX, (int)g_Frags[i].dPosY,
- g_Frags[i].pdds, &g_Frags[i].src,
- DDBLTFAST_SRCCOLORKEY );
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ReceiveGameMessages()
- // Desc: Checks if there are any messages for us and receives them
- //-----------------------------------------------------------------------------
- HRESULT ReceiveMessages()
- {
- DPID idFrom, idTo;
- LPVOID pvMsgBuffer;
- DWORD dwMsgBufferSize;
- HRESULT hr;
-
- // read all messages in queue
- dwMsgBufferSize = g_dwReceiveBufferSize;
- pvMsgBuffer = g_pvReceiveBuffer;
-
- while( TRUE )
- {
- // See what's out there
- idFrom = 0;
- idTo = 0;
-
- hr = DPUtil_Receive( &idFrom, &idTo, DPRECEIVE_ALL, pvMsgBuffer,
- &dwMsgBufferSize );
- if( hr == DPERR_BUFFERTOOSMALL )
- {
- if( pvMsgBuffer == NULL )
- {
- pvMsgBuffer = GlobalAllocPtr( GHND, dwMsgBufferSize );
- if( pvMsgBuffer == NULL )
- return DPERR_NOMEMORY;
- g_pvReceiveBuffer = pvMsgBuffer;
- g_dwReceiveBufferSize = dwMsgBufferSize;
- }
- else if( dwMsgBufferSize > g_dwReceiveBufferSize )
- {
- pvMsgBuffer = GlobalReAllocPtr( pvMsgBuffer, dwMsgBufferSize, 0 );
- if( pvMsgBuffer == NULL )
- return DPERR_NOMEMORY;
- g_pvReceiveBuffer = pvMsgBuffer;
- g_dwReceiveBufferSize = dwMsgBufferSize;
- }
- }
- else if( SUCCEEDED(hr) &&
- ( (dwMsgBufferSize >= sizeof(GENERICMSG)) ||
- (dwMsgBufferSize >= sizeof(DPMSG_GENERIC) ) ) )
- {
- if( idFrom == DPID_SYSMSG )
- {
- DoSystemMessage( (DPMSG_GENERIC*)pvMsgBuffer, dwMsgBufferSize,
- idFrom, idTo );
- }
- else
- {
- DoApplicationMessage( (GENERICMSG*)pvMsgBuffer, dwMsgBufferSize,
- idFrom, idTo );
- }
- }
- else
- break;
- }
-
- return hr;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DoSystemMessage()
- // Desc: Evaluates system messages and performs appropriate actions
- //-----------------------------------------------------------------------------
- VOID DoSystemMessage( DPMSG_GENERIC* pMsg, DWORD dwMsgSize, DPID idFrom,
- DPID idTo )
- {
- switch( pMsg->dwType )
- {
- case DPSYS_CREATEPLAYERORGROUP:
- {
- DPMSG_CREATEPLAYERORGROUP* pAddMsg = (DPMSG_CREATEPLAYERORGROUP*)pMsg;
- int iLeastAmt = -1;
- int iLeastType = -1;
- int i;
-
- if( g_bHostPlayer)
- {
- g_HostMsg.Blocks = g_Blocks;
-
- //Copy the used ship types array into the message to be sent
- for( i = 0; i < NUM_SHIP_TYPES; i++ )
- g_HostMsg.usedShipTypes[i] = g_ShipTypesUsed[i];
-
- SendGameMessage( (GENERICMSG*)&g_HostMsg, pAddMsg->dpId );
- }
-
- // Loop through the used ship types array and find the one that's been used the least
- for( i = 0; i < NUM_SHIP_TYPES; i++ )
- {
- if( (iLeastAmt < 0) || (g_ShipTypesUsed[i] < iLeastAmt) )
- {
- iLeastAmt = g_ShipTypesUsed[i];
- iLeastType = i;
- }
- }
- g_ShipTypesUsed[iLeastType]++; // update our copy of the used ship types
- break;
- }
-
- case DPSYS_DESTROYPLAYERORGROUP:
- {
- SHIP* pShip;
- DPMSG_DESTROYPLAYERORGROUP* pDestroyMsg = (DPMSG_DESTROYPLAYERORGROUP*)pMsg;
-
- if( (sizeof(SHIP) != pDestroyMsg->dwLocalDataSize) ||
- (NULL == pDestroyMsg->lpLocalData))
- break;
-
- pShip = (SHIP*)pDestroyMsg->lpLocalData;
- g_ShipTypesUsed[pShip->byType]--; // decrement the leaving players' ship type usage counter
- ReleasePlayerLocalSoundData(pShip);
- break;
- }
-
- case DPSYS_HOST:
- {
- g_bHostPlayer = TRUE;
- UpdateTitle();
- break;
- }
-
- case DPSYS_SESSIONLOST:
- // inform user that session was lost
- TRACE(_T("Session lost\n"));
- if( !g_bSessionLost )
- {
- g_bSessionLost = TRUE;
- ShowError(IDS_DPLAY_ERROR_SL);
- }
- break;
-
- case DPSYS_SENDCOMPLETE:
- // Async send status
- {
- DPMSG_SENDCOMPLETE* pComplete = (DPMSG_SENDCOMPLETE*)pMsg;
-
- if( FAILED(pComplete->hr) )
- {
- TCHAR* strErr;
- switch( pComplete->hr )
- {
- case DPERR_CANCELLED: strErr = _T("Cancelled"); break;
- case DPERR_ABORTED: strErr = _T("Aborted"); break;
- case DPERR_TIMEOUT: strErr = _T("Timed out"); break;
- case DPERR_GENERIC: strErr = _T("Generic"); break;
- default: strErr = _T("Unknown");
- }
- TRACE(_T("Async msg %u to %u transmission failed. err = %s %#08X\n"),
- pComplete->dwMsgID, pComplete->idTo, strErr,
- pComplete->hr );
- }
- break;
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DoApplicationMessage()
- // Desc: Evaluates an application message and performs appropriate actions
- //-----------------------------------------------------------------------------
- VOID DoApplicationMessage( GENERICMSG* pMsg, DWORD dwMsgSize, DPID idFrom,
- DPID idTo )
- {
- HRESULT hr;
-
- switch( pMsg->byType )
- {
- case MSG_HOST:
- {
- HOSTMSG* pHostMsg = (HOSTMSG*)pMsg;
- SHIP ship;
- DWORD dwSize = sizeof (ship);
- int leastUsed = -1;
-
- if( !g_bHostPlayer )
- {
- // receive the field layout
- g_Blocks = pHostMsg->Blocks;
-
- // The Host keeps the official record of ship colors in use.
- // Sync up our data and recompute our color
- hr = DPUtil_GetPlayerLocalData( g_LocalPlayerDPID, &ship, &dwSize );
-
- // Insure that host is not a Beta version of Duel that does not
- // send the additional ShipTypesUsed.
- if( SUCCEEDED(hr) && dwMsgSize >= sizeof(HOSTMSG) )
- {
- // Loop through the used ship types array we were given,
- // copying it and finding the least used type for ourself.
- for( int i = 0; i < NUM_SHIP_TYPES; i++ )
- {
- g_ShipTypesUsed[i] = pHostMsg->usedShipTypes[i];
- if( (leastUsed < 0) || (g_ShipTypesUsed[i] < leastUsed) )
- {
- leastUsed = g_ShipTypesUsed[i];
- ship.byType = (char) i;
- }
- }
- g_ShipTypesUsed[ship.byType]++; // increment it because we used one
-
- hr = DPUtil_SetPlayerLocalData( g_LocalPlayerDPID, &ship, dwSize );
- }
-
- // Have host initializtion at this point
- g_bHaveHostInit = TRUE;
-
- // Start updating screen
- g_bIsActive = TRUE;
- }
- break;
- }
-
- case MSG_BLOCKHIT:
- {
- BLOCKHITMSG* pBlockHitMsg = (BLOCKHITMSG*)pMsg;
- g_Blocks.bits[pBlockHitMsg->byRow][pBlockHitMsg->byCol] &= ~pBlockHitMsg->byMask;
- break;
- }
-
- case MSG_ADDBLOCK:
- {
- ADDBLOCKMSG* pAddBlockMsg = (ADDBLOCKMSG*)pMsg;
- setBlock( pAddBlockMsg->byX, pAddBlockMsg->byY );
- break;
- }
-
- case MSG_SHIPHIT:
- {
- SHIPHITMSG* pShipHitMsg = (SHIPHITMSG*)pMsg;
- SHIP ship;
- DWORD dwSize;
-
- dwSize = sizeof(SHIP);
- // Get player local data
- hr = DPUtil_GetPlayerLocalData( pShipHitMsg->Id, &ship, &dwSize );
- if( FAILED(hr) )
- return;
-
- // No player data yet
- if( 0 == dwSize )
- return;
-
- if( !ship.bIgnore )
- {
- // Explode the ship on our screen
- DestroyShip( &ship );
-
- // Turn it off
- ship.bEnable = FALSE;
- ship.bBulletEnable = FALSE;
-
- // If it is us
- if( pShipHitMsg->Id == g_LocalPlayerDPID )
- {
- // Set our hide time-out
- ship.iCountDown = HIDE_TIMEOUT;
- ship.dwLastTick = timeGetTime();
- // Let the world know that we are dead
- g_ShipHitMsg.Id = g_LocalPlayerDPID;
- SendGameMessage( (GENERICMSG*)&g_ShipHitMsg, DPID_ALLPLAYERS );
- }
- }
- // Ppdate player local data
- DPUtil_SetPlayerLocalData( pShipHitMsg->Id, &ship, sizeof(ship) );
- break;
- }
-
- case MSG_CONTROL:
- {
- CONTROLMSG* pControlMsg = (CONTROLMSG*)pMsg;
- SHIP ship;
- DWORD dwSize;
-
- dwSize = sizeof(SHIP);
- // Get player local data
- hr = DPUtil_GetPlayerLocalData( idFrom, &ship, &dwSize );
- if( FAILED(hr) )
- return;
-
- // No player data yet
- if( 0 == dwSize )
- return;
-
- // Update its State
- UpdateState( &ship, (DWORD)pControlMsg->byState );
-
- // Save it back
- DPUtil_SetPlayerLocalData( idFrom, &ship, dwSize );
- break;
- }
-
- case MSG_SYNC:
- {
- SYNCMSG* pSyncMsg = (SYNCMSG*)pMsg;
- SHIP ship;
- DWORD dwSize;
-
- dwSize = sizeof(SHIP);
- // Get player local data
- hr = DPUtil_GetPlayerLocalData( idFrom, &ship, &dwSize );
- if( FAILED(hr) )
- return;
-
- // We are seeing this player for the first time
- // so do the initialization
- if( 0 == dwSize )
- {
- ZeroMemory( &ship, sizeof(ship) );
-
- ship.byType = pSyncMsg->byShipType;
- ship.dPosX = pSyncMsg->dPosX;
- ship.dPosY = pSyncMsg->dPosY;
- ship.cFrame = pSyncMsg->cFrame;
- ship.dwLastTick = timeGetTime();
- ship.bEnable = TRUE;
- ship.dpidID = idFrom;
-
- // initialize sound buffers
- InitPlayerLocalSoundData(&ship);
- }
-
- if( ship.bEnable )
- {
- // Head towards rendezvous location (accelerate/decelerate as necessary)
- ship.dVelX = (pSyncMsg->dPosX - ship.dPosX)/1000;
- ship.dVelY = (pSyncMsg->dPosY - ship.dPosY)/1000;
- ship.cFrame = pSyncMsg->cFrame;
- }
- else if( !ship.bIgnore )
- {
- // Ship is alive, but we just don't know it.
- // So, display it at the rendezvous location.
- ship.dPosX = pSyncMsg->dPosX;
- ship.dPosY = pSyncMsg->dPosY;
- ship.cFrame = pSyncMsg->cFrame;
- ship.dwLastTick = timeGetTime();
- ship.bEnable = TRUE;
- ship.dpidID = idFrom;
- }
-
- // Save it back
- DPUtil_SetPlayerLocalData( idFrom, &ship, sizeof(ship) );
- break;
- }
-
- default:
- {
- TRACE( TEXT("Unknown message type %d\n"), pMsg->byType );
- break;
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: SendGameMessage()
- // Desc: Sends a message to specified player(s)
- //-----------------------------------------------------------------------------
- VOID SendGameMessage( GENERICMSG* pMsg, DPID idTo )
- {
- int nBytes;
- DWORD dwFlags = 0;
-
- // No sends when we are not in the session
- if( g_bSessionLost )
- return;
-
- switch( pMsg->byType )
- {
- case MSG_HOST:
- nBytes = sizeof( HOSTMSG );
- dwFlags = DPSEND_GUARANTEED;
- break;
-
- case MSG_BLOCKHIT:
- nBytes = sizeof( BLOCKHITMSG );
- break;
-
- case MSG_SHIPHIT:
- nBytes = sizeof( SHIPHITMSG );
- break;
-
- case MSG_ADDBLOCK:
- nBytes = sizeof( ADDBLOCKMSG );
- break;
-
- case MSG_CONTROL:
- nBytes = sizeof( CONTROLMSG );
- break;
-
- case MSG_SYNC:
- nBytes = sizeof( SYNCMSG );
- break;
-
- default:
- return;
- }
-
- if( g_bAsync )
- dwFlags |= DPSEND_ASYNC;
- if( g_bReliable )
- dwFlags |= DPSEND_GUARANTEED;
-
- // Send the message to the relevant player(s)
- DPUtil_Send( g_LocalPlayerDPID, idTo, dwFlags, (VOID*)pMsg, nBytes );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CleanupComm()
- // Desc: Cleans up communication stuff
- //-----------------------------------------------------------------------------
- VOID CleanupComm()
- {
- HRESULT hr;
-
- // Free up all the local sound buffers
- ReleaseLocalData();
-
- // Free the receive buffer
- if( g_pvReceiveBuffer )
- {
- GlobalFreePtr(g_pvReceiveBuffer);
- g_pvReceiveBuffer = NULL;
- }
-
- // Delete our player
- if( g_LocalPlayerDPID )
- {
- hr = DPUtil_DestroyPlayer( g_LocalPlayerDPID );
- if( FAILED(hr) )
- {
- ShowError(IDS_DPLAY_ERROR_DP);
- }
- g_LocalPlayerDPID = 0;
- }
-
- // Cleanup DPlay objects
- hr = DPUtil_FreeDirectPlay();
- hr = DPUtil_Release();
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InitializeGameSounds()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT InitializeGameSounds()
- {
- if( FAILED( DSUtil_InitDirectSound( g_hwndMain ) ) )
- return E_FAIL;
-
- g_pShipEngineSound = DSUtil_CreateSound( TEXT("SENGINE"), 1 );
- g_pBulletFiringSound = DSUtil_CreateSound( TEXT("BFIRE"), NUM_SHIP_TYPES );
- g_pShipExplodeSound = DSUtil_CreateSound( TEXT("SBOOM"), NUM_SHIP_TYPES );
- g_pShipStartSound = DSUtil_CreateSound( TEXT("SSTART"), NUM_SHIP_TYPES );
- g_pShipStopSound = DSUtil_CreateSound( TEXT("SSTOP"), NUM_SHIP_TYPES );
- g_pShipBounceSound = DSUtil_CreateSound( TEXT("SBOUNCE"), NUM_SHIP_TYPES );
- g_pBlockExplodeSound = DSUtil_CreateSound( TEXT("LBOOM"), NUM_SHIP_TYPES );
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CleanupGameSounds()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID CleanupGameSounds()
- {
- DSUtil_DestroySound( g_pBulletFiringSound );
- DSUtil_DestroySound( g_pShipExplodeSound );
- DSUtil_DestroySound( g_pShipEngineSound );
- DSUtil_DestroySound( g_pShipStartSound );
- DSUtil_DestroySound( g_pShipStopSound );
- DSUtil_DestroySound( g_pShipBounceSound );
- DSUtil_DestroySound( g_pBlockExplodeSound );
- g_pBulletFiringSound = NULL;
- g_pShipExplodeSound = NULL;
- g_pShipEngineSound = NULL;
- g_pShipStartSound = NULL;
- g_pShipStopSound = NULL;
- g_pShipBounceSound = NULL;
- g_pBlockExplodeSound = NULL;
-
- DSUtil_FreeDirectSound();
- }
-
-
-
-