www.pudn.com > GameEngine_src.rar > CPictureGroup.cpp


#include "CPictureGroup.h" 
#include "BaseUtil.h" 
#include "normal.h" 
#include "CMap.h" 
#include  
 
extern PEASYDRAW g_pEasyDraw; 
extern CMap		theMap; 
 
struct EPGFILEHEADER 
{ 
	DWORD epgType;						//文件类型EPG 
	DWORD epgNumPicture;				//文件中所含图片总数 
	DWORD epgNumShadow;					//阴影图片数(为0则没有阴影) 
	DWORD epgNumDirection;				//方向数 
	DWORD epgNumHoldCell;				//占据的CELL总数 
	DWORD epgNumBaseCell;				//基CELL数,1或4 
	DWORD epgDelayTime;					//动画间隔时间 
	DWORD epgOffsetHoldCell;			//从文件头到占位CELL数据的偏移 
}; 
 
const DWORD EPG = 'EPG'; 
 
 
//*********************************************CPictureGroup类定义**************************************************** 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
CPictureGroup::CPictureGroup() 
{ 
	m_DelayTime = 0; 
	m_Direction = 1; 
} 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
CPictureGroup::~CPictureGroup() 
{ 
	Free(); 
} 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::FreeSurface() 
{ 
	for ( int i = 0; i < m_SurfaceArray.GetLength(); ++i ) 
		g_pEasyDraw->DeleteSurface( m_SurfaceArray[i] ); 
 
	m_SurfaceArray.Free(); 
} 
 
 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
bool CPictureGroup::Init() 
{ 
	m_DelayTime = 0; 
	m_Direction = 1; 
	bool b = m_SurfaceArray.Init( 64 ); 
	b &= m_BaseOffsetArray.Init( 64 ); 
	return b; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::Free() 
{ 
	FreeSurface(); 
	m_BaseOffsetArray.Free(); 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::Clear() 
{ 
	FreeSurface(); 
	m_SurfaceArray.Clear(); 
	m_BaseOffsetArray.Clear(); 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::GetRenderPoint( int frame, const POINT &base, POINT &render ) 
{ 
	render.x = base.x - m_BaseOffsetArray[frame].x; 
	render.y = base.y - m_BaseOffsetArray[frame].y; 
} 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::UpdateFrame( int &frame, unsigned int &LastTick ) 
{ 
	unsigned int this_tick = timeGetTime(); 
	if ( this_tick - LastTick >= m_DelayTime ) 
	{ 
		LastTick = this_tick; 
		frame++; 
		frame = frame % m_SurfaceArray.GetLength(); 
	} 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::GetRect( int frame, const POINT &base, RECT &rc ) 
{ 
	rc.left = base.x - m_BaseOffsetArray[frame].x; 
	rc.top = base.y - m_BaseOffsetArray[frame].y; 
	rc.right = rc.left + m_SurfaceArray[frame]->GetWidth(); 
	rc.bottom  = rc.top + m_SurfaceArray[frame]->GetHeight();  
} 
 
//////////////////////////////////////////////////////////////////////// 
//更新活动精灵, 包括更新精灵的当前帧, 计时器, 包围矩形框 
//////////////////////////////////////////////////////////////////////// 
int CPictureGroup::UpdateAliveSprite( bool bNextFrame, int &frame, int direction, const POINT &base, POINT &render, RECT &rc ) 
{ 
	//确定方向,注意精灵逻辑方向都是八方向的,而实际动画有四或八方向 
	if ( m_Direction == 4 ) 
		direction = ( direction - 1 ) / 2; 
	else 
		direction -= 1; 
 
	if ( bNextFrame ) 
	{ 
		frame++; 
		frame = frame % m_FramePerDirection; 
	} 
 
	int pg_frame = direction * m_FramePerDirection + frame; 
 
	rc.left = base.x - m_BaseOffsetArray[pg_frame].x; 
	rc.top = base.y - m_BaseOffsetArray[pg_frame].y; 
	rc.right = rc.left + m_SurfaceArray[pg_frame]->GetWidth(); 
	rc.bottom  = rc.top + m_SurfaceArray[pg_frame]->GetHeight(); 
 
	render.x = rc.left; 
	render.y = rc.top; 
	theMap.MapToClient( render ); 
 
	return pg_frame; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//更新静态精灵, 包括更新精灵的当前帧, 计时器, 包围矩形框 
//与活动精灵不同的是,这里不用转换方向和帧,即逻辑帧==实际帧 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::UpdateStaticSprite( int &frame, unsigned int &LastTick, 
									  const POINT &base, POINT &render, RECT &rc ) 
{ 
	unsigned int this_tick = timeGetTime(); 
	if ( this_tick - LastTick >= m_DelayTime ) 
	{ 
		LastTick = this_tick; 
		frame++; 
		frame = frame % m_SurfaceArray.GetLength(); 
	} 
 
	rc.left = base.x - m_BaseOffsetArray[frame].x; 
	rc.top = base.y - m_BaseOffsetArray[frame].y; 
	rc.right = rc.left + m_SurfaceArray[frame]->GetWidth(); 
	rc.bottom  = rc.top + m_SurfaceArray[frame]->GetHeight(); 
 
	render.x = rc.left; 
	render.y = rc.top; 
	theMap.MapToClient( render ); 
} 
 
//////////////////////////////////////////////////////////////////////// 
//更新天空或地面魔法精灵 
//////////////////////////////////////////////////////////////////////// 
int CPictureGroup::UpdateMagicSprite( bool bNextFrame, int &frame, const POINT &base, POINT &render, RECT &rc ) 
{ 
	if ( bNextFrame ) 
	{ 
		frame++; 
		frame = frame % m_SurfaceArray.GetLength(); 
	} 
	rc.left = base.x - m_BaseOffsetArray[frame].x; 
	rc.top = base.y - m_BaseOffsetArray[frame].y; 
	rc.right = rc.left + m_SurfaceArray[frame]->GetWidth(); 
	rc.bottom  = rc.top + m_SurfaceArray[frame]->GetHeight(); 
 
	render.x = rc.left; 
	render.y = rc.top; 
	theMap.MapToClient( render ); 
	return frame; 
} 
 
//////////////////////////////////////////////////////////////////////// 
//frame是动画的实际帧,不是逻辑的帧 
// x_client, y_client 是窗口工作区的坐标 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::DrawFrame( int frame, int x_client, int y_client ) 
{ 
	m_SurfaceArray[frame]->DrawAutoClip( x_client, y_client );  
} 
 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::DrawShadow( int frame, const POINT &base ) 
{ 
	POINT render; 
	render.x = base.x - m_BaseOffsetArray[frame].x; 
	render.y = base.y - m_BaseOffsetArray[frame].y; 
 
 
	theMap.MapToClient( render ); 
	m_SurfaceArray[frame]->DrawAlphaShadow( render.x, render.y ); 
} 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::DrawFrame( int frame, const POINT &base ) 
{ 
	POINT render; 
	render.x = base.x - m_BaseOffsetArray[frame].x; 
	render.y = base.y - m_BaseOffsetArray[frame].y; 
 
	theMap.MapToClient( render ); 
	m_SurfaceArray[frame]->DrawAutoClip( render.x, render.y ); 
} 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
void CPictureGroup::DrawContour( int frame, int x, int y ) 
{ 
	m_SurfaceArray[frame]->DrawContour( x, y ); 
} 
 
//////////////////////////////////////////////////////////////////////// 
// 
//////////////////////////////////////////////////////////////////////// 
bool CPictureGroup::LoadEPG( char *filename, bool isFromFile, CPictureGroup *pSPG, CELL **ppCell, int *NumHoldCell ) 
{ 
	Free(); 
 
	if ( isFromFile ) 
	{ 
		//open file 
		FILE *fp = fopen( filename, "rb" ); 
		if ( fp == 0 ) 
			return false; 
 
		//read file header; 
		EPGFILEHEADER efh; 
		fread( &efh, sizeof(efh), 1, fp ); 
		if ( efh.epgType != EPG ) 
		{ 
			fclose(fp); 
			return false; 
		} 
 
		m_DelayTime = efh.epgDelayTime; 
		m_Direction = efh.epgNumDirection; 
 
		//load surface 
		int offset; 
 
		for ( int i = 0; i < efh.epgNumPicture; ++i ) 
		{ 
			fseek( fp, sizeof(efh) + i * 4, SEEK_SET ); 
			fread( &offset, 4, 1, fp ); 
 
			POINT base; 
			PSURFACE surf = g_pEasyDraw->CreateSurfaceFromEPG( fp, offset, &base ); 
			m_SurfaceArray.Add( surf ); 
			m_BaseOffsetArray.Add( base ); 
		} 
		//num fo frame per directon 
		m_FramePerDirection = m_SurfaceArray.GetLength() / m_Direction; 
 
		//load shadow 
		if ( pSPG != 0 ) 
		{ 
			pSPG->Free(); 
			pSPG->m_DelayTime = efh.epgDelayTime; 
			pSPG->m_Direction = efh.epgNumDirection; 
 
			for ( int j = 0; j < efh.epgNumShadow; ++j ) 
			{ 
				fseek( fp, sizeof(efh) + (i + j) * 4, SEEK_SET ); 
				fread( &offset, 4, 1, fp ); 
 
				POINT base; 
				PSURFACE surf = g_pEasyDraw->NewSurface(); 
 
				debug_assert( surf != NULL ); 
				debug_assert( efh.epgNumPicture == efh.epgNumShadow ); 
 
				surf->CreateEcpSurfaceHelp( fp, offset, &base, true ); 
				pSPG->m_SurfaceArray.Add( surf ); 
				pSPG->m_BaseOffsetArray.Add( base ); 
			} 
 
			pSPG->m_FramePerDirection = pSPG->m_SurfaceArray.GetLength() / pSPG->m_Direction; 
		} 
 
 
		if ( ppCell != 0 && efh.epgNumHoldCell > 0 ) 
		{ 
			*ppCell = new CELL[ efh.epgNumHoldCell ]; 
			fseek( fp, efh.epgOffsetHoldCell, SEEK_SET ); 
			fread( *ppCell, efh.epgNumHoldCell * sizeof(CELL), 1, fp ); 
		} 
 
		if ( NumHoldCell != 0 ) 
			*NumHoldCell = efh.epgNumHoldCell; 
 
		fclose(fp); 
	} 
	else		//load it from memory 
	{ 
		BYTE *buf = (BYTE *)filename; 
		BYTE *old_buf = buf; 
 
		EPGFILEHEADER efh; 
		efh = READ_MEMORY( buf, EPGFILEHEADER ); 
		buf += sizeof(EPGFILEHEADER); 
 
		m_DelayTime = efh.epgDelayTime; 
		m_Direction = efh.epgNumDirection; 
 
		if ( efh.epgType != EPG ) 
			return false; 
 
		//load surface 
		int offset; 
		for ( int i = 0; i < efh.epgNumPicture; ++i ) 
		{ 
			buf = old_buf + sizeof(EPGFILEHEADER) + i * 4; 
			offset = READ_MEMORY( buf, int ); 
			buf = old_buf + offset; 
 
			POINT base; 
			PSURFACE surf = g_pEasyDraw->NewSurface(); 
			surf->CreateEcpSurfaceFromMemory( buf, false, &base ); 
 
			m_SurfaceArray.Add( surf ); 
			m_BaseOffsetArray.Add( base ); 
		} 
		m_FramePerDirection = m_SurfaceArray.GetLength() / m_Direction; 
 
		//load shadow 
		if ( pSPG != 0 ) 
		{ 
			pSPG->FreeSurface(); 
			pSPG->m_DelayTime = efh.epgDelayTime; 
			pSPG->m_Direction = efh.epgNumDirection; 
 
			for ( int j = 0; j < efh.epgNumShadow; ++j ) 
			{ 
				buf = old_buf + sizeof(EPGFILEHEADER) + (i+j) * 4; 
				offset = READ_MEMORY( buf, int ); 
				buf = old_buf + offset; 
 
				POINT base; 
				PSURFACE surf = g_pEasyDraw->NewSurface(); 
				 
#ifdef ALPHA_SHADOW 
			surf->CreateEcpSurfaceFromMemory( buf, false, &base ); 
#else 
			surf->LoadEcpShadowFromMemory( buf, &base ); 
#endif 
				pSPG->m_SurfaceArray.Add( surf ); 
				pSPG->m_BaseOffsetArray.Add( base ); 
			} 
			pSPG->m_FramePerDirection = pSPG->m_SurfaceArray.GetLength() / pSPG->m_Direction; 
		} 
 
		//load cell 
		if ( ppCell != 0 && efh.epgNumHoldCell != 0 ) 
		{ 
			*ppCell = new CELL[ efh.epgNumHoldCell ]; 
			buf = (BYTE *)filename + efh.epgOffsetHoldCell; 
			memcpy( *ppCell, buf, efh.epgNumHoldCell * sizeof(CELL) ); 
		} 
 
		if ( NumHoldCell != 0 ) 
			*NumHoldCell = efh.epgNumHoldCell; 
	} 
	return true; 
} 
 
 
//////////////////////////////////////////////////////////////////////// 
//此处已改成求最高的高度 
//////////////////////////////////////////////////////////////////////// 
int CPictureGroup::GetMaxHeight() 
{ 
	int result = 0; 
	for ( int i = 0; i < m_BaseOffsetArray.GetLength(); ++i ) 
		result = ( result > m_BaseOffsetArray[i].y ? result : m_BaseOffsetArray[i].y ); 
 
	return result; 
}