📄 game.cpp
字号:
ddsd.dwHeight = height;
LPDIRECTDRAWSURFACE pdds;
if( FAILED(m_pDD->CreateSurface( &ddsd, &pdds, NULL )) )
return NULL;
return pdds;
}
void CGame::RestoreSurfaces()
{
m_pddsBackBuffer->Restore();
m_pddsFrontBuffer->Restore();
for( int i = 0; i < NUM_BITMAPS; i ++ )
m_pBmpList[i]->Restore();
DDReLoadBitmap( m_pBmpList[0], "Tile" );
DDReLoadBitmap( m_pBmpList[1], "Player1" );
DDReLoadBitmap( m_pBmpList[2], "Bullet" );
DDReLoadBitmap( m_pBmpList[3], "Explode1" );
DDReLoadBitmap( m_pBmpList[4], "Explode2" );
DDReLoadBitmap( m_pBmpList[5], "Enemys" );
DDReLoadBitmap( m_pBmpList[6], "Bonus" );
DDReLoadBitmap( m_pBmpList[7], "Bore" );
DDReLoadBitmap( m_pBmpList[8], "Misc" );
DDReLoadBitmap( m_pBmpList[9], "Player2" );
DDReLoadBitmap( m_pBmpList[10], "Splash" );
DDReLoadBitmap( m_pBmpList[11], "GameOver" );
//12
//13
DDReLoadBitmap( m_pBmpList[14], "Shield" );
DDReLoadBitmap( m_pBmpList[15], "About" );
DDReLoadBitmap( m_pBmpList[16], "Logo" );
}
void CGame::DDClear( RECT* prc, DWORD dwFillColor )
{
DDBLTFX ddbfx;
ZeroMemory( &ddbfx, sizeof(ddbfx) );
ddbfx.dwSize = sizeof(ddbfx);
ddbfx.dwFillColor = dwFillColor;
m_pddsBackBuffer->Blt( prc, NULL, NULL,
DDBLT_COLORFILL | DDBLT_WAIT, &ddbfx );
}
void CGame::ProcessInput()
{
static DWORD lastTick = timeGetTime();
DWORD time = timeGetTime() - lastTick;
CBullet* bullet;
float x, y;
DIRECTION dir;
int surface;
int i, j, k;
lastTick = timeGetTime();
// process player's input
WORD input[2];
m_DirectInput.GetKey( input[0], input[1] );
for( k = 0; k < 2; k ++ )
{
if( !m_player[k].m_active )
continue;
x = m_player[k].m_x;//save old pos and dir
y = m_player[k].m_y;
dir = m_player[k].m_dir;
surface = m_plane.GetSurface( m_player[k] );
if(surface==OBJ_ICE) //reduce speed of player that is on ice
m_player[k].m_speed=0.8f;
else
m_player[k].m_speed=2.8f;
if( !m_player[k].m_bBoring && m_gameState != GS_OVER )
{
if( m_player[k].ProcessInput(input[k], time) )//refresh new pos and dir via this func
m_DirectSound.Play( EFFECT_FIRE );
}
surface = m_plane.GetSurface( m_player[k] );
if( surface != OBJ_NULL &&
surface != OBJ_TREE && surface!=OBJ_ICE)
{
m_player[k].m_x = x;
m_player[k].m_y = y;
m_player[k].m_dir = dir;
}
if( m_player[k].HitTest( m_player[!k], (int)x, (int)y ) )
{
//two players hit together
m_player[k].m_x = x;
m_player[k].m_y = y;
m_player[k].m_dir = dir;
}
for( i = 0; i < m_nMaxEnemys; i ++ )
{
if( m_player[k].HitTest( m_enemy[i], (int)x, (int)y ) )
{
// we hit the enemy
m_player[k].m_x = x;
m_player[k].m_y = y;
m_player[k].m_dir = dir;
break;
}
}
if( m_player[k].HitTest( m_bonus ) )
{
// we hit the bonus
EatBonus( m_player[k] );
}
// bullet
for( j = 0; j < 3; j ++ )
{
bullet = &m_player[k].m_bullet[j];
if( !bullet->m_active )
continue;
if( !bullet->Move() )
{
bullet->m_active = FALSE;
continue;
}
int surface = m_plane.HitSurface( *bullet, m_player[k].m_type>=2 );
if( surface == OBJ_BRICK )
{
bullet->m_active = FALSE;
Explode( *bullet );
}
else if( surface == OBJ_CONCRETE )
{
bullet->m_active = FALSE;
Explode( *bullet );
m_DirectSound.Play( EFFECT_HIT );
}
else if( surface == OBJ_HAWK )
{
bullet->m_active = FALSE;
Explode( *bullet, TRUE );
m_DirectSound.Play( EFFECT_EXPLODE );
//m_
m_gameState = GS_OVER;
}
if( !m_bSingle &&
bullet->HitTest( m_player[!k] ) )
{
// We hit the other player
bullet->m_active = FALSE;
if( !m_player[!k].m_bShield )
m_player[!k].Lock();
}
for( i = 0; i < m_nMaxEnemys; i ++ )
{
if( !m_enemy[i].m_bShield && !m_enemy[i].m_bBoring &&
bullet->HitTest( m_enemy[i] ) )
{
// our bullet hit the enemy
bullet->m_active = FALSE;
Explode( *bullet );
if( m_enemy[i].m_bBonus )
{
m_enemy[i].m_bBonus = FALSE;
BoreBonus();
}
if( m_enemy[i].m_type >= 2 )
{
m_enemy[i].m_level=m_enemy[i].m_level-m_player[k].m_type-1;
if( m_enemy[i].m_level < 0 )
m_enemy[i].m_active = FALSE;
else
m_DirectSound.Play( EFFECT_HIT );
}
else
m_enemy[i].m_active = FALSE;
if( !m_enemy[i].m_active )
{
// the enemy is dead
Explode( m_enemy[i], TRUE );
m_DirectSound.Play( EFFECT_EXPLODE );
m_nEnemys --;
m_player[k].m_nScore += (m_enemy[i].m_type+1) * 10; //rewards score
}
break;
}
else if( bullet->HitTest( m_enemy[i].m_bullet[0] ) )
{
// our bullet hit the enemy's
bullet->m_active = FALSE;
m_enemy[i].m_bullet[0].m_active = FALSE;
break;
}
}
}
}
if( !m_bSingle )
{
for( i = 0; i < 2; i ++ )
for( j = 0; j < 2; j ++ )
{
if( m_player[0].m_bullet[i].HitTest(
m_player[1].m_bullet[j] ) )
{
// two players' bullet hit together
m_player[0].m_bullet[i].m_active = FALSE;
m_player[1].m_bullet[j].m_active = FALSE;
}
}
}
// process enemys
for( i = 0; i < m_nMaxEnemys; i ++ )
{
if( !m_bEnemyLocked && !m_enemy[i].m_bBoring &&
m_enemy[i].m_active )
{
x = m_enemy[i].m_x;
y = m_enemy[i].m_y;
dir = m_enemy[i].m_dir;
float oldspeed=m_enemy[i].m_speed;
surface=m_plane.GetSurface(m_enemy[i]);
if(surface==OBJ_ICE)
m_enemy[i].m_speed=0.8f;
else
m_enemy[i].m_speed=oldspeed;
if( rand() % 200 == 0 ||
!m_enemy[i].Move() )
{
m_enemy[i].ChangeDirection();
}
m_enemy[i].m_speed=oldspeed; //restore speed for next effect
surface = m_plane.GetSurface( m_enemy[i] );
if( surface == OBJ_BRICK )
{
if( rand() % 100 < 30 )
{
m_enemy[i].ChangeDirection();
surface = m_plane.GetSurface( m_enemy[i] );
}
else
m_enemy[i].Fire();
}
else if( surface == OBJ_CONCRETE ||
surface == OBJ_RIVER )
{
m_enemy[i].ChangeDirection();
surface = m_plane.GetSurface( m_enemy[i] );
}
if( m_enemy[i].HitTest( m_player[0], (int)x, (int)y ) ||
m_enemy[i].HitTest( m_player[1], (int)x, (int)y ) )
{
m_enemy[i].m_x = x;
m_enemy[i].m_y = y;
m_enemy[i].m_dir = dir;
m_enemy[i].Fire();
}
else if( surface != OBJ_NULL && surface != OBJ_TREE && surface!=OBJ_ICE)
{
m_enemy[i].m_x = x;
m_enemy[i].m_y = y;
m_enemy[i].m_dir = dir;
}
for( int j = 0; j < m_nMaxEnemys; j ++ )
{
if( i != j &&
m_enemy[i].HitTest( m_enemy[j], (int)x, (int)y ) )
{
// two enemys hit each other
m_enemy[i].ChangeDirection();
if( m_enemy[i].HitTest( m_enemy[j], (int)x, (int)y ) )
{
m_enemy[i].m_x = x;
m_enemy[i].m_y = y;
m_enemy[i].m_dir = dir;
}
break;
}
}
// the enemy can also eat the bonus
if( m_enemy[i].HitTest( m_bonus ) )
EatBonus( m_enemy[i] );
if( random(0,10-m_nLevel/4) == 2 )
m_enemy[i].Fire();
}
bullet = &m_enemy[i].m_bullet[0];
if( bullet->m_active )
{
if( !bullet->Move() )
bullet->m_active = FALSE;
surface = m_plane.HitSurface(*bullet,m_enemy[i].m_type>3 );
if( surface == OBJ_BRICK ||
surface == OBJ_CONCRETE )
{
bullet->m_active = FALSE;
Explode( *bullet );
}
else if( surface == OBJ_HAWK )
{
bullet->m_active = FALSE;
Explode( *bullet, TRUE );
m_DirectSound.Play( EFFECT_EXPLODE );
m_gameState = GS_OVER;
}
for( k = 0; k < 2; k ++ )
{
if( bullet->HitTest( m_player[k] ) )
{
// enemy's bullet hit us
bullet->m_active = FALSE;
if( !m_player[k].m_bShield )
{
if(--(m_player[k].m_nArmor)<0)
{
Explode( *bullet );
PlayerBeenHit( m_player[k] );
m_DirectSound.Play( EFFECT_EXPLODE );
}
else
m_DirectSound.Play( EFFECT_HIT );
}
}
}
}
}
// produce some enemys...
static DWORD lastTime;
DWORD thisTime = timeGetTime();
if( thisTime - lastTime > 3000 )
{
lastTime = thisTime;
BoreEnemy();
}
// It's time to unlock the enemys
if( m_bEnemyLocked &&
thisTime - m_lockTime > 10000 )
{
m_bEnemyLocked = FALSE;
}
if( m_nEnemys <= 0 && m_gameState == GS_ACTIVE )
{
m_gameState = GS_WIN;
m_lastTime = timeGetTime();
}
if( !m_player[0].m_active && !m_player[1].m_active )
m_gameState = GS_OVER;
}
void CGame::DrawWorld()
{
RECT rc;
DrawGround();
rc.left = 608;
rc.right = 640;
rc.top = 0;
rc.bottom = 480;
DDClear( &rc, 0 );
m_plane.Draw( m_pddsBackBuffer );
for( int i = 0; i < m_nMaxEnemys; i ++ )
m_enemy[i].Draw( m_pddsBackBuffer );
m_player[0].Draw( m_pddsBackBuffer );
m_player[1].Draw( m_pddsBackBuffer );
m_plane.DrawTree( m_pddsBackBuffer );
for( i = 0; i < NUM_EXPLODES; i ++ )
m_explode[i].Draw( m_pddsBackBuffer );
m_bonus.Draw( m_pddsBackBuffer );
char num[5];
sprintf(num,"%d",m_nEnemysLeft);
OutputText(610,50,num);
rc.left=0;
rc.right=32;
rc.top=0;
rc.bottom=32;
m_pddsBackBuffer->BltFast( 608, 10, m_pBmpList[8], &rc,
DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
rc.left = 32;
rc.right = rc.left + 32;
m_pddsBackBuffer->BltFast( 608, 200, m_pBmpList[8], &rc,
DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
sprintf(num,"%d",m_player[0].m_nLife);
OutputText(610,240,num);
sprintf(num,"%d",m_player[0].m_nScore);
OutputText( 608, 255, num);
/*m_pddsBackBuffer->BltFast( 20, 20, m_pBmpList[8], &rc,
DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
rc.left = 14;
rc.right = rc.left + 14;
m_pddsBackBuffer->BltFast( 550, 317, m_pBmpList[8], &rc,
DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
BltNumber( 570, 317, m_player[0].m_nLife );*/
if( !m_bSingle )
{
rc.left = 64;
rc.right = 64+32;
m_pddsBackBuffer->BltFast( 608, 300, m_pBmpList[8],
&rc, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
sprintf(num,"%d",m_player[1].m_nLife);
OutputText(610,340,num);
sprintf(num,"%d",m_player[1].m_nScore);
OutputText( 608, 355, num);
}
// draw level No.
rc.left=96;
rc.right=128;
m_pddsBackBuffer->BltFast( 608, 410, m_pBmpList[8], &rc,
DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
sprintf(num,"%d", m_nLevel );
OutputText(610,450,num);
}
void CGame::BltNumber( int x, int y, int n )
{
char szNum[20];
sprintf( szNum, "%d", n );
int len = lstrlen( szNum );
for( int i = 0; i < len; i ++ )
{
RECT rc;
rc.left = (szNum[i] - '0') * 14;
rc.right = rc.left + 14;
rc.top = 0;
rc.bottom = 14;
m_pddsBackBuffer->BltFast( x, y, m_pBmpList[13], &rc,
DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
x += 15;
}
}
void CGame::DoSplash()
{
HRESULT hr;
DDClear( NULL, 0 );
hr = m_pddsBackBuffer->BltFast( 135, 130, m_pBmpList[10], NULL,
DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
if( hr == DDERR_SURFACELOST )
RestoreSurfaces();
RECT rc;
rc.left = 0;
rc.right = 32;
rc.top = 32;
rc.bottom = 64;
m_pddsBackBuffer->BltFast( 200, 300 + 30*m_iSel,
m_pBmpList[1], &rc, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
OutputText(550,450,"V 0.11 Siney");
}
void CGame::UpdateFrame()
{
static DWORD lastTick;
static float fps;
if(timeGetTime()-lastTick<20)
return;
lastTick = timeGetTime();
if( m_gameState == GS_OVER || m_gameState == GS_ACTIVE ||
m_gameState == GS_WIN )
ProcessInput(); //process input
switch( m_gameState )
{
case GS_SPLASH:
DoSplash();
break;
case GS_OVER:
DrawWorld();
m_pddsBackBuffer->BltFast( 200, 200, m_pBmpList[11],
NULL, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT );
break;
case GS_ACTIVE:
DrawWorld();
break;
case GS_WIN:
DrawWorld();
if( timeGetTime() - m_lastTime > 3000 ||
timeGetTime() < m_lastTime )
{
m_gameState = GS_ACTIVE;
m_nLevel ++;
InitLevel();
}
break;
case GS_ABOUT:
DoAbout();
break;
case GS_BEGIN:
DoBegin();
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -