📄 gamebo~1.cpp
字号:
register const int nLines = m_pCurPiece->GetLines();
for( register int l = nLines - 1 ; l >= 0 ; l-- ) {
for( register int c = 0 ; c < nCols ; c++ ) {
register const int nL = nLine - ((nLines-1) & l) ;
register const int nC = nCol + c;
if( m_pCurPiece->IsSquare(l, c) ) {
if( nL >= Height() || nC < 0 || nC >= Width() )
return false;
else if( nL >= 0 && m_Board[nL][nC] != m_clrBackground )
return false;
}
}
}
return true;
}
void CGameBoard::CheckBoard()
{
for( register int l = Height() - 1 ; l > 0 ; --l ) {
bool bLineComplete = true;
for( register int c = Width() - 1 ; c >= 0 ; --c ) {
ASSERT(l>0);
ASSERT(c>=0);
if( m_Board[l][c] == m_clrBackground ) {
bLineComplete = false;
break;
}
}
if( bLineComplete ) {
// show animated annihilation of that line
{
UINT * low = guBoomArray;
UINT * high = ENDVEC(guBoomArray);
CClientDC cdc(this);
int nWidth = Width();
m_SndLineComplete.Play();
while( low <= high ) {
HICON hIcon = AfxGetApp()->LoadIcon(*low);
if( ! hIcon )
break;
for( register c1 = nWidth - 1; c1 >= 0; --c1 )
::DrawIconEx(
cdc.GetSafeHdc(),
c1 * m_nSquareWidth, l * m_nSquareHeight,
hIcon,
m_nSquareWidth, m_nSquareHeight,
0, 0, DI_NORMAL
);
::Sleep(100);
++low;
}
}
// remove that line from the board
for( register int l1 = l ; l1 > 0 ; --l1 ) {
for( register int c1 = Width() - 1 ; c1 >= 0 ; --c1 ) {
ASSERT( l1 > 0 ) ;
ASSERT( c1 >= 0 ) ;
m_Board[l1][c1] = m_Board[l1-1][c1] ;
}
}
++l ; // try same line again ...
OnLineComplete();
m_SndPlace.Play();
Paint();
}
}
}
void CGameBoard :: FixPiece() {
ASSERT( m_pCurPiece != 0 ) ;
m_SndPlace.Play();
register const int nCols = m_pCurPiece->GetColumns() ;
register const int nLines = m_pCurPiece->GetLines() ;
for( register int l = nLines - 1 ; l >= 0 ; l-- ) {
for( register int c = 0 ; c < nCols ; c++ ) {
if( m_pCurPiece->IsSquare( l, c ) ) {
int nL = m_nCurLine - ((nLines-1) & l) ;
int nC = m_nCurCol + c ;
if( nL >= 0 ) {
ASSERT( nL < Height() ) ;
ASSERT( nC >= 0 ) ;
ASSERT( nC < Width() ) ;
m_Board[nL][nC] = m_clrCurPiece;
}
}
}
}
m_uPoints += UINT(m_pCurPiece->GetPoints()) + m_usLevel + (m_bExFigures ? 10 : 0);
}
void CGameBoard::OnLineComplete()
{
++m_ulCompleteLines;
m_uPoints += m_bExFigures ? 20 : 10;
if( (m_ulCompleteLines % 10) == 0 ) {
m_SndLevelWarp.Play();
++m_usLevel;
m_uPoints += m_bExFigures ? 20 : 10;
if( m_usLevel >= 2 && m_bShowGrid )
m_bShowGrid = FALSE;
ResetTimer();
}
NotifyParent();
}
void CGameBoard::StartGame()
{
InitBoard();
ResetTimer();
if( m_pMusic )
m_pMusic->Play(TRUE);
}
void CGameBoard::StopGame()
{
KillTimer(m_uTimer);
if( m_pMusic )
m_pMusic->Stop();
}
void CGameBoard::ResumeGame()
{
ResetTimer();
if( m_pMusic )
m_pMusic->Continue();
}
void CGameBoard::PauseGame()
{
KillTimer(m_uTimer);
if( m_pMusic )
m_pMusic->Pause();
}
void CGameBoard :: OnNewPiece()
{
++m_ulPieces;
NotifyParent();
ResetTimer();
}
void CGameBoard :: OnGameOver()
{
StopGame();
CWnd * pParent = GetParent();
ASSERT(pParent != 0);
m_BoardNotifier.hdr.hwndFrom = GetSafeHwnd();
m_BoardNotifier.hdr.idFrom = UINT(::GetWindowLong(GetSafeHwnd(), GWL_ID));
m_BoardNotifier.hdr.code = NMB_GAMEOVER;
m_SndGameOver.Play();
pParent->SendMessage(WM_NOTIFY, WPARAM(m_BoardNotifier.hdr.idFrom), LPARAM(&m_BoardNotifier.hdr));
}
void CGameBoard::OnTimer(UINT nIDEvent)
{
if( m_pNextPiece == 0 ) {
m_pNextPiece = SelectPiece();
NotifyParent(FALSE);
}
if( m_pCurPiece == 0 ) {
m_pCurPiece = m_pNextPiece;
m_pNextPiece = 0;
do {
m_clrCurPiece = RGB(rand()%255, rand()%255, rand()%255);
} while( m_clrCurPiece == m_clrBackground );
m_nCurLine = 1;
if( m_usLevel >= 4 )
// random startpoint ...
m_nCurCol = rand() % (Width()-m_pCurPiece->GetColumns()) ;
else
// fixed (centered) startpoint ...
m_nCurCol = (Width() - m_pCurPiece->GetColumns()) / 2 ;
if( ! CanPlace( m_nCurLine, m_nCurCol ) ) {
OnGameOver();
return ;
}
OnNewPiece();
} else {
if( ! CanPlace( m_nCurLine+1, m_nCurCol ) ) {
FixPiece() ;
delete m_pCurPiece ;
m_pCurPiece = 0 ;
CheckBoard() ;
} else
m_nCurLine++ ;
}
Paint() ;
}
LRESULT CALLBACK GameBoardWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch (uiMsg) // Dispatch on message type
{
case WM_NCCREATE: // On WM_NCCREATE we create a C++ object and attach it to the control
{
CGameBoard * pCtl = new CGameBoard(); // Create an instance of the class
ASSERT(pCtl); // Better not fail!
BOOL b = pCtl->SubclassWindow(hWnd); // Attach the window handle to the new object
ASSERT(b); // Better not fail!
return b; // Return result to continue/abort window creation
break;
}
default: // All other messages go through default window processor
return ::DefWindowProc(hWnd, uiMsg, wParam, lParam);
}
}
void CGameBoard::OnNcDestroy()
{
CWnd::OnNcDestroy();
// Make sure the window was destroyed
ASSERT(NULL == m_hWnd);
// Destroy this object since it won't be destroyed otherwise
delete this;
}
int CGameBoard::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// Set the styles for the parent control
ModifyStyleEx(0, WS_EX_CLIENTEDGE | WS_EX_NOPARENTNOTIFY);
m_SndKey.Create(IDR_SndKey);
m_SndPlace.Create(IDR_SndPlace);
m_SndLevelWarp.Create(IDR_SndLevelWarp);
m_SndGameOver.Create(IDR_SndGameOver);
m_SndLineComplete.Create(IDR_SndLineComplete);
return 0;
}
BOOL CGameBoard::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CGameBoard :: NotifyParent(BOOL bStatistics /* = TRUE */)
{
CWnd * pParent = GetParent();
ASSERT(pParent != 0);
NMHDR & hdr = bStatistics ? m_BoardNotifier.hdr : m_PreviewNotifier.hdr;
hdr.hwndFrom = GetSafeHwnd();
hdr.idFrom = UINT(::GetWindowLong(GetSafeHwnd(), GWL_ID));
hdr.code = bStatistics ? NMB_STATISTICS : NMB_PREVIEW;
if( bStatistics ) {
m_BoardNotifier.level = UINT(m_usLevel);
m_BoardNotifier.lines = UINT(m_ulCompleteLines);
m_BoardNotifier.pieces = UINT(m_ulPieces);
m_BoardNotifier.points = UINT(m_uPoints);
} else {
ASSERT(m_pNextPiece != 0);
m_PreviewNotifier.piece = m_pNextPiece;
}
pParent->SendMessage(WM_NOTIFY, WPARAM(hdr.idFrom), bStatistics ? LPARAM(&m_BoardNotifier) : LPARAM(&m_PreviewNotifier));
}
CPiece * CGameBoard::SelectPiece()
{
CPiece * pPiece = 0;
switch( rand() % (m_bExFigures ? 11 : 7) ) {
case 0:
pPiece = new CLongPiece();
break;
case 1:
pPiece = new CSquarePiece();
break;
case 2:
pPiece = new CRevLShapePiece();
break;
case 3:
pPiece = new CLShapePiece();
break;
case 4:
pPiece = new CTeeShapePiece();
break;
case 5:
pPiece = new CSShapePiece();
break;
case 6:
pPiece = new CRevSShapePiece();
break;
case 7:
pPiece = new CCrossShapePiece();
break;
case 8:
pPiece = new CUShapePiece();
break;
case 9:
pPiece = new CZShapePiece();
break;
case 10:
pPiece = new CRevZShapePiece();
break;
}
ASSERT(pPiece != 0);
return pPiece;
}
void CGameBoard::ResetTimer(BOOL bSpeed)
{
if( m_uTimer )
KillTimer(m_uTimer);
srand(time(0));
UINT uElaps = (m_usLevel < 20 && ! bSpeed) ? 500-(m_usLevel*25) : 50;
m_uTimer = SetTimer(2, uElaps, 0);
}
void CGameBoard::EnableSound(BOOL bEnable) {
m_SndKey.EnableSound(bEnable);
m_SndPlace.EnableSound(bEnable);
m_SndLevelWarp.EnableSound(bEnable);
m_SndGameOver.EnableSound(bEnable);
m_SndLineComplete.EnableSound(bEnable);
}
void CGameBoard::EnableMusic(BOOL bEnable) {
delete m_pMusic;
m_pMusic = 0;
if( bEnable )
m_pMusic = new CMIDI();
}
void CGameBoard::SetMusicType(UINT uResource) {
if( m_pMusic ) {
m_pMusic->Create(uResource, this);
m_pMusic->SetVolume(m_dwVolume);
}
}
void CGameBoard::OnMouseMove(UINT nFlags, CPoint point)
{
::SetCursor(0);
CWnd::OnMouseMove(nFlags, point);
}
LONG CGameBoard :: OnVolumeChanged(WPARAM wParam, LPARAM lParam) {
ASSERT(m_pMusic != 0);
ASSERT(m_pMusic == (CMIDI *)wParam);
// Volume of music changed during playback.
// Reset the volume to what we want it to be.
m_pMusic->SetChannelVolume(LOWORD(lParam), m_dwVolume);
return 0;
}
void CGameBoard :: SetVolume(DWORD dwPercent) {
ASSERT(dwPercent <= 100);
m_dwVolume = dwPercent;
if( m_pMusic )
m_pMusic->SetVolume(m_dwVolume);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -