📄 gameproc.c
字号:
{
lpShip->dwKeys = dwControls;
if( dwControls & KEY_LEFT )
{
gbUpdate = TRUE;
lpShip->cFrame -= 1;
if( lpShip->cFrame < 0 )
lpShip->cFrame += MAX_SHIP_FRAME;
}
if( dwControls & KEY_RIGHT )
{
gbUpdate = TRUE;
lpShip->cFrame += 1;
if( lpShip->cFrame >= MAX_SHIP_FRAME )
lpShip->cFrame -= MAX_SHIP_FRAME;
}
if( dwControls & KEY_UP )
{
gbUpdate = TRUE;
lpShip->dVelX += gDirx[lpShip->cFrame] * 10.0 / 1000.0;
lpShip->dVelY += gDiry[lpShip->cFrame] * 10.0 / 1000.0;
}
if( dwControls & KEY_DOWN )
{
gbUpdate = TRUE;
lpShip->dVelX -= gDirx[lpShip->cFrame] * 10.0 / 1000.0;
lpShip->dVelY -= gDiry[lpShip->cFrame] * 10.0 / 1000.0;
}
if( dwControls & KEY_STOP )
{
gbUpdate = TRUE;
lpShip->dVelX = 0.0;
lpShip->dVelY = 0.0;
}
if( !lpShip->bBulletEnable && lpShip->bEnable )
{
if( dwControls & KEY_FIRE )
{
gbUpdate = TRUE;
// launch a new bullet
lpShip->dBulletPosX = (WORD) (gDirx[lpShip->cFrame]*6.0 + 16.0 + lpShip->dPosX);
lpShip->dBulletPosY = (WORD) (gDiry[lpShip->cFrame]*6.0 + 16.0 + lpShip->dPosY);
lpShip->dBulletVelX = gDirx[lpShip->cFrame]*500.0/1000.0;
lpShip->dBulletVelY = gDiry[lpShip->cFrame]*500.0/1000.0;
lpShip->bBulletEnable = TRUE;
lpShip->dwBulletFrame = 0;
}
}
}
/*
* SendSync
*
* 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(LPSHIP lpShip)
{
gSyncMsg.byShipType = lpShip->byType;
gSyncMsg.cFrame = lpShip->cFrame;
gSyncMsg.dPosX = lpShip->dPosX + lpShip->dVelX*1000;
gSyncMsg.dPosY = lpShip->dPosY + lpShip->dVelY*1000;
SendGameMessage((LPGENERICMSG) &gSyncMsg, DPID_ALLPLAYERS);
}
/*
* UpdateDisplayStatus
*
* Updates the disable timeout. Enables the ship if disable timeout has elapsed.
*/
void UpdateDisplayStatus(LPSHIP lpShip)
{
DWORD dwTickDiff;
DWORD dwTickCount;
// current time
dwTickCount = timeGetTime();
// time elapsed since last update
dwTickDiff = dwTickCount - lpShip->dwLastTick;
// timestamp
lpShip->dwLastTick = dwTickCount;
// update time-out
lpShip->iCountDown -= dwTickDiff;
// time-out ?
if( lpShip->iCountDown < 0 )
{
// get new position and enable our lpShip
lpShip->dPosX = randInt(0,MAX_SHIP_X);
lpShip->dPosY = randInt(0,MAX_SHIP_Y);
lpShip->cFrame = randInt(0, MAX_SHIP_FRAME);
lpShip->bEnable = TRUE;
}
}
/*
* UpdatePosition
*
* Updates our ship's position
*/
void UpdatePosition(DPID dpId, LPSHIP 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 == gOurID) && 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 == gOurID) && 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 == gOurID) && 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( gBlocks.bits[row][col] & mask )
{
// dwScored a block hit
gBlockHitMsg.byRow = row;
gBlockHitMsg.byCol = col;
gBlockHitMsg.byMask = mask;
SendGameMessage((LPGENERICMSG) &gBlockHitMsg, DPID_ALLPLAYERS);
gBlocks.bits[row][col] &= ~mask;
lpShip->dwScore += 10;
lpShip->bBulletEnable = FALSE;
lpShip->bBlockHit = TRUE;
lpShip->bFiring = FALSE;
}
}
}
/*
* IsHit
*
* 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( gBlocks.bits[y][col] & mask )
return TRUE;
else
return FALSE;
}
/*
* InitField
*
* Initializes block positions on the field
*/
void InitField(void)
{
int i, x, y;
// clear all gBlocks
for(x=0; x<5; x++)
for(y=0; y<30; y++)
gBlocks.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--;
}
}
/*
* AddBlock
*
* Adds a block to the field
*/
void AddBlock(void)
{
int x,y;
// maybe add a block?
if(gbIsHost && gbIsActive && ( randInt( 0, 100 ) > 98 ))
{
x = randInt( 0, 40);
y = randInt( 0, 30);
if( setBlock( x, y) )
{
gAddBlockMsg.byX = (BYTE) x;
gAddBlockMsg.byY = (BYTE) y;
SendGameMessage((LPGENERICMSG) &gAddBlockMsg, DPID_ALLPLAYERS);
}
}
}
/*
* setBlock
*
* 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( gBlocks.bits[y][col] & mask )
return FALSE;
// set the block and return success
gBlocks.bits[y][col] |= mask;
return TRUE;
}
/*
* AddFrag
*
* Turns on a fragment
*/
void AddFrag(LPSHIP lpShip, int offX, int offY)
{
int i;
for(i=0; i<64; i++) // find available fragment
{
if( !gFrags[i].valid )
break;
}
if( i == 64 )
return;
gFrags[i].dPosX = offX + lpShip->dPosX;
gFrags[i].dPosY = offY + lpShip->dPosY;
switch( lpShip->byType )
{
case 0: gFrags[i].surf = glpShip0; break;
case 1: gFrags[i].surf = glpShip1; break;
case 2: gFrags[i].surf = glpShip2; break;
case 3: gFrags[i].surf = glpShip3; break;
default: DEBUG_OUT(TEXT("Unknown ship type\n")); return;
}
gFrags[i].src.top = 32 * ( (int)lpShip->cFrame / 10 ) + offX;
gFrags[i].src.left = 32 * ( (int)lpShip->cFrame % 10 ) + offY;
gFrags[i].src.right = gFrags[i].src.left + 8;
gFrags[i].src.bottom = gFrags[i].src.top + 8;
gFrags[i].dVelX = ((double)offX - 12.0)/24.0;
gFrags[i].dVelY = ((double)offY - 12.0)/24.0;
gFrags[i].valid = TRUE;
}
/*
* UpdateFragment
*
* 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( !gFrags[i].valid )
return;
gFrags[i].dPosX += (int) (gFrags[i].dVelX * dwTickDiff);
gFrags[i].dPosY += (int) (gFrags[i].dVelY * dwTickDiff);
if( (gFrags[i].dPosX < 0.0) || (gFrags[i].dPosX >= 632.0) ||
(gFrags[i].dPosY < 0.0) || (gFrags[i].dPosY >= 472.0) )
{
gFrags[i].valid = FALSE;
}
}
/*
* DestroyShip
*
* Renders a bunch of fragments to show that the ship is destroyed
*/
void DestroyShip( LPSHIP lpShip )
{
// Set flag for explosion sound
lpShip->bDeath = TRUE;
// add ship fragments
AddFrag(lpShip, 0, 0);
AddFrag(lpShip, 8, 0);
AddFrag(lpShip, 16, 0);
AddFrag(lpShip, 24, 0);
AddFrag(lpShip, 0, 8);
AddFrag(lpShip, 8, 8);
AddFrag(lpShip, 16, 8);
AddFrag(lpShip, 24, 8);
AddFrag(lpShip, 0, 16);
AddFrag(lpShip, 8, 16);
AddFrag(lpShip, 16, 16);
AddFrag(lpShip, 24, 16);
AddFrag(lpShip, 0, 24);
AddFrag(lpShip, 8, 24);
AddFrag(lpShip, 16, 24);
AddFrag(lpShip, 24, 24);
// Play explosion sound
ProcessSoundFlags(lpShip);
}
/*
* UpdateFrame
*
* Refreshes the screen
*/
BOOL UpdateFrame( void )
{
int i;
DWORD dwTickCount;
SHIP ship;
DWORD dwSize;
HRESULT hr;
static dwSyncLastTick = 0;
static dwUpdateLastTick = 0;
switch( gnProgramState )
{
case PS_ACTIVE:
// DINPUT: use DirectInput to read game-play keys
DI_ReadKeys();
// get our local data
dwSize = sizeof(ship);
hr = DPlayGetPlayerData(gOurID, &ship, &dwSize, DPGET_LOCAL);
if (FAILED(hr))
{
wsprintf(gDebugBuff, TEXT("Get Player local data failed for id %d\n"), gOurID);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -