⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddcompo.cpp

📁 赤壁之战(游戏原码)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	return rcDest;
}

// 应用程序在显示鼠标光标时应该使用此函数
// draw cursor to front surface
// bForce		:	TRUE for force draw the cursor, 
//					usually used after changing the state or frame of a cursor
// bForce		:	TRUE for force drawing
// return value	:	TRUE for has drew
BOOL CDDCursor::Draw( BOOL bForce/*=FALSE*/ )
{
	//if( !m_bCreatedC )	return FALSE;
	Assert( m_bCreatedC == TRUE );
	if( !m_bShow	)	return FALSE;

	POINT ptPosOld;
	RECT rcDest1, rcDest2;
	RECT rcSrcFile;

	ptPosOld.x = m_ptPos.x;
	ptPosOld.y = m_ptPos.y;

	// get old destination rectangle
	rcDest1 = GetRect();

	// get current cursor position
	GetCursorPos( &m_ptPos );

	// test if needn't draw
	if( m_ptPos.x == ptPosOld.x && m_ptPos.y == ptPosOld.y && !bForce )
		return FALSE;	// needn't 

	// get current destination rectangle
	rcDest2 = GetRect();

	// get source rectangle of the bitmap file
	rcSrcFile.left = m_nFrame*m_szSize.cx;
	rcSrcFile.top = m_nState*m_szSize.cy;
	rcSrcFile.right = rcSrcFile.left + m_szSize.cx;
	rcSrcFile.bottom = rcSrcFile.top + m_szSize.cy;

	// calculate if the two rectangles cross
	POINT ptDest;	// destination position
	RECT rcSrc;		// source rectangle

	// if they cross
	if( IntersectRect( &rcSrc, &rcDest1, &rcDest2 ) )
	{	// draw it together
		RECT rcSrcUni;	// intersection of the two rectangles
		UnionRect( &rcSrcUni, &rcDest1, &rcDest2 );
		// step 1:	draw back buffer to mix buffer
		IntersectRect( &rcSrc, &rcSrcUni, &m_rcRange );
		ptDest.x = rcSrc.left - rcSrcUni.left;
		ptDest.y = rcSrc.top - rcSrcUni.top;
		m_lpMixBuffer->BltSurface( ptDest.x, ptDest.y, DD_GetBackBuffer(), &rcSrc, DDBLTFAST_NOCOLORKEY );
		// step 2:	draw cursor to mix buffer in new position
		ptDest.x = rcDest2.left - rcSrcUni.left;
		ptDest.y = rcDest2.top - rcSrcUni.top;
		m_lpMixBuffer->BltSurface( ptDest.x, ptDest.y, GetSurface(), &rcSrcFile, GetDrawFlag() );
		// step 3:	draw mix buffer to front buffer
		IntersectRect( &rcSrc, &rcSrcUni, &m_rcRange );
		ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
		rcSrc.left -= rcSrcUni.left, rcSrc.top -= rcSrcUni.top;
		rcSrc.right -= rcSrcUni.left;
		rcSrc.bottom -= rcSrcUni.top;
		m_lpMixBuffer->BltToFront( ptDest, &rcSrc );
	}
	else
	{	// draw it seperatly
		// step 1:	draw back buffer to front buffer in old position 
		IntersectRect( &rcSrc, &rcDest1, &m_rcRange );
		ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
		DD_BltSurface( ptDest, DD_GetFrontBuffer(), &rcSrc, DD_GetBackBuffer(), DDBLTFAST_NOCOLORKEY );
		// step 2:	draw cursor to front buffer in new position
		IntersectRect( &rcSrc, &rcDest2, &m_rcRange );
		ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
		rcSrcFile.left -= rcDest2.left - rcSrc.left;
		rcSrcFile.top -= rcDest2.top - rcSrc.top;
		rcSrcFile.right -= rcDest2.right - rcSrc.right ;
		rcSrcFile.bottom -= rcDest2.bottom - rcSrc.bottom;
		BltToFront( ptDest, &rcSrcFile );
	}

	// set last state and last frame
	m_nStateLast = m_nState, m_nFrameLast = m_nFrame;
	return TRUE;
}

// 应用程序在擦除鼠标光标时应该使用此函数
// erase cursor to front surface, doesn't change frame
// return value	:	TRUE for has erased
BOOL CDDCursor::Erase()
{
	Assert( m_bCreatedC == TRUE );
	if( !m_bShow	)	return FALSE;

	POINT ptPosOld;
	RECT rcDest1, rcDest2;
	RECT rcSrcFile;

	ptPosOld.x = m_ptPos.x;
	ptPosOld.y = m_ptPos.y;

	// get old destination rectangle
	rcDest1 = GetRect();

	// get current cursor position
	GetCursorPos( &m_ptPos );

	// get current destination rectangle
	rcDest2 = GetRect();

	// get source rectangle of the bitmap file
	rcSrcFile.left = m_nFrame*m_szSize.cx;
	rcSrcFile.top = m_nState*m_szSize.cy;
	rcSrcFile.right = rcSrcFile.left + m_szSize.cx;
	rcSrcFile.bottom = rcSrcFile.top + m_szSize.cy;

	// calculate if the two rectangles cross
	POINT ptDest;	// destination position
	RECT rcSrc;		// source rectangle

	// if they cross
	if( IntersectRect( &rcSrc, &rcDest1, &rcDest2 ) )
	{	// draw it together
		RECT rcSrcUni;	// intersection of the two rectangles
		UnionRect( &rcSrcUni, &rcDest1, &rcDest2 );
		// step 1:	draw back buffer to mix buffer
		IntersectRect( &rcSrc, &rcSrcUni, &m_rcRange );
		ptDest.x = rcSrc.left - rcSrcUni.left;
		ptDest.y = rcSrc.top - rcSrcUni.top;
		m_lpMixBuffer->BltSurface( ptDest.x, ptDest.y, DD_GetBackBuffer(), &rcSrc, DDBLTFAST_NOCOLORKEY );
		// step 2:	draw cursor to mix buffer in new position
//		ptDest.x = rcDest2.left - rcSrcUni.left;
//		ptDest.y = rcDest2.top - rcSrcUni.top;
//		m_lpMixBuffer->BltSurface( ptDest.x, ptDest.y, GetSurface(), &rcSrcFile, GetDrawFlag() );
		// step 3:	draw mix buffer to front buffer
		IntersectRect( &rcSrc, &rcSrcUni, &m_rcRange );
		ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
		rcSrc.left -= rcSrcUni.left, rcSrc.top -= rcSrcUni.top;
		rcSrc.right -= rcSrcUni.left;
		rcSrc.bottom -= rcSrcUni.top;
		m_lpMixBuffer->BltToFront( ptDest, &rcSrc );
	}
	else
	{	// draw it seperatly
		// step 1:	draw back buffer to front buffer in old position 
		IntersectRect( &rcSrc, &rcDest1, &m_rcRange );
		ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
		DD_BltSurface( ptDest, DD_GetFrontBuffer(), &rcSrc, DD_GetBackBuffer(), DDBLTFAST_NOCOLORKEY );
		// step 2:	draw cursor to front buffer in new position
//		IntersectRect( &rcSrc, &rcDest2, &m_rcRange );
//		ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
//		rcSrcFile.left -= rcDest2.left - rcSrc.left;
//		rcSrcFile.top -= rcDest2.top - rcSrc.top;
//		rcSrcFile.right -= rcDest2.right - rcSrc.right ;
//		rcSrcFile.bottom -= rcDest2.bottom - rcSrc.bottom;
//		BltToFront( ptDest, &rcSrcFile );
	}

	// set last state and last frame
//	m_nStateLast = m_nState, m_nFrameLast = m_nFrame;
	return TRUE;
}

SIZE CURSOR_szSave;
// 把鼠标显示在背景面上(BackBuffer),特殊情况下使用
// 把背景面保存在m_lpMixBuffer中
// draw corsor to back buffer
// stores back ground to m_lpMixBuffer
// prcCut		:	只显示在此矩形区域内,if NULL则不操作
// return value	:	TRUE for has drew
BOOL CDDCursor::Draw2Back( CONST RECT *prcCut/* = NULL*/ )
{
	RECT rcDestOld = GetRect();
	RECT rcDest;
	RECT rcSrc;
	POINT ptDest;
	if( IntersectRect( &rcDest, &rcDestOld, prcCut ) )
	{
		// calc offset
		POINT ptTLOff, ptRBOff;
		ptTLOff.x = rcDestOld.left - rcDest.left;
		ptTLOff.y = rcDestOld.top - rcDest.top;
		ptRBOff.x = rcDestOld.right - rcDest.right;
		ptRBOff.y = rcDestOld.bottom - rcDest.bottom;
		
		// get source rectangle of the bitmap file
		rcSrc.left = m_nFrame*m_szSize.cx;
		rcSrc.top = m_nState*m_szSize.cy;
		rcSrc.right = rcSrc.left + m_szSize.cx - ptRBOff.x;
		rcSrc.bottom = rcSrc.top + m_szSize.cy - ptRBOff.y;
		rcSrc.left -= ptTLOff.x;
		rcSrc.top -= ptTLOff.y;

		// for backup back buffer to mix buffer
		ptDest.x = ptDest.y = 0;
		CURSOR_szSave.cx = rcDest.right - rcDest.left;	// save backup size
		CURSOR_szSave.cy = rcDest.bottom - rcDest.top;
		// rcDest as rcSrc
		DD_BltSurface( ptDest, m_lpMixBuffer->GetSurface(), &rcDest, DD_GetBackBuffer(), DDBLTFAST_NOCOLORKEY );

		// draw cursor to back buffer
		ptDest.x = rcDest.left, ptDest.y = rcDest.top;
		BltToBack( ptDest, &rcSrc );
	}
	return TRUE;
}

// 把保存的背景面(在m_lpMixBuffer中)放回背景
// restores from m_lpMixBuffer to back buffer
// prcCut		:	只显示在此矩形区域内,if NULL则不操作
// return value	:	TRUE for has drew
BOOL CDDCursor::Restore2Back( CONST RECT *prcCut/* = NULL*/ )
{
	RECT rcDestOld = GetRect();
	RECT rcDest;
	RECT rcSrc;
	if( IntersectRect( &rcDest, &rcDestOld, prcCut ) )
	{
		// get source rectangle of the bitmap file
		rcSrc.left = rcSrc.top = 0;
		rcSrc.right = CURSOR_szSave.cx;
		rcSrc.bottom = CURSOR_szSave.cy;

		POINT ptDest;
		ptDest.x = rcDest.left, ptDest.y = rcDest.top;
		m_lpMixBuffer->BltToBack( ptDest, &rcSrc );
	}
	return TRUE;
}


#ifdef	_CURSOR_OLD_VERSION_
// when draw sprite should draw cursor on it
// used only in DDCompo.cpp, do not use outside
// pRect1, pRect2	:	the new and old positoin of the sprite
// return value		:	if one rectangle is NULL, or did not draw, return FALSE
// Warning	:	A bug report here
//				Draw cursor on any sprite even if cursor is out of range
BOOL CDDCursor::drawSprite( CONST RECT *pRect1, CONST RECT *pRect2 )
{
	Assert( m_bCreatedC );

	// get cursor rectangle in screen
	RECT rcCursor = GetRect();

	// get source rectangle of the bitmap file
	RECT rcSrcFile;
	rcSrcFile.left = m_nFrame*m_szSize.cx;
	rcSrcFile.top = m_nState*m_szSize.cy;
	rcSrcFile.right = rcSrcFile.left + m_szSize.cx;
	rcSrcFile.bottom = rcSrcFile.top + m_szSize.cy;

	// get old destination rectangle
	RECT rcDest1;
	rcDest1.left = pRect1->left;
	rcDest1.top = pRect1->top;
	rcDest1.right = pRect1->right;
	rcDest1.bottom = pRect1->bottom;

	// get current destination rectangle
	RECT rcDest2;
	rcDest2.left = pRect2->left; 
	rcDest2.top = pRect2->top;
	rcDest2.right = pRect2->right;
	rcDest2.bottom = pRect2->bottom;

	// calculate if the two rectangles cross
	POINT ptDest;	// destination position
	RECT rcSrc;		// source rectangle

	// if they cross
	if( IntersectRect( &rcSrc, &rcDest1, &rcDest2 ) )
	{	// draw it together
		RECT rcSrcUni;	// intersection of the two rectangles
		UnionRect( &rcSrcUni, &rcDest1, &rcDest2 );
		// step 1:	draw back buffer to Sprite buffer
		if( !IntersectRect( &rcSrc, &rcSrcUni, &DDC_rcSpriteRange ) )
			return FALSE;
		ptDest.x = rcSrc.left - rcSrcUni.left;
		ptDest.y = rcSrc.top - rcSrcUni.top;
		m_lpSpriteBuffer->BltSurface( ptDest.x, ptDest.y, DD_GetBackBuffer(), &rcSrc, DDBLTFAST_NOCOLORKEY );
		// step 2:	draw cursor to Sprite buffer in new position
		IntersectRect( &rcSrc, &rcCursor, &rcSrcUni );
		ptDest.x = rcSrc.left - rcSrcUni.left;
		ptDest.y = rcSrc.top - rcSrcUni.top;

		rcSrc.left = rcSrcFile.left + rcSrc.left - rcCursor.left;
		rcSrc.top = rcSrcFile.top + rcSrc.top - rcCursor.top;
		rcSrc.right = rcSrcFile.right + rcSrc.right - rcCursor.right ;
		rcSrc.bottom = rcSrcFile.bottom + rcSrc.bottom - rcCursor.bottom;

		m_lpSpriteBuffer->BltSurface( ptDest.x, ptDest.y, GetSurface(), &rcSrc, GetDrawFlag() );
		// step 3:	draw Sprite buffer to front buffer
		if( !IntersectRect( &rcSrc, &rcSrcUni, &DDC_rcSpriteRange ) )
			return FALSE;
		ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
		rcSrc.left -= rcSrcUni.left, rcSrc.top -= rcSrcUni.top;
		rcSrc.right -= rcSrcUni.left;
		rcSrc.bottom -= rcSrcUni.top;
		m_lpSpriteBuffer->BltToFront( ptDest, &rcSrc );
	}
	else	// not fully tested
	{	// draw it seperatly
		// step 1:	draw back buffer to front buffer in old position 
		if( !IntersectRect( &rcSrc, &rcDest1, &DDC_rcSpriteRange ) )
			return FALSE;
		ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
		DD_BltSurface( ptDest, DD_GetFrontBuffer(), &rcSrc, DD_GetBackBuffer(), DDBLTFAST_NOCOLORKEY );
		// step 2:	draw back buffer to front buffer in new position
		if( !IntersectRect( &rcSrc, &rcDest2, &DDC_rcSpriteRange ) )
			return FALSE;
		ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
		DD_BltSurface( ptDest, DD_GetFrontBuffer(), &rcSrc, DD_GetBackBuffer(), DDBLTFAST_NOCOLORKEY );
		Assert( DDC_pCursor != NULL );
		DDC_pCursor->Draw( TRUE );
	}
	return TRUE;
}// end of drawSprite()
#endif	// _CURSOR_OLD_VERSION_
//////////////////////////////


// global functions for cursor
//////////////////////////////
// set the cursor as the current cursor
// pCursor	:	cursor pointer to be set, set to NULL if you don't need cursor at all
// return	:	TRUE if the cursor is not null now
BOOL CURSOR_Set( class CDDCursor *pCursor )
{
	//if( pCursor == NULL ) return FALSE;
	if( DDC_pCursor != NULL )
	{
		DDC_pCursor->Erase();
		DDC_pCursor->SetState(0);
	}
	DDC_pCursor = pCursor;
	return TRUE;
}

// get the current cursor
inline class CDDCursor *CURSOR_Get()
{
	return DDC_pCursor;
}

// animate cursor, should be called each cycle
inline void CURSOR_Animate()
{
	if( DDC_pCursor != NULL )
		DDC_pCursor->Animate();
}
//////////////////////////////
////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////
// display functions
//////////////////////////////
#ifdef	_CURSOR_OLD_VERSION_
// set sprite moving range
// rcRange		:	range for sprites to move
// return value	:	old range for sprites to move
RECT DDC_SetSpriteRange( RECT rcRange )
{
	RECT rcRangeOld;
	rcRangeOld.left = DDC_rcSpriteRange.left,
	rcRangeOld.top = DDC_rcSpriteRange.top,
	rcRangeOld.right = DDC_rcSpriteRange.right,
	rcRangeOld.bottom = DDC_rcSpriteRange.bottom;

	DDC_rcSpriteRange.left = rcRange.left,
	DDC_rcSpriteRange.top = rcRange.top,
	DDC_rcSpriteRange.right = rcRange.right,
	DDC_rcSpriteRange.bottom = rcRange.bottom;
	
	return rcRangeOld;
} // DDC_SetSpriteRange()
#endif	// _CURSOR_OLD_VERSION_

#ifdef	_CURSOR_OLD_VERSION_
// 应用程序在更新完sprites后应该调用此函数,而不是DD_UpdateScreen()
// this function will redraw cursor automatically
// 两个矩形一般为该sprite在旧位置上的矩形和新位置上的矩形
// update two rectangles from back buffer to front buffer
// if the two rectangles cross, it will combine it to a large rectangle,
// else	update two rectangles seperatly
// pRect1, pRect2	:	the two rectangles
// return value		:	if one is NULL, or do not draw, return FALSE
BOOL DDC_UpdateSprite( CONST RECT *pRect1, CONST RECT *pRect2 )
{
	// update whole screen from back buffer to front buffer
	if( pRect1 == NULL || pRect2 == NULL )
		return FALSE;

	// calculate if the two rectangles cross
	POINT ptDest;	// destination position
	RECT rcSrc;		// source rectangle

	// update cursor if need
	Assert( DDC_pCursor != NULL );
	RECT rcCursor = DDC_pCursor->GetRect();
	RECT rcDest;

	if( IntersectRect( &rcDest, pRect1, &rcCursor) ||
		IntersectRect( &rcDest, pRect2, &rcCursor) )
	{
		// should draw cursor on it
		return DDC_pCursor->drawSprite( pRect1, pRect2 );
	}
	else
	{
		// need not to draw cursor on it
		// if they cross
		if( IntersectRect( &rcSrc, pRect1, pRect2 ) )
		{	// draw it together
			RECT rcSrcUni;	// intersection of the two rectangles
			UnionRect( &rcSrcUni, pRect1, pRect2 );
			// step 1:	draw back buffer to front buffer
			if( !IntersectRect( &rcSrc, &rcSrcUni, &DDC_rcSpriteRange ) )
				return FALSE;
			ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
			DD_BltSurface( ptDest, DD_GetFrontBuffer(), &rcSrc, DD_GetBackBuffer(), DDBLTFAST_NOCOLORKEY );
		}
		else
		{	// draw it seperatly
			// step 1:	draw back buffer to front buffer in old position 
			if( !IntersectRect( &rcSrc, pRect1, &DDC_rcSpriteRange ) )
				return FALSE;
			ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
			DD_BltSurface( ptDest, DD_GetFrontBuffer(), &rcSrc, DD_GetBackBuffer(), DDBLTFAST_NOCOLORKEY );
			// step 2:	draw cursor to front buffer in new position
			if( !IntersectRect( &rcSrc, pRect2, &DDC_rcSpriteRange ) )
				return FALSE;
			ptDest.x = rcSrc.left, ptDest.y = rcSrc.top;
			DD_BltSurface( ptDest, DD_GetFrontBuffer(), &rcSrc, DD_GetBackBuffer(), DDBLTFAST_NOCOLORKEY );
		}
	}

	return TRUE;
} // DDC_UpdateSprite()
#endif	// _CURSOR_OLD_VERSION_

// when need update, should use this functions instead of DD_UpdateScreen() in DDAPI.h
// update only one rectangle of back buffer to front buffer
// pRect	:	rectangle to be update
void DDC_UpdateScreen( RECT *pRect/*=NULL*/ )
{
	if( DDC_pCursor != NULL )
		DDC_pCursor->Draw2Back( pRect );
	DD_UpdateScreen( pRect );
	if( DDC_pCursor != NULL )
		DDC_pCursor->Restore2Back( pRect );
}	// DDC_UpdateScreen()

#ifdef	_CURSOR_OLD_VERSION_
// set max size of sprites
// in order to take effect, you must call this function before CDDCursor::Load()
// szMax		:	max size of sprites
// return value	:	old max size of sprites
SIZE DDC_SetSpriteMaxSize( SIZE szMax )
{
	SIZE szMaxOld;
	szMaxOld.cx = DDC_szSpriteMax.cx;
	szMaxOld.cy = DDC_szSpriteMax.cy;
	DDC_szSpriteMax.cx = szMax.cx;
	DDC_szSpriteMax.cy = szMax.cy;
	return szMaxOld;
} // DDC_SetSpriteMaxSize()
#endif	// _CURSOR_OLD_VERSION_
//////////////////////////////

// sub-draw functions
//////////////////////////////
// draw rectangle on screen, by using DC
// pRect		:	rectangle to draw
// color		:	color to draw
// bFront		:	TRUE for draw it on front buffer
// return value	:	TRUE if succeeded
BOOL DDC_FrameRect( CONST RECT *pRect, COLORREF color, BOOL bFront/*=FALSE*/ )
{
	HDC hdc; 
	LPDIRECTDRAWSURFACE2 lpDDS=NULL;
	if( bFront )	lpDDS = DD_GetFrontBuffer();
	else			lpDDS = DD_GetBackBuffer();
	if( lpDDS->GetDC(&hdc) != DD_OK )
		return FALSE;

	HBRUSH hbr = CreateSolidBrush( color );
	FrameRect( hdc, pRect, hbr );
	DeleteObject( HBRUSH(hbr) );

	lpDDS->ReleaseDC( hdc );
	return TRUE;
}

// draw rectangle on one surface, by using DC
// pRect		:	rectangle to draw
// color		:	color to draw
// bFront		:	TRUE for draw it on front buffer
// return value	:	TRUE if succeeded
BOOL DDC_FrameRect( LPDIRECTDRAWSURFACE2 lpDDS, CONST RECT *pRect, COLORREF color )
{
	HDC hdc; 
	if( lpDDS->GetDC(&hdc) != DD_OK )
		return FALSE;

	HBRUSH hbr = CreateSolidBrush( color );
	FrameRect( hdc, pRect, hbr );
	DeleteObject( HBRUSH(hbr) );

	lpDDS->ReleaseDC( hdc );
	return TRUE;
}
//////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -