www.pudn.com > CarCrash.rar > CarThread.cpp
// CarThread.cpp : implementation file // #include "stdafx.h" #include "CarCrash.h" #include "CarThread.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif CRITICAL_SECTION CCarThread::cs; CRITICAL_SECTION CCarThread::csCrash; CDC CCarThread::m_MemDC; vectorCCarThread::m_Cars; CBitmap CCarThread::m_bmpCars[8]; //HANDLE CCarThread::m_hEventSimulationStop; ///////////////////////////////////////////////////////////////////////////// // CCarThread IMPLEMENT_DYNCREATE(CCarThread, CWinThread) CCarThread::CCarThread():m_nBmpId(0) { } CCarThread::~CCarThread() { CloseHandle(m_hEventKill); } BOOL CCarThread::InitInstance() { m_DC.Attach(m_hDC); while(WaitForSingleObject(m_hEventKill,0)==WAIT_TIMEOUT) { EnterCriticalSection(&cs); m_pParent->GetClientRect(&m_pMainBorder); CBitmap *pOldBmp=m_MemDC.SelectObject(&m_bmpCars[m_nBmpId]); m_DC.BitBlt(m_ptPosition.x,m_ptPosition.y,m_bmpRect.Width(),m_bmpRect.Height(),NULL,0,0,WHITENESS); if (RandomVelocityChange()) UpdateBitmap(); else if (!m_pMainBorder.PtInRect(m_ptPosition)) { m_ptVelocity=-m_ptVelocity; UpdateBitmap(); } m_ptPosition+=m_ptVelocity; m_DC.BitBlt(m_ptPosition.x,m_ptPosition.y,m_bmpRect.Width(),m_bmpRect.Height(),&m_MemDC,0,0,SRCCOPY); m_MemDC.SelectObject(pOldBmp); LeaveCriticalSection(&cs); vector *pThreadKilled; if (CheckCrash(this,&pThreadKilled)) { ::PostMessage(m_pParent->GetSafeHwnd(),MSG_KILLME,(WPARAM) /*this*/pThreadKilled,(LPARAM) 0); break; } Sleep(30); } m_DC.Detach(); return FALSE; //important otherwise it will enter the message loop and the thread will not terminate } int CCarThread::ExitInstance() { // TODO: perform any per-thread cleanup here return CWinThread::ExitInstance(); } BEGIN_MESSAGE_MAP(CCarThread, CWinThread) //{{AFX_MSG_MAP(CCarThread) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCarThread message handlers CCarThread::CCarThread(CWnd *pParent,HDC hDC,CRect r/*,UINT UID,CPoint ptPos,CPoint ptVel*/) { m_pParent=pParent; m_hDC=hDC; m_pMainBorder=r; m_ptVelocity=CPoint(rand() % 3 -1,rand()%3-1); if (m_ptVelocity==CPoint(0,0)) m_ptVelocity=CPoint(1,0); UpdateBitmap(); m_ptPosition=CPoint(rand()% r.Width(),rand()% r.Height()); m_hEventKill=CreateEvent(NULL,TRUE,FALSE,NULL); m_hEventDead=CreateEvent(NULL,TRUE,FALSE,NULL); m_nChanged=rand()%100+50; m_bAutoDelete=FALSE; //very important otherwise thread will destroy itself as soon as delete is called and no member or event can then be accessed } void CCarThread::UpdateBorder() { EnterCriticalSection(&cs); { m_pParent->GetClientRect(&m_pMainBorder); } LeaveCriticalSection(&cs); } void CCarThread::KillThread() { _ASSERT(SetEvent(m_hEventKill)); SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL); WaitForSingleObject(m_hEventDead,INFINITE); WaitForSingleObject(m_hThread,INFINITE); delete this; } void CCarThread::Delete() { CWinThread::Delete(); VERIFY(SetEvent(m_hEventDead)); } void CCarThread::UpdateBitmap() { if (m_ptVelocity==CPoint(0,1)) { m_nBmpId=0; } else if (m_ptVelocity==CPoint(0,-1)) { m_nBmpId=1; } else if (m_ptVelocity==CPoint(-1,0)) { m_nBmpId=2; } else if (m_ptVelocity==CPoint(1,0)) { m_nBmpId=3; } else if (m_ptVelocity==CPoint(1,-1)) { m_nBmpId=4; } else if (m_ptVelocity==CPoint(-1,-1)) { m_nBmpId=5; } else if (m_ptVelocity==CPoint(1,1)) { m_nBmpId=6; } else if (m_ptVelocity==CPoint(-1,1)) { m_nBmpId=7; } BITMAP bmpInfo; m_bmpCars[m_nBmpId].GetBitmap(&bmpInfo); m_bmpRect=CRect(0,0,bmpInfo.bmWidth,bmpInfo.bmHeight); } bool CCarThread::RandomVelocityChange() { m_nChanged--; if ( m_nChanged) return false; //just random m_nChanged=rand()%100+50; if (m_ptVelocity.x==0) m_ptVelocity.x=rand()%2?-1:1; else if (m_ptVelocity.y==0) m_ptVelocity.y=rand()%2?-1:1; else if (rand()%2) m_ptVelocity.x=0; else m_ptVelocity.y=0; return true; } bool CCarThread::CheckCrash(CCarThread* pThread,vector **ppThreadKilled) { if (WaitForSingleObject(pThread->m_hEventKill,0)!=WAIT_TIMEOUT) return false; bool bRetVal=false; CRect IntersectRect, rect1(pThread->m_ptPosition,CSize(pThread->m_bmpRect.Width(),pThread->m_bmpRect.Height())); vector ::iterator iter, iterThis; vector *pThreadKilled=new vector ; EnterCriticalSection(&csCrash); if (WaitForSingleObject(pThread->m_hEventKill,0)!=WAIT_TIMEOUT) { LeaveCriticalSection(&csCrash); return false; } for(iter=CCarThread::m_Cars.begin();iter!=CCarThread::m_Cars.end();iter++) { if (*iter==pThread) iterThis=iter; else if (IntersectRect.IntersectRect(rect1,CRect((*iter)->m_ptPosition,CSize(pThread->m_bmpRect.Width(),pThread->m_bmpRect.Height() ) ))) { SetEvent((*iter)->m_hEventKill); pThreadKilled->push_back(*iter); bRetVal=true; } } if (bRetVal) { SetEvent((*iterThis)->m_hEventKill); pThreadKilled->push_back(*iterThis); } LeaveCriticalSection(&csCrash); if (bRetVal) *ppThreadKilled=pThreadKilled; else delete pThreadKilled; return bRetVal; } void CCarThread::Initialize() { m_bmpCars[0].LoadBitmap(IDB_BITMAPCARDOWN); m_bmpCars[1].LoadBitmap(IDB_BITMAPCARUP); m_bmpCars[2].LoadBitmap(IDB_BITMAPCARRIGHT); m_bmpCars[3].LoadBitmap(IDB_BITMAPCARLEFT); m_bmpCars[4].LoadBitmap(IDB_BITMAPCARLEFTUP); m_bmpCars[5].LoadBitmap(IDB_BITMAPCARRIGHTUP); m_bmpCars[6].LoadBitmap(IDB_BITMAPLEFTDOWN); m_bmpCars[7].LoadBitmap(IDB_BITMAPRIGHTDOWN); InitializeCriticalSection(&CCarThread::cs); InitializeCriticalSection(&CCarThread::csCrash); }