📄 gameproc.c
字号:
/*==========================================================================
*
* Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
*
* File: gameproc.c
* Content: Game processing code
*
*
***************************************************************************/
#include "gameproc.h"
#include "util.h"
#include "gfx.h"
#include "comm.h"
#include "input.h"
#include "lobby.h"
#include "wizard.h"
#include "dsound.h"
#include "sfx.h"
#include "stdio.h"
/*
* Externals
*/
extern DWORD gdwKeys;
extern LPDIRECTDRAWSURFACE glpShip0;
extern LPDIRECTDRAWSURFACE glpShip1;
extern LPDIRECTDRAWSURFACE glpShip2;
extern LPDIRECTDRAWSURFACE glpShip3;
extern BOOL gbShowFrameCount;
extern LPDIRECTDRAWSURFACE glpNum;
extern BOOL gbIsHost;
extern BOOL gbIsActive;
extern LPDPSESSIONDESC2 glpdpSD;
extern HWND ghWndMain;
extern HINSTANCE ghinst;
extern BOOL gbReliable;
/*
* Globals
*/
FRAG gFrags[64]; // ship framents
BLOCKS gBlocks; // field layout
LPVOID glpvReceiveBuffer = NULL; // buffer to store received messages
DWORD gdwReceiveBufferSize = 0; // size of buffer
DPID gOurID; // our player id
BOOL gbHaveHostInit; // do we need to do host initializaton
int gnProgramState; // current state of the game
DWORD gdwFrameCount; // used for fps calc
DWORD gdwFramesLast; // ..
DWORD gdwFrameTime; // ..
BOOL gbUpdate; // TRUE if player data needs to be updated
BOOL gbNoField; // display blocks ?
BOOL gbSessionLost; // did we get disconnected ?
HOSTMSG gHostMsg; // message buffer
BLOCKHITMSG gBlockHitMsg; // ..
SHIPHITMSG gShipHitMsg; // ..
ADDBLOCKMSG gAddBlockMsg; // ..
CONTROLMSG gControlMsg; // ..
SYNCMSG gSyncMsg; // ..
TCHAR gDebugBuff[MAX_ERRORMSG]; // buffer for debug output
/*
* Statics
*/
static double gDirx[40] =
{
0.000000,
0.156434,
0.309017,
0.453991,
0.587785,
0.707107,
0.809017,
0.891007,
0.951057,
0.987688,
1.000000,
0.987688,
0.951057,
0.891007,
0.809017,
0.707107,
0.587785,
0.453990,
0.309017,
0.156434,
0.000000,
-0.156435,
-0.309017,
-0.453991,
-0.587785,
-0.707107,
-0.809017,
-0.891007,
-0.951057,
-0.987688,
-1.000000,
-0.987688,
-0.951056,
-0.891006,
-0.809017,
-0.707107,
-0.587785,
-0.453990,
-0.309017,
-0.156434
};
static double gDiry[40] =
{
-1.000000,
-0.987688,
-0.951057,
-0.891007,
-0.809017,
-0.707107,
-0.587785,
-0.453990,
-0.309017,
-0.156434,
0.000000,
0.156434,
0.309017,
0.453991,
0.587785,
0.707107,
0.809017,
0.891007,
0.951057,
0.987688,
1.000000,
0.987688,
0.951057,
0.891006,
0.809017,
0.707107,
0.587785,
0.453990,
0.309017,
0.156434,
0.000000,
-0.156435,
-0.309017,
-0.453991,
-0.587785,
-0.707107,
-0.809017,
-0.891007,
-0.951057,
-0.987688
};
/*
* InitMessageBuffers
*
* Sets up buffes used for sending different types of messages
*/
void InitMessageBuffers(void)
{
gHostMsg.byType = MSG_HOST;
gBlockHitMsg.byType = MSG_BLOCKHIT;
gShipHitMsg.byType = MSG_SHIPHIT;
gAddBlockMsg.byType = MSG_ADDBLOCK;
gControlMsg.byType = MSG_CONTROL;
gSyncMsg.byType = MSG_SYNC;
}
/*
* LaunchGame
*
* Sets up the game layout and launches
*/
void LaunchGame(void)
{
HRESULT hr;
// initialize global message buffers
InitMessageBuffers();
// update window title
UpdateTitle();
// get current session description (glpdpSD is initialized in here)
hr = DPlayGetSessionDesc();
if (FAILED(hr) || (!glpdpSD))
{
ShowError(IDS_DPLAY_ERROR_GSD);
goto ABORT;
}
// initialize random number seed
srand((int)GetTickCount());
// clear front buffer before changing palette
EraseScreen();
FlipScreen();
// initialize us
hr = InitOurShip();
if (FAILED(hr))
{
goto ABORT;
}
// get the field layout
if( gbIsHost )
{
// initialize field (done only by host)
if (!gbNoField)
InitField();
// we have host initialization
gbHaveHostInit = TRUE;
// start updating screen
gbIsActive = TRUE;
}
else
{
// get it from host, if we are joining
gbHaveHostInit = FALSE;
}
// success
return;
ABORT:
// something went wrong, terminate game
ExitGame();
}
/*
* ExitGame
*
* Game termination code
*/
void ExitGame(void)
{
// shut down app
PostMessage( ghWndMain, WM_CLOSE, 0, 0 );
}
/*
* InitOurShip
*
* Initializes our ship's initial attributes
*/
HRESULT InitOurShip(void)
{
int i;
SHIP ship;
HRESULT hr;
// wipe out everything
ZeroMemory(&ship, sizeof(ship));
// initialize sound buffers
InitPlayerLocalSoundData(&ship);
// calculate ship type based on the number of players in the game
// we cycle through four ships (Y,R,G,B) for now.
ship.byType = (BYTE) ((glpdpSD->dwCurrentPlayers-1) % NUM_SHIP_TYPES);
ship.dPosX = randInt(0,MAX_SHIP_X);
ship.dPosY = randInt(0,MAX_SHIP_Y);
ship.cFrame = randInt(0, MAX_SHIP_FRAME);
ship.bEnable = TRUE;
// set our local data
hr = DPlaySetPlayerData(gOurID, &ship, sizeof(ship), DPSET_LOCAL);
if (FAILED(hr))
{
ShowError(IDS_DPLAY_ERROR_SPLD);
goto FAIL;
}
// no ship fragments
for(i=0; i<64; i++)
gFrags[i].valid = FALSE;
// success
return DP_OK;
FAIL:
// failed
return hr;
}
/*
*FUNCTION: InitPlayerLocalSoundData
*
*
*NOTES: Takes a ship and initializes ONLY its soundbuffers and sound flags.
* It leaves everything else alone. Good for when going to
* full-screen mode, when we need to get rid of the sound buffers
* for a bit, but don't want to change the data.
*/
void InitPlayerLocalSoundData(LPSHIP lpShip)
{
int i;
if (gbSoundInitialized)
{
for (i=0; i<MAX_SOUNDS; i++)
{
if (FALSE == WaveGetBuffers(gSoundEffect[i],&lpShip->lpDirectSoundBuffer[i], &lpShip->lpDirectSound3DBuffer[i]))
{//if it didn't work, get rid of all the other sound buffers
ShowError(IDS_DSOUND_DUPBUF);
for (--i; i>=0; i--)
{
IDirectSoundBuffer_Release(lpShip->lpDirectSoundBuffer [i]);
IDirectSoundBuffer_Release(lpShip->lpDirectSound3DBuffer[i]);
lpShip->lpDirectSoundBuffer [i] = NULL;
lpShip->lpDirectSound3DBuffer[i] = NULL;
}
return;
}
}
lpShip->bFiring = FALSE;
lpShip->bBounced = FALSE;
lpShip->bDeath = FALSE;
lpShip->bBlockHit = FALSE;
lpShip->bEngineRunning = FALSE;
lpShip->bMoving = FALSE;
}
else
{
//if sound initialization has already failed in InitSfx(), then we want the ships'
//sound buffers to be NULL so that we don't try to release them later.
for (i=0; i<MAX_SOUNDS; i++)
{
lpShip->lpDirectSoundBuffer [i] = NULL;
lpShip->lpDirectSound3DBuffer[i] = NULL;
}
}
};
/*
*FUNCTION: SetPlayerLocalSoundDataCB (CALLBACK)
*
*PURPOSE: Initializes and registers a player's local SOUND data ONLY.
*/
BOOL WINAPI SetPlayerLocalSoundDataCB(DPID dpId, DWORD dwPlayerType, LPCDPNAME lpName,
DWORD dwFlags, LPVOID lpContext)
{
SHIP ship;
DWORD dwSize = sizeof(ship);
HRESULT hr;
DPlayGetPlayerData(dpId, &ship, &dwSize, DPGET_LOCAL);
// no player data yet
if (0 == dwSize)
return TRUE;
InitPlayerLocalSoundData(&ship);
hr = DPlaySetPlayerData(dpId, &ship, dwSize, DPSET_LOCAL);
return (DP_OK == hr);
};
/*
*FUNCTION: InitLocalSoundData
*
*PURPOSE: Initializes and registers all players' sound data ONLY
*/
HRESULT InitLocalSoundData(void)
{
HRESULT hr;
hr = DPlayEnumPlayers(&(glpdpSD->guidInstance), SetPlayerLocalSoundDataCB, NULL, 0);
return hr;
}
/*
*FUNCTION: ReleaseLocalSoundData
*
*NOTES: Releases a single ship's local sound buffers.
*/
void ReleasePlayerLocalSoundData(LPSHIP lpShip)
{
int i;
if (gbSoundInitialized)
{
for (i=0; i<MAX_SOUNDS; i++)
{
if (lpShip->lpDirectSoundBuffer[i] != NULL)
{
IDirectSoundBuffer_Stop (lpShip->lpDirectSoundBuffer[i]);
IDirectSoundBuffer_Release (lpShip->lpDirectSoundBuffer[i]);
lpShip->lpDirectSoundBuffer[i] = NULL;
}
if (lpShip->lpDirectSound3DBuffer[i] != NULL)
{
IDirectSound3DBuffer_Release(lpShip->lpDirectSound3DBuffer[i]);
lpShip->lpDirectSound3DBuffer[i] = NULL;
}
}
}
};
/*
*FUNCTION: ReleasePlayerLocalData (CALLBACK)
*
*PURPOSE: Retrieves and releases a player's local data from dplay.
*/
BOOL WINAPI ReleasePlayerLocalDataCB(DPID dpId, DWORD dwPlayerType, LPCDPNAME lpName,
DWORD dwFlags, LPVOID lpContext)
{
SHIP ship;
DWORD dwSize = sizeof(SHIP);
HRESULT hr;
hr = DPlayGetPlayerData(dpId, &ship, &dwSize, DPGET_LOCAL);
if (FAILED(hr))
{
wsprintf(gDebugBuff, TEXT("Get Player local data failed for id %d\n"), dpId);
DEBUG_OUT(gDebugBuff);
goto FAIL;
}
// no player data yet
if (0 == dwSize)
return TRUE;
ReleasePlayerLocalSoundData(&ship);
hr = DPlaySetPlayerData(dpId, &ship, dwSize, DPSET_LOCAL);
if (FAILED(hr))
{
ShowError(IDS_DPLAY_ERROR_SPLD);
goto FAIL;
}
// success
return TRUE;
FAIL:
// we failed
return FALSE;
}
/*
*FUNCTION: ReleaseLocalData
*
*PURPOSE: Releases local data of ALL players.
*/
void ReleaseLocalData(void)
{
HRESULT hr;
if (gnProgramState == PS_ACTIVE)
{
hr = DPlayEnumPlayers(&(glpdpSD->guidInstance), ReleasePlayerLocalDataCB, NULL, 0);
if (FAILED(hr))
{
ShowError(IDS_DPLAY_ERROR_EP);
}
}
};
/*
* ProcessUserInput
*
* Processes any input from the user and updates our ship state
*/
void ProcessUserInput(LPSHIP lpShip)
{
static dwOldKeys = 0;
gbUpdate = FALSE;
// DSOUND: check if the engine was turned off
if (!(gdwKeys & (KEY_DOWN | KEY_UP)) &&
(dwOldKeys & (KEY_DOWN | KEY_UP)))
{
gdwKeys |= KEY_ENGINEOFF;
gControlMsg.byState = (BYTE) gdwKeys;
// let everyone know that we just turned our engine off
SendGameMessage((LPGENERICMSG) &gControlMsg, DPID_ALLPLAYERS);
}
// update our ship state
UpdateState(lpShip, gdwKeys);
// remember current keys for next frame
dwOldKeys = gdwKeys;
}
/*
* UpdateState
*
* Updates the current state of our ship, given user input
*/
void UpdateState(LPSHIP lpShip, DWORD dwControls)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -