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; 
vector CCarThread::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); 
}